python爬虫之xpath语法及案例使用 | 乐文库-凯发k8官网下载客户端
python爬虫之xpath语法及案例使用
—- 钢铁知识库 2022.08.15
我们在写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(‘//div’)选取了div节点的所有子节点/从根节点选取xpath(‘/div’)从根节点上选取div节点//选取所有当前节点,不考虑位置xpath(‘//div’)选取所有的div节点.选取当前节点xpath(‘./div’)选取当前节点下的div节点…选取当前节点的父节点xpath(‘…’)回到上一个节点@选取属性xpath(‘//@calss’)选取所有的class属性谓语规则
谓语被嵌在方括号内,用来查找某个特定的节点或包含某个制定的值的节点
表达式结果xpath(‘/body/div[1]’)选取body下的第一个div节点xpath(‘/body/div[last()]’)选取body下最后一个div节点xpath(‘/body/div[last()-1]’)选取body下倒数第二个div节点xpath(‘/body/div[positon()❤️]’)选取body下前两个div节点xpath(‘/body/div[@class]’)选取body下带有class属性的div节点xpath(‘/body/div[@class=“main”]’)选取body下class属性为main的div节点xpath(‘/body/div[price>35.00]’)选取body下price元素值大于35的div节点通配符
通配符来选取未知的xml元素
表达式结果xpath(‘/div/*’)选取div下的所有子节点xpath(‘/div[@*]’)选取所有带属性的div节点取多个路径
使用“|”运算符可以选取多个路径
表达式结果xpath(‘//div|//table’)选取所有的div和table节点功能函数
使用功能函数能够更好的进行模糊搜索
函数用法解释starts-withxpath(‘//div[starts-with(@id,“ma”)]’)选取id值以ma开头的div节点containsxpath(‘//div[contains(@id,“ma”)]’)选取id值包含ma的div节点andxpath(‘//div[contains(@id,“ma”) and contains(@id,“in”)]’)选取id值包含ma和in的div节点text()xpath(‘//div[contains(text(),“ma”)]’)选取节点文本包含ma的div节点语法熟悉
下面举一段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/div/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的上一级div
page = etree.html(text)ul = page.xpath("//ul")print(ul[0].xpath("."))print(ul[0].xpath(".."))```[][]```
属性匹配
匹配时可以用@符号进行属性过滤 查找a标签下属性href值为https://blog.csdn.net/u011463397/article/details/link2.html的内容
html = etree.html(text)a = html.xpath("//a[@href='https://blog.csdn.net/u011463397/article/details/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"]/div/div[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输出带有['n 刘瑜 / 2022-4 / 广西师范大学出版社 / 82.00元 / 精装n '] 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=,23,54,55,66,60,; 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('//div[@]/ul[@]/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('//div[@]/div[2]/ul/div[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,觉得有用点赞加关注,就当你送了红包666
本文来自网络,不代表乐文库立场,如若转载,请注明出处:https://www.lewenku.com/?p=483390