进击的爬虫-002-xpath实现猫眼电影前100爬取

1.什么是XPath
XPATH路径语言, 查找信息的语言, 用来搜寻XML文档, 也适用于HTML
XPath 提供了简洁明了的路径选择表达式
超过100个内建函数
 
2.XPath常用规则
  1. nodename : 选取此节点的所有子节点
  2. / : 从当前节点选取直接子节点
  3. // : 从当前节点选取子孙节点
  4. . : 选取当前节点
  5. .. : 选取当前节点的父节点
  6. @ : 选取属性
3. 使用
3.1安装lxml库
3.2 基本用法:
from lxml import etree #从lxml 导入etree模块 text = '''html 文档 ''' #声明 HTML文本 html = etree.HTML(text) #调用HTML类, 进行初始化, 构造了一个XPath解析队形, 可以自动修正HTML文本 result = etree.tostring(html) # 调用tostring() 方法即可输出修正后的HTML代码, 结果是bytes类型的, print(result.decode('utf-8')) #利用decode() 方法将其转化成str类型
还可以直接读取文本文件进行解析
html = etree.parse('猫眼.html',etree.HTMLParser()) ret = etree.tostring(html) print(ret.decode('utf-8'))
3.3 找到所有节点
我们一般都会用 // 开头的XPath来选取所有符合要求的节点
from lxml import etree html = etree.parse('猫眼.html', etree.HTMLParser()) ret = html.xpath('//*') #我们使用*代表匹配所有 for i in ret: print(i) #获取的是一个列表,包含了所有的节点 # <Element html at 0x1b1781ac148> #每个节点都是一个 Element 类型, 后面跟着节点名称
当然我们也可以指定节点名称,要选取所有的li节点, 可以使用// 直接加上节点名称即可, 调用时直接使用xpath()方法即可
from lxml import etree html = etree.parse('猫眼.html', etree.HTMLParser()) ret = html.xpath('//li') #指定li节点 for i in ret: print(i)
 
3.4 子节点
我们通过/ 或者 // 即可查找元素的子节点或者子孙节点
选择所有的li节点的所有直接 a 子节点 : ret = html.xpath('//li/a')
选择ul节点下的所有a子孙节点 ret = html.xpath('//ul//a)
ret = html.xpath('//ul/a) 匹配结果为空, 因为ul直接子节点没有a
3.5 父节点
父节点用.. 来实现
查找href属性为 link4.html 的a节点,然后再获取其父节点, 然后再获取其class属性
ret = html.xpath('//a[@href="/board/7"]/../@class') print(ret[0]) #我们还可以通过parent::* 来获取父标签 ret = html.xpath('//a[@href="/board/7"]/parent::*/@class')
3.6 属性匹配
选取class为item-0的li节点
ret = html.xpath('//li[@class="item-0"]')
3.7 文本获取
利用xpath中的text()方法可以获取节点中的文本,
如果想要获取紫苏节点内部的所有文本, 可以直接使用// 加 text() 方法,这样可以保证获取到最全面的文本信息, 但是可能会夹杂一些换行符等特殊字符,
如果想要获取某些特定子孙节点下的所有文本, 可以先选取到特定的子孙节点,然后再调用text() 方法获取其内部文本.
3.8 属性获取
ret = html.xpath('//a[@href="/board/7"]/@href')
注意: 中括号加属性名和值来限定某个属性是 属性匹配
@加属性名是获取该属性的值
3.9 属性多值匹配
当标签属性值拥有多个值的时候,属性匹配就不好用了,要用contains函数
ret = html.xpath('//a[contains(@href,"/board/7")]')
contains 函数第一个传入属性名, 第二个传入属性的值, 只要元素的href属性包含这个值,就会被匹配到
3.10 多属性匹配
利用多个属性确定一个节点,需要匹配多个属性,利用and符连接起来.
ret = html.xpath('//a[contains(@href,"lalala") and @id="1"]')
3.10 按序选择
result = html.xpath('//li[1]/a/text()') 
#查找所有li标签中的第一个, 注意索引从1开始
result = html.xpath(//li[last()]/a/text())
#查找最后一个li标签
result = html.xpath(//li[position()<3]/a/text())
#选取位置序号为1和2的元素
result = html.xpath(//li[last()-2])/a/text()
#选取倒数第三个

这里我们使用了position(), last() 函数, 详见w3school
3.11 节点选择轴
result = html.xpath('//li[1]/ancestor::*)
#ancestor轴,可以获取所有祖先节点,其后需要跟两个::, 然后是节点选择器,我们
直接使用*, 表示获取所有祖先节点  html , body , div , ul

result = html.xpath('//li[1]/ancestor::div')
获取祖先节点中的div标签

result = html.xpath('//li[1]/attribute::*')
attribute轴可以获得所有属性值, 其后跟的选择器还是*, 代表获取所有属性的值

result = html.xpath('//li[1]/child::[@href="link1-html"])
#child轴可以获取所有直接子节点, 我们又给他加了限定条件,选取href属性为xx的元素

result = html.xpath('//li[1]/descendant::span')
#descendant轴可以获取所有子孙节点, 获取所有子孙节点中的span标签

result = html.xpath('//li[1]/following::*[2]')
#following 可以获取当前节点之后的所有节点, 获取当前节点后续的第二个节点

result = html.xpath('//li[1]/following-sibling::*')
#获取所有同级的后续节点

 
查询更多python lxml用法, 可以查看 http://lxml.de/
 1 from lxml import etree
 2 
 3 url = 'https://maoyan.com/board/4'
 4 
 5 def get_html(url,data):
 6 
 7     ret = requests.get(url, params=data)  #获取网页源代码
 8 
 9     return etree.HTML(ret.text)  #用HTML类处理
10 
11 
12 def getmovieinfo(html):
13     for i in range(1,11):
14 
15         num = html.xpath(f'//dd[{i}]/i/text()')  #获取所有的dd标签, 其中每一个dd标签就是一个电影的信息
16 
17         name = html.xpath(f'//dd[{i}]/div/div/div[1]/p[1]/a/text()')
18 
19 
20         star = html.xpath(f'//dd[{i}]/div/div/div[1]/p[2]/text()')
21 
22         releasetime = html.xpath(f'//dd[{i}]/div/div/div[1]/p[3]/text()')
23 
24         movie_info = f'{num[0]}  {name[0]}  {star[0].strip()}   {releasetime[0]}'
25         print(movie_info)
26 
27 
28 for i in range(10):
29     data = {
30         'offset': i * 10
31     }
32     html = get_html(url, data=data)
33     getmovieinfo(html)
 
 

猜你喜欢

转载自www.cnblogs.com/zhangjian0092/p/11210616.html