Python爬虫之xpath语法及案例使用

Python爬虫之xpath语法及案例使用

我们在写Python爬虫时,经常需要对网页提取信息,如果用传统正则表达去写会增加很多工作量,此时需要一种对数据解析的方法,也就是本章要介绍的Xpath表达式

Xpath是什么

XPath,全称 XML Path Language,即 XML 路径语言,它是一门在 XML 文档中查找信息的语言。最初是用来搜寻 XML 文档的,但同样适用于 HTML 文档的搜索。所以在做爬虫时完全可以使用 XPath 做相应的信息抽取。

XPath 的选择功能十分强大,它提供了非常简洁明了的路径选择表达式。另外,它还提供超过 100 个内置函数,用于字符串、数值、时间的匹配以及节点、序列的处理等,几乎所有想要定位的节点都可以用 XPath 来选取。

下面介绍实战中常用的几个知识点,详细也可以看W3C介绍:https://www.w3school.com.cn/xpath/index.asp

Xpath语法介绍

路径常用规则

表达式

描述

实例

nodename

选取此节点的所有子节点

xpath(‘//p’)

选取了p节点的所有子节点

/

从根节点选取

xpath(‘/p’)

从根节点上选取p节点

//

选取所有当前节点,不考虑位置

xpath(‘//p’)

选取所有的p节点

.

选取当前节点

xpath(‘./p’)

选取当前节点下的p节点

..

选取当前节点的父节点

xpath(‘..’)

回到上一个节点

@

选取属性

xpath(’//@calss’)

选取所有的class属性

谓语规则

谓语被嵌在方括号内,用来查找某个特定的节点或包含某个制定的值的节点

表达式

结果

xpath(‘/body/p[1]’)

选取body下的第一个p节点

xpath(‘/body/p[last()]’)

选取body下最后一个p节点

xpath(‘/body/p[last()-1]’)

选取body下倒数第二个p节点

xpath(‘/body/p[positon() ]’)

选取body下前两个p节点

xpath(‘/body/p[@class]’)

选取body下带有class属性的p节点

xpath(‘/body/p[@class=”main”]’)

选取body下class属性为main的p节点

xpath(‘/body/p[price>35.00]’)

选取body下price元素值大于35的p节点

通配符

通配符来选取未知的XML元素

表达式

结果

xpath(’/p/*’)

选取p下的所有子节点

xpath(‘/p[@*]’)

选取所有带属性的p节点

取多个路径

使用“|”运算符可以选取多个路径

表达式

结果

xpath(‘//p|//table’)

选取所有的p和table节点

功能函数

使用功能函数能够更好的进行模糊搜索

函数

用法

解释

starts-with

xpath(‘//p[starts-with(@id,”ma”)]’)

选取id值以ma开头的p节点

contains

xpath(‘//p[contains(@id,”ma”)]’)

选取id值包含ma的p节点

and

xpath(‘//p[contains(@id,”ma”) and contains(@id,”in”)]’)

选取id值包含ma和in的p节点

text()

xpath(‘//p[contains(text(),”ma”)]’)

选取节点文本包含ma的p节点

语法熟悉

下面举一段HTML文本进行语法热身,代码如下

#!/usr/bin/env python# -*- coding: utf-8 -*-# time: 2022/8/8 0:05# author: gangtie# email: 648403020@qq.comfrom lxml import etreetext = ”’

  • first item
  • second item
  • third item
  • fourth item
  • fifth item

”’# 调用HTML类进行初始化,这样就成功构造了一个XPath解析对象。# 利用etree.HTML解析字符串page = etree.HTML(text) print(type(page))

可以看到打印结果已经变成XML元素:

字符串转换HTML

字符串利用etree.HTML解析成html格式:

print(etree.tostring(page,encoding=’utf-8′).decode(‘utf-8’))“`

  • first item
  • second item
  • third item
  • fourth item
  • fifth item

Process finished with exit code 0“`

经过处理可以看到缺失的

也自动补全了,还自动添加html、body节点。

查找绝对路径

通过绝对路径获取a标签的所有内容

a = page.xpath(“/html/body/p/ul/li/a”)for i in a: print(i.text)“`first itemsecond itemthird itemNonefifth item“`

查找相对路径(常用)

查找所有li标签下的a标签内容

html = etree.HTML(text)a = html.xpath(“//a/text()”)print(a)“`[‘first item’, ‘second item’, ‘third item’, ‘fifth item’]“`

当前标签节点

. 表示选取当前标签的节点。

我们先定位 ul 元素节点得到一个列表,打印当前节点列表得到第一个 ul,接着打印 ul 节点的子节点 li,text()输出。

page = etree.HTML(text)ul = page.xpath(“//ul”)print(ul)print(ul[0].xpath(“.”))print(ul[0].xpath(“./li”))print(ul[0].xpath(“./li/a/text()”))“`[][][, , , , ][‘first item’, ‘second item’, ‘third item’, ‘fifth item’]“`

父节点

.. 表示选取当前标签的父节点。

可以看到得到ul的上一级p

page = etree.HTML(text)ul = page.xpath(“//ul”)print(ul[0].xpath(“.”))print(ul[0].xpath(“..”))“`[][]“`

属性匹配

匹配时可以用@符号进行属性过滤查找a标签下属性href值为link2.html的内容

html = etree.HTML(text)a = html.xpath(“//a[@href=’link2.html’]/text()”)print(a)“`[‘second item’]“`

函数

last():查找最后一个li标签里的a标签的href属性

html = etree.HTML(text)a = html.xpath(“//li[last()]/a/text()”)print(a)“`[‘fifth item’]“`

contains:查找a标签中属性href包含link的节点,并文本输出

html = etree.HTML(text)a = html.xpath(“//a[contains(@href, ‘link’)]/text()”)print(a)“`[‘first item’, ‘second item’, ‘third item’, ‘fifth item’]“`

实战案例

上面说完基本用法,接下来做几个实战案例练练手。

案例一:豆瓣读书

# -*-coding:utf8 -*-# 1.请求并提取需要的字段# 2.保存需要的数据import requestsfrom lxml import etreeclass DoubanBook(): def __init__(self): self.base_url = ‘https://book.douban.com/chart?subcat=all&icn=index-topchart-popular’ self.headers = { ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ‘ ‘Chrome/104.0.0.0 Safari/537.36’ } # 请求并提取需要的字段 def crawl(self): res = requests.get(self.base_url, headers=self.headers) lis = etree.HTML(res.text).xpath(‘//*[@id=”content”]/p/p[1]/ul/li’) # print(type(lis)) books = [] for li in lis: # print(etree.tostring(li,encoding=’utf-8′).decode(‘utf-8′)) # print(“==================================================”) title = “”.join(li.xpath(“.//a[@class=’fleft’]/text()”)) score = “”.join(li.xpath(“.//p[@class=’clearfix w250′]/span[2]/text()”)) # list输出带有[‘ 刘瑜 / 2022-4 / 广西师范大学出版社 / 82.00元 / 精装 ‘] publishing = “”.join(li.xpath(“.//p[@class=’subject-abstract color-gray’]/text()”)).strip() book = { ‘title’: title, ‘score’: score, ‘publishing’: publishing, } books.append(book) self.save_data(books) def save_data(self, datas): with open(‘books.txt’, ‘w’, encoding=’utf-8′) as f: f.write(str(datas)) def run(self): self.crawl()if __name__ == ‘__main__’: DoubanBook().run()

案例二:彼岸图片下载

#!/usr/bin/env python# -*- coding: utf-8 -*-# author: 钢铁知识库# email: 648403020@qq.comimport osimport requestsfrom lxml import etree# 彼岸图片下载class BiAn(): def __init__(self): self.url = ‘https://pic.netbian.com’ self.headers = { ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ‘ ‘Chrome/104.0.0.0 Safari/537.36’, ‘cookie’: ‘__yjs_duid=1_cb922eedbda97280755010e53b2caca41659183144320; Hm_lvt_c59f2e992a863c2744e1ba985abaea6c=1649863747,1660203266; zkhanecookieclassrecord=%2C23%2C54%2C55%2C66%2C60%2C; Hm_lpvt_c59f2e992a863c2744e1ba985abaea6c=1660207771; yjs_js_security_passport=1225f36e8501b4d95592e5e7d5202f4081149e51_1630209607_js’ } # 如果目录不存在会报错 if not os.path.exists(‘BianPicture’): os.mkdir(‘BianPicture’) # 请求拿到ul列表 def crawl(self): res = requests.get(self.url, headers=self.headers) res.encoding = ‘gbk’ uls = etree.HTML(res.text).xpath(‘//p[@class=”slist”]/ul[@class=”clearfix”]/li’) # print(etree.tostring(uls,encoding=’gbk’).decode(‘gbk’)) # 循环拿到图片名、图片地址,拼接请求再次下载到图片 for ul in uls: img_name = ul.xpath(‘.//a/b/text()’)[0] img_src = ul.xpath(‘.//a/span/img/@src’)[0] # print(img_name + img_src) img_url = self.url + img_src # 拼接后下载图片,转义Bytes img_res = requests.get(img_url, headers=self.headers).content img_path = “BianPicture/” + img_name + “.jpg” data = { ‘img_res’: img_res, ‘img_path’: img_path } self.save_data(data) # 数据保存逻辑 def save_data(self, data): with open(data[‘img_path’], ‘wb’) as f: f.write(data[‘img_res’]) # print(data) def run(self): self.crawl()if __name__ == ‘__main__’: BiAn().run()

案例三:全国城市名称爬取

#!/usr/bin/env python# -*- coding: utf-8 -*-# author: 钢铁知识库# email: 648403020@qq.comimport osimport requestsfrom lxml import etreeclass CityName(): def __init__(self): self.url = ‘https://www.aqistudy.cn/historydata/’ self.headers = { ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36’ } # 判断目录是否存在 if not os.path.exists(‘city_project’): os.mkdir(‘city_project’) def crawl(self): res = requests.get(url=self.url, headers=self.headers).text uls = etree.HTML(res).xpath(‘//p[@class=”all”]/p[2]/ul/p[2]/li’) all_city_name = list() for ul in uls: city_name = ul.xpath(‘.//a/text()’)[0] # print(type(city_name)) all_city_name.append(city_name) self.save_data(all_city_name) def save_data(self, data): with open(‘./city_project/city.txt’, ‘w’) as f: f.write(str(data)) def run(self): self.crawl()if __name__ == ‘__main__’: CityName().run()

xpath使用工具

chrome生成XPath表达式

经常使用chome的朋友都应该知道这功能,在 审查 状态下(快捷键ctrl+shift+i,F12),定位到元素(快捷键ctrl+shift+c) ,在Elements选项卡中,右键元素 Copy->Copy xpath,就能得到该元素的xpath了

Xpath Helper插件

为chome装上XPath Helper就可以很轻松的检验自己的xpath是否正确了。安装插件需要特别上网,安装好插件后,在chrome右上角点插件的图标,调出插件的黑色界面,编辑好xpath表达式,表达式选中的元素被标记为黄色

—- 钢铁侠的知识库 2022.08.15

结语:

以上就是利用XPath的所有用法,从常用语法,到案例练习都走了一遍。下一章 钢铁知识库 会继续介绍另一种好用的解析框架,Beautiful Soup

文章来自https://www.cnblogs.com/jiba/p/16589856.html

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年8月17日
下一篇 2022年8月17日

相关推荐

  • SQL的基本函数

    【二】SQL的基本函数 2.1 关系型数据库SQL命令类别 数据操纵语言:DML: select; insert; delete; update; merge. 数据定义语言:DD…

    2022年6月24日
  • web开发之-前端css(6)

    css除了用来设置样式外,还可以设置各种特效,我们常用到的特效有两种:过渡和动画,过渡需要响应事件更改样式属性来触发,而动画,不需要响应事件就可以执行,下面我们看下,这两种实现的方…

    2022年6月14日
  • 硒对心脏病的作用 硒是预防心脏病、抵抗癌症的重要元素!吃哪些食物能补充?告诉您

    这些年,凡是能跟“硒”扯上点关系的,都卖得贼贵。什么富含硒的青菜啦、硒含量高的大米啦等等,都远超普通食品数十倍的价格。 那么硒真的那么重要吗?还真的非常重要。硒是人体必不可少的微量…

    2022年6月29日
  • springboot实现简单的上传下载

    eneity:/** * 主键 */ @Id @Column(length = 50) private String id= UUIDHelper.NewID(); /** * 上…

    2022年6月17日
  • “羊了个羊”,离谱又上头!100W人沦陷

    世界的尽头,是羊了个羊。 以前黑马认为,对付失眠最好的办法是数羊,数着数着就困了。 现在黑马认为,对付失眠最好的办法是打开《羊了个羊》,恭喜大家,喜提通宵。 近日,有款神奇的微信小…

    2022年9月18日
  • Python Queue 入门

    Queue 简介 Queue 叫队列,是数据结构中的一种,基本上所有成熟的编程语言都内置了对 Queue 的支持。 Python 中的 Queue 模块实现了多生产者和多消费者模型…

    2022年7月10日
  • 原神无相之草怎么打?原神无相之草打法攻略

    原神无相之草打法是什么?原神无相之草怎么打?无相之草是今天更新后新增加的boss,很多玩家不知道应该带什么属性,下面就由小编带来原神无相之草打法攻略,感兴趣的玩家赶紧前来围观吧! …

    2022年11月4日
  • 意式轻奢风格餐厅 低调又不失奢华案例分享

    #头号周刊# 来自Turri的Vogue 餐厅系列从高端包袋和行李箱中汲取灵感的珍贵元素,并将所有现代细节都与手工制作的饰面完美融合。 Vogue系列的长方形桌子散发着魅力和奢华的…

    2022年8月30日
  • vlookup函数的使用方法教程注意事项!

    vlookup函数想学好并不容易,需要不断的学习和使用,让大脑记住这些公式。 Hello,大家好,这一章我们开始学习函数,函数可以说是excel的精髓,它们能够帮助我们快速的处理数…

    2022年8月13日
  • 彩票的属性你真的知道吗?

    彩票以小博大属于一种合法的赌博行为,故而和其它赌博行为并称博彩业。 彩票在国外叫博彩。彩票对国家来说是募集资金的一种渠道。彩票对于有理智的老百姓来说,是一种娱乐。每期买几注,花几块…

    2022年7月13日

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息