目录
3.1.1 XPath的作用
解析网页,与正则表达式异曲同工
3.1.2 XPath使用前提
需要从lxml库导入etree模块,且xpath不能直接对字符串进行解析,需要构造解析对象。
这里以爬取Scrape | Movie中的电影名、种类、信息、剧情简介、分数为例(爬取目标如下图)。
代码解释
from lxml import etree
import requests
url = 'https://ssr1.scrape.center/detail/1'
response = requests.get(url)
content = response.content # 得到网页文本,为字符串
html = etree.HTML(content) # 使用HTML类将其初始化为XPath解析对象
title = html.xpath('//h2[@class="m-b-sm"]/text()') # 才可以使用xpath方法
print(title)
3.1.3 XPath的使用
(1)属性匹配和获取一个属性值节点的内容
html.path() 方法可以根据 () 中的规则,得到对应内容,返回列表。在 xpath 方法中,开头的 // 表示查询内容中所有的h2节点。其他常用规则如下图。
其之后的[ ]表示h2这个节点中的属性,@class即查询class这个属性=“ ”的节点,即属性匹配。
/text() 表示获取符合规则节点中的内容(参考上下文代码理解)。所以分析网页的html代码得到上面的规则,然后获取信息。
练习:获取种类、信息、剧情简介、分数
等等。
(2)属性多值匹配
例如:要获取分数 9.5。其中class中不只有score,难道全写上去?其实使用contains方法即可。
代码如下:
from lxml import etree
import requests
url = 'https://ssr1.scrape.center/detail/1'
response = requests.get(url)
content = response.content
html = etree.HTML(content)
title = html.xpath('//h2[@class="m-b-sm"]/text()')
categories = html.xpath('//div[@class="categories"]/button/span/text()')
info = html.xpath('//div[@class="m-v-sm info"]/span/text()')
drama = html.xpath('//div[@class="drama"]/p/text()')
score = html.xpath('//p[contains(@class, "score")]/text()')
print(title)
print(categories)
print(info)
print(drama)
print(score)
结果如下:
(3)获取<>中的内容
这里以获取下面文本中的href中的内容为例。
from lxml import etree
text = '''
<a data-v-7f856186="" href="/detail/11" class="name">
<h2 data-v-7f856186="" class="m-b-sm">V字仇杀队 - V for Vendetta</h2>
</a>
'''
html = etree.HTML(text)
result = html.xpath('//a/@href')
print(result)
# 输出:['/detail/11']
(4)多属性匹配
要获取text中的霸王别姬电影名。使用运算符即可。
from lxml import etree
text = '''
<h2 class="h2 m-b-sm" name="title">霸王别姬 - Farewell My Concubine</h2>
<h2 class="h2 m-b-sm">这个杀手不太冷 - Léon</h2>
<h2 name="title">这个杀手不太冷 - Léon</h2>
'''
html = etree.HTML(text)
result = html.xpath('//h2[contains(@class, "h2") and @name="title"]/text()')
print(result)
(5)运算符及其介绍
(6)按序选择
注:获得节点后,又可以对节点进行 .path 解析。若节点为最内层节点,想获取属性或者文本,应用 .path('./@class'),.path('./text()')等,具体参考上述常用规则。
3.1.4 使用 XPath 过程中的问题
(1) 遍历节点时,解析用 // 出现的问题
例如下方想要得到两个 a 节点中的 class 为 title 的节点中的内容:
from lxml import etree
text = '''
<a href="https://movie.douban.com/subject/1292052/" class="">
<span class="title">肖申克的救赎</span>
<span class="title"> / The Shawshank Redemption</span>
<span class="other"> / 月黑高飞(港) / 刺激1995(台)</span>
</a>
<a href="https://movie.douban.com/subject/1291546/" class="">
<span class="title">霸王别姬</span>
<span class="other"> / 再见,我的妾 / Farewell My Concubine</span>
</a>
'''
html = etree.HTML(text)
a_href = html.xpath('//a')
print(len(a_href))
print(a_href)
for a in a_href:
title1 = a.xpath('//span[@class="title"]/text()')
print(title1)
结果如下:
2
[<Element a at 0x1d08d8f0400>, <Element a at 0x1d091055540>]
['肖申克的救赎', '\xa0/\xa0The Shawshank Redemption', '霸王别姬']
['肖申克的救赎', '\xa0/\xa0The Shawshank Redemption', '霸王别姬']
发现结果相同,原来 // 直接选取了所有的 a 节点,换成 ./ 就是从当前节点往子节点解析。结果如下:
2
[<Element a at 0x235de3a1dc0>, <Element a at 0x235de3a2940>]
['肖申克的救赎', '\xa0/\xa0The Shawshank Redemption']
['霸王别姬']
出现的 \xa0 用 replace('\xa0', '') 函数替换即可。
本人新手,若有错误,欢迎指正;若有疑问,欢迎讨论。若文章对你有用,点个小赞鼓励一下,谢谢,一起加油吧!