0


Python3爬虫——用Xpath提取网页信息

Python3爬虫——用Xpath提取网页信息

前言

本笔记用于记录整理requests库的一些基本知识,内容会根据博主自己的认知作增添或压缩。
水平有限,如有错误请不吝赐教。
本文需要读者初步了解HTML有关节点的相关知识。


文章目录

Xpath的梗概和安装

XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。使用Xpath最初是用于搜寻XML文档的,但同样适用于HTML文档的搜索。

使用Xpath前,请先保证其已经安装,可以利用pip进行安装:

pip3 install lxml

这里主要用到

lxml

包内的

etree

的库,其提供了

Xpath

的方法。

Xpath常用规则

表达式描述nodename选取此节点的所有子节点/进入当前节点的直接子节点//进入当前节点的子孙节点.选取当前节点..选取当前节点的父节点@选取当前节点的属性
小试牛刀:

//title[@endtime="2023-02-04"]

意思是选取所有名为

title

并带有属性

endtime

"2023-02-04"

的节点

使用Xpath

接入HTML文本

从内存中读取

假设已经存在这样一段HTML文本:

text = '''
<div class="device-notification">
  <a class="device-notification--logo" href="#0">
    <img src="assets/img/logo.png" alt="Global">
    <p>Emoreの云</p>
  </a>
  <p class="device-notification--message">请将手机横向放置以继续体验</p>
</div>
'''

这意味着这段HTML存在内存内,可能是网上抓取来的或是提前读取好的,接入Xpath的方法如下:

import lxml import etree  # 载入etree库

html = etree.HTML(text)  # 构造Xpath解析对象

从文件中读取

假设有一个

text.html

文件在你的程序所在的文件夹中,里面这需要解析的HTML文本:

from lxml import etree  # 载入etree库

html = etree.parse('./text.html', etree.HTMLParser())  # 从文本构造Xpath解析对象

不论是哪种方法构造Xpath解析对象,

etree

都会对HTML文本进行修正。如果从文件读取,修正时可能额外出现

DOCTYPE

声明。

查找节点

所有节点

利用Xpath查找结点时,一般采用以

//

开头的Xpath规则选择所有符合要求的节点。以上文的HTML文本为例:

>>> html = etree.HTML(text)
>>> result1 = html.xpath('//*')  # *代表选择当前目录的所有节点
>>> print(result1)  # 返回结果是列表
[<Element html at 0x27378d2c440>, <Element body at 0x27378e98140>, <Element div at 0x27378e98300>, <Element a at 0x27378e98400>, <Element img at 0x27378e98440>, <Element p at 0x27378e98480>, <Element p at 0x27378e98240>]

>>> print(result1[0])  # 选取结果中的第一个
<Element html at 0x27378d2c440>

其中

Element

后面的内容便是节点名,本身不存在的

html

节点和

body

节点都自动补全了。

指定节点

//

后面的内容换成节点名,即可查找指定节点,如查询上文所有的

p

节点:

>>> result2 = html.xpath('//p')
>>> print(result2)
[<Element p at 0x27378e98480>, <Element p at 0x27378e98240>]

同时可以查询具有指定属性的

p

节点,只需要在节点名后面附带筛选属性,利用

[@]

将其包裹起来:

>>> result3 = html.xpath('//p[@class="device-notification--message"]')
>>> print(result3)
[<Element p at 0x27378e98240>]

如此只返回了最后一个

p

节点。

属性多值匹配

有的属性不止有一个值(上文HTML并没有这种情况),需要用

contains()

方法进行匹配。该方法第一个参数为属性名,第二个参数填入属性值,只要拥有该属性值的节点都会被返回。

result = html.xpath('//p[contains(@class, "device-notification--message")]')
多属性匹配

需要通过多个属性匹配一个节点,可以利用

and

进行连接,比如匹配一个

class

含有值

device

并且

name

Emore

p

节点:

result = html.xpath('//p[contains(@class, "device") and @name="Emore"]')  # 仅举例

除了

and

,Xpath还含有很多运算符(摘自菜鸟编程),
运算符描述实例返回值|计算两个节点集//book | //cd返回所有拥有 book 和 cd 元素的节点集+加法6 + 410-减法6 - 42*乘法6 * 424div除法8 div 42=等于price=9.80如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。!=不等于price!=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。<小于price<9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。<=小于或等于price<=9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。>大于price>9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。>=大于或等于price>=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。or或price=9.80 or price=9.70如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。and与price>9.00 and price<9.90如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。mod计算除法的余数5 mod 21

选择顺序

有时候有两个或者多个节点,可以像列表一样选择其中某个节点。需要注意的是,Xpath是从1开始计数的。

# 仅举例
result = html.xpath('//div/p[0]')  # 选择第一个p节点
result = html.xpath('//div/p[last()]')  # 选择最后一个p节点
result = html.xpath('//div/p[posision()<3]')  # 选择前面两个p节点
result = html.xpath('//div/p[last()-2]')  # 选择倒数第三个p节点 

查找子孙节点

查找子孙节点只需要像文件路径一样

/

下去就好了,不同的是

/

是只访问直接子节点,而

//

是访问所有的子孙节点:

例如我需要寻找

div

节点下的

p

节点:

>>> result4 = html.xpath('//div/p')  # 利用'/'搜索节点p
>>> result5 = html.xpath('//div//p')  # 利用'//'搜索节点p
>>> print(result4)
[<Element p at 0x27378e98240>]

>>> print(result5)
[<Element p at 0x27378e98480>, <Element p at 0x27378e98240>]
div

节点的直接子节点中含有一个

p

节点,还有一个

a

节点。其中

a

节点内含有一个

img

节点和一个

p

节点。利用

/

只检索到一个

p

节点,而利用

//

检索到了两个

p

节点,即访问了子节点和孙节点。

查找父节点

同样类似命令

cd ..

打开上级目录,Xpath中的

..

可以用于进入父节点。

>>> result6 = html.xpath('//div/p/../a/img')
>>> print(result6)
[<Element img at 0x27378e98440>]

首先进入了

div

节点的

p

节点,然后从

p

节点返回绕到了

a

节点,并取得里面的

img

节点。

获得属性和文本

利用Xpath内的

text()

方法可以获得节点的文本,利用

@

可以获得指定属性的值。

>>> print(result7)
['请将手机横向放置以继续体验']

>>> result8 = html.xpath('//div/p/@class')
>>> print(result8)
['device-notification--message']

同样输出为列表。

节点轴选择

通过轴节点可以快速选择具有相关关系的节点,如选择

div

节点的所有直接子节点:

>>> result10 = html.xpath('//div/child::*')
>>> print(result10)
[<Element a at 0x27378e98400>, <Element p at 0x27378e98240>]

首先需要调用

child

轴,获得所有匹配的节点,然后使用两个冒号

::

进入选择器,接着用

*

选择所有节点。

还有很多轴可供选择(摘自菜鸟编程):
轴名称结果ancestor选取当前节点的所有先辈(父、祖父等)。ancestor-or-self选取当前节点的所有先辈(父、祖父等)以及当前节点本身。attribute选取当前节点的所有属性。child选取当前节点的所有子元素。descendant选取当前节点的所有后代元素(子、孙等)。descendant-or-self选取当前节点的所有后代元素(子、孙等)以及当前节点本身。following选取文档中当前节点的结束标签之后的所有节点。following-sibling选取当前节点之后的所有兄弟节点namespace选取当前节点的所有命名空间节点。parent选取当前节点的父节点。preceding选取文档中当前节点的开始标签之前的所有节点。preceding-sibling选取当前节点之前的所有同级节点。self选取当前节点。

小结

使用XPath可以快速而准确地进行HTML节点选择,并提取信息,但是要注意构造XPath表达式,以避免提取错误。

同时还有一些需要注意的地方:

  • 顺序选择节点时,起始数为1
  • 选择文本的时候需要精准地进入节点,否则text()会返回错误的文本,如一个换行符或一个缩进。
标签: 爬虫 python 前端

本文转载自: https://blog.csdn.net/e_more_day/article/details/128884479
版权归原作者 甲寅Emore 所有, 如有侵权,请联系我们删除。

“Python3爬虫——用Xpath提取网页信息”的评论:

还没有评论