网页数据的解析提取(XPath的使用----lxml库详解)

这篇具有很好参考价值的文章主要介绍了网页数据的解析提取(XPath的使用----lxml库详解)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        在提取网页信息时,最基础的方法是使用正则表达式,但过程比较烦琐且容易出错。对于网页节点来说,可以定义id、class或其他属性,而且节点之间还有层次关系,在网页中可以通过XPath或CSS选择器来定位一个或多个节点。那么,在解析页面时,利用XPath或CSS选择器提取某个节点,然后调用相应方法获取该节点的正文内容或者属性,就可以提取我们想要的任意信息了。

        在Python中,如何实现上述操作呢?不用担心,相关解析库有非常多,其中比较强大的有lxml、Beautiful Soup,parsel、pyquery等。此帖介绍使用lxml库来定位网页源代码所需部分。(哇哦,Python也太强大了!又对Python深爱了一份!!!)

目录

XPath的使用

1. XPath概览

2. XPath常用规则

3.准备工作

4.实例引入

5、所有节点

6.子节点

7.父节点

8、属性匹配

 9、文本获取

10.属性获取

11.属性多值匹配

12.多属性匹配

13.按序选择


XPath的使用

XPath 的全称是 XML Path Language, 即XML 路径语言, 用来在 XML 文档中查找信息。它虽然最初是用来搜寻 XML 文档的,但同样适用于 HTML 文档的搜索。

所以在做爬虫时,我们完全可以使用XPath实现相应的信息抽取。本节我们就介绍一下 XPath的基本用法。

1. XPath概览

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

XPath于1999年11月16日成为 W3C标准,它被设计出来, 供XSLT、XPointer以及其他XML解析软件使用。

2. XPath常用规则

        下表列举了 XPath的几个常用规则。

表 达 式

nodename

选取此节点的所有子节点

/

从当前节点选取直接子节点

//

从当前节点选取子孙节点

.

选取当前节点

. .

选取当前节点的父节点

@

选取属性

        这里列出了 XPath 的一个常用匹配规则,如下:

//title[@lang='eng']

        它代表选择所有名称为 title,同时属性 lang 的值为 eng的节点。后面会通过 Python 的 lxml库, 利用XPath对HTML 进行解析。

3.准备工作

        使用lxml库之前,首先要确保其已安装好。可以使用 pip3 来安装:

pip3 install 1xml

更详细的安装说明可以参考:https://setup.scrape.center/lxml

        安装完成后,就可以进入接下来的学习了。

4.实例引入

        下面通过实例感受一下使用XPath对网页进行解析的过程,相关代码如下:

from lxml import etree
text = '''
<div>
    <ul>
    <li class="item-0"><a href="link1.html">first item</a></li>
    <li class="item-1"><a href="link2.html">second item</a></li>
    <li class="item-inactive"><a href="link3.html">third item</a></li>
    <li class="item-1"><a href="link4.html">fourth item</a></li>
    <li class="item-0"><a href="link5.html">fifth item</a>
    </ul>
</div>
'''
html =etree.HTML(text)
result = etree.tostring(html)
print(result.decode('utf-8'))

        这里首先导入 lxml库的etree模块,然后声明了一段HTML 文本,接着调用HTML 类进行初始化,这样就成功构造了一个 XPath 解析对象。此处需要注意一点,HTML 文本中的最后一个 li 节点是没有闭合的, 而 etree模块可以自动修正 HTML 文本。之后调用tostring方法即可输出修正后的 HTML 代码,但是结果是 bytes类型。于是利用 decode 方法将其转换成 str类型,结果如下:

text = '''
<div>
    <ul>
    <li class="item-0"><a href="link1.html">first item</a></li>
    <li class="item-1"><a href="link2.html">second item</a></li>
    <li class="item-inactive"><a href="link3.html">third item</a></li>
    <li class="item-1"><a href="link4.html">fourth item</a></li>
    <li class="item-0"><a href="link5.html">fifth item</a>
    </ul>
</div>
'''

        可以看到,经过处理之后的 li 节点标签得以补全,并且自动添加了 body、html节点。另外,也可以不声明,直接读取文本文件。 首先要将HTML文本新建一个html程序,然后采用调用的方式

test.html文件代码:(该html文本一定需要创建到与一下Python程序同一目录下,后面都是基于此html代码进行分析)

text = '''
<div>
    <ul>
    <li class="item-0"><a href="link1. html">first item</a></li>
    <li class="item-1"><a href="link2. html">second item</a></li>
    <li class="item-inactive"><a href="link3. html">third item</a></li>
    <li class="item-1"><a href="link4. html">fourth item</a></li>
    <li class="item-0"><a href="link5. html">fifth item</a>
    </ul>
</div>
'''

Python代码:

from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = etree.tostring(html)
print(result.decode('utf-8'))

         此次输出结果略有不同,多了一个DOCTYPE声明,不过对解析无任何影响,结果如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>text = '''&#13;
</p><div>&#13;
    <ul>&#13;
    <li class="item-0"><a href="link1. html">first item</a></li>&#13;
    <li class="item-1"><a href="link2. html">second item</a></li>&#13;
    <li class="item-inactive"><a href="link3. html">third item</a></li>&#13;
    <li class="item-1"><a href="link4. html">fourth item</a></li>&#13;
    <li class="item-0"><a href="link5. html">fifth item</a>&#13;
    </li></ul>&#13;
</div>&#13;
'''</body></html>

5、所有节点

        一般以//开头的XPath规则,来选取所有符合要点的节点。这里还是以第一个实例中的HTML文本为例,选取其中所有节点。
Python代码:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//*')
pprint.pprint(result)

结果如下:

[<Element html at 0x2a9cf235280>,
 <Element body at 0x2a9cf4ea780>,
 <Element p at 0x2a9cf4ea7c0>,
 <Element div at 0x2a9cf4ea040>,
 <Element ul at 0x2a9cf4ea200>,
 <Element li at 0x2a9cf4ea680>,
 <Element a at 0x2a9cf4ea700>,
 <Element li at 0x2a9cf4ea740>,
 <Element a at 0x2a9cf4ea8c0>,
 <Element li at 0x2a9cf4ea540>,
 <Element a at 0x2a9cf4eaa40>,
 <Element li at 0x2a9cf4eaa00>,
 <Element a at 0x2a9cf4ea840>,
 <Element li at 0x2a9cf4eab80>,
 <Element a at 0x2a9cf4eabc0>]

        这里使用*代表匹配所有节点,也就是获取整个HTML 文本中的所有节点。从运行结果可以看到返回形式是一个列表,其中每个元素是Element类型,类型后面跟着节点的名称,如html、body、div ul、li、a等,所有节点都包含在了列表中。当然,此处匹配也可以指定节点名称。例如想获取所有 li 节点,实例如下:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li')
pprint.pprint(result)
pprint.pprint(result[0])

        这里选取所有li 节点,可以使用//,然后直接加上节点名称,调用时使用xpath方法即可。

运行结果如下:

[<Element li at 0x1c5211da700>,
 <Element li at 0x1c5211da740>,
 <Element li at 0x1c5211d9fc0>,
 <Element li at 0x1c5211da180>,
 <Element li at 0x1c5211da4c0>]
<Element li at 0x1c5211da700>

        可以看到,提取结果也是一个列表,其中每个元素都是 Element类型。要是想取出其中一个对象可以直接用中括号加索引获取,如[0]。

6.子节点

通过/ 或//即可查找元素的子节点或子孙节点。假如现在想选择 li 节点的所有直接子节点a,可以这样实现:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li/a')
pprint.pprint(result)

        这里通过追加/a的方式,选择了li节点的所有直接子节点a。其中//li用于选中所有li节点,/a用于选中li节点的所有直接子节点a。

运行结果如下 :

[<Element a at 0x1c663e9a780>,
 <Element a at 0x1c663e9a7c0>,
 <Element a at 0x1c663e9a040>,
 <Element a at 0x1c663e9a200>,
 <Element a at 0x1c663e9a540>]

        上面的/用于选取节点的直接子节点,如果要获取节点的所有孙子节点,可以使用//。例如:要获取ul节点下的所有子孙节点a,可以这样实现:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//ul//a')
pprint.pprint(result)

        运行结果与上面相同。如果这里用//ul/a,就无法获取结果了。因为/用于获取直接子节点,二ul节点下没有直接的a子节点,只有li子节点。因此要注意/和//的区别,前者用于获取直接子节点,后者用于获取子孙节点。

7.父节点

        通过连续的 /或 //可以查找子节点或子孙节点,那么假如知道了子节点,怎样查找父节点呢?这可以用..实现。例如, 首先选中 href属性为 link4. html的a节点, 然后获取其父节点,再获取父节点的 class 属性,相关代码如下:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//a[@href="link4.html"]/../@class')
pprint.pprint(result)

运行结果如下:

['item-1']

        检查一下结果发现,这正是我们获取的目标li节点的 class 属性。

也可以通过 parent::获取父节点,代码如下:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//a[@href="link4.html"]/parent::*/@class')
pprint.pprint(result)

8、属性匹配

        在选取节点的时候,还可以使用@符号实现属性过滤。例如,要选取class属性为item-0的li节点,可以这样实现:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]')
pprint.pprint(result)

结果如下:

[<Element li at 0x1cf3f68a7c0>, <Element li at 0x1cf3f68a040>]

 9、文本获取

        用XPath中的text方法可以获取节点中的文本,接下来尝试获取前面li节点中的文本,代码如下:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]/text()')
pprint.pprint(result)

结果如下:

['\r\n    ']

        奇怪的是,我们没有获取任何文本,只获取了一个换行符,这是为什么呢? 因为xpath中text方法的前面是/,而/的含义是选取直接子节点,很明显li的直接子节点都是 a 节点,文本都是在 a节点内部的,所以这里匹配到的结果就是被修正的 li 节点内部的换行符,因为自动修正的 li 节点的尾标签换行了。

即选中的是这两个节点:

<li class="item-0"><a href="link1.html">first item</a></li>
 <li class="item-0"><a href="link5.html">fifth item</a>

        其中一个节点因为自动修正,li 节点的尾标签在添加的时候换行了,所以提取文本得到的唯一结果就是 li节点的尾标签和a节点的尾标签之间的换行符。因此,如果想获取 li 节点内部的文本,就有两种方式,一种是先选取 a 节点再获取文本,另一种是使用//。接下来,我们看下两种方式的区别。

先选取a节点,再获取文本的代码如下:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]/a/text()')
pprint.pprint(result)

结果如下:

['first item', 'fifth item']

        可以看到,这里有两个返回值,内容都是 class 属性为 item-0 的 1i 节点的文本,这也印证了前面属性匹配的结果是正确的。这种方式下,我们是逐层选取的,先选取li节点,然后利用/选取其直接子节点a,再选取节点a的文本,得到的两个结果恰好是符合我们预期的。这种方式下,我们是逐层选取的,先选li节点,然后利用/选取其直接子节点a,再选取节点a 的文本,得到的两个结果恰好是符合我们预期的。再来看一下使用//能够获取什么样的结果,代码如下:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]//text()')
pprint.pprint(result)

运行结果如下:

['first item', 'fifth item', '\r\n    ']

        不出所料,这里的返回结果是三个。可想而知,这里选取的是所有子孙节点的文本,其中前两个是 li 的子节点 a 内部的文本,另外一个是最后一个 li 节点内部的文本,即换行符。由此,要想获取子孙节点内部的所有文本,可以直接使用//加text 方法的方式,这样能够保证获取最全面的文本信息,但是可能会夹杂一些换行符等特殊字符。如果想获取某些特定子孙节点下的所有文本,则可以先选取特定的子孙节点,再调用 text方法获取其内部的文本,这样可以保证获取的结果是整洁的。

10.属性获取

        我们已经可以用text方法获取节点内部文本,那么节点属性该怎样获取呢? 其实依然可以用@符号。例如,通过如下代码获取所有 li 节点下所有 a 节点的 href属性:

import pprint
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li/a/@href')
pprint.pprint(result)

        这里通过@href获取节点的 href属性。注意,此处和属性匹配的方法不同,属性匹配是用中括号加属性名和值来限定某个属性, 如[@href="link1.html"], 此处的@href是指获取节点的某个属性,二者需要做好区分。结果如下:

['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html']

         可以看到,我们成功获取了所有 li 节点下 a 节点的 href 属性,并以列表形式返回了它们。

11.属性多值匹配

        有时候,某些节点的某个属性可能有多个值,例如:

from lxml import etree
text= '''
<li class="li li-first"><a href="link. html">first item</a></li>
'''
html= etree. HTML(text)
result = html.xpath('//li[@class="li"]/a/text()')
print(result)

这里 HTML 文本中 li 节点的 class 属性就有两个值: li 和li-first。此时如果还用之前的属性匹配获取节点, 就无法进行了, 运行结果如下:

[]

        这种情况需要用到 contains 方法, 于是代码可以改写如下:

from lxml import etree
text= '''
<li class="li li-first"><a href="link. html">first item</a></li>
'''
html= etree. HTML(text)
result = html.xpath('//li[contains(@class,"li")]/a/text()')
print(result)

        上面使用了contains方法,给其第一个参数传入属性名称,第二个参数传入属性值,只要传入的属性包含传入的属性值,就可以完成匹配。

运行结果为:

['first item']

        contains方法经常在某个节点的某个属性有多个值用到。

12.多属性匹配

        我们还可能遇到一种情况, 就是根据多个属性确定一个节点, 这时需要同时匹配多个属性。运算符and用于连接多个属性, 实例如下:

from lxml import etree

text = '''
<li class="li li-first" name="item"><a href="link.html">first item</a></li>
'''
html = etree.HTML(text)
result = html.xpath('//li[contains(@class,"li") and @name="item"]/a/text()')
print(result)

        这里的 li 节点又增加了一个属性name。因此要确定 li 节点, 需要同时考察 class 和 name 属性,一个条件是class 属性里面包含li字符串, 另一个条件是 name 属性为item字符串, 这二者同时得到满足, 才是 li 节点。class 和 name 属性需要用 and 运算符相连, 相连之后置于中括号内进行条件筛选。运行结果如下:

['first item']

        这里的 and其实是 XPath中的运算符。除了它,还有很多其他运算符,如or、mod等,在此总结为下表。

  

描述

实例

返 回 值

or

age=19 or age=20

如果 age 是 19, 则返回true。

and

age>19 and age<21

如果 age 是 20, 则返回true。如果age 是18, 则返回false

mod

计算除法的余数

5 mod 2

1

|

计算两个节点集

//book|//cd

返回所有拥有 book 和cd元素的节点集

+

加法

6 + 4

10

-

减法

6 - 4

2

*

乘法

6

* 4

24

div

除法

8 div

4

2

=

等于

age=19

如果 age 是 19, 则返回true。

!=

不等于

age!=19

如果 age 是 18, 则返回true。如果age 是 19, 则返回false

<

小于

age<19

如果 age 是 18, 则返回 true。如果age 是 19, 则返回 false

<=

小于或等于

<=19

如果 age 是 19, 则返回 true。如果age 是 20, 则返回false

>

大于

age>19

如果 age 是 20, 则返回true。如果age 是 19, 则返回 false

>=

大于或等于

age>=19

如果age 是 19, 则返回true。如果age 是18, 则返回false

13.按序选择

        在选择节点时, 某些属性可能同时匹配了多个节点, 但我们只想要其中的某一个,如第二个或者最后一个, 这时该怎么办呢?可以使用往中括号中传入索引的方法获取特定次序的节点, 实例如下:

from lxml import etree
text= '''
<div>
<ul>
    <li class="item-0"><a href="link1.html">first item</a></li>
    <li class="item-1">< a href="link2.html">second item</a></li>
    <li class="item-inactive"><a href="link3.html">third item</a></li>
    <li class="item-1">< a href="link4.html">fourth item</a></li>
    <li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
'''
html= etree. HTML(text)
result = html.xpath('//li[1]/a/text()')
print(result)
result = html.xpath('//li[last()]/a/text()')
print(result)
result = html.xpath('//li[position()<3]/a/text()')
print(result)
result = html.xpath('//li[last()-2]/a/text()')
print(result)

        上述代码中, 第一次选择时选取了第一个 li 节点, 往中括号中传入数字1 即可实现。注意,这里和写代码不同, 序号以1开头, 而非0。第二次选择时, 选取了最后一个 li 节点, 在中括号中调用last 方法即可实现。第三次选择时, 选取了位置小于3 的 li 节点, 也就是位置序号为1 和2 的节点, 得到的结果就是前两个 li节点。第四次选择时, 选取了倒数第三个 li 节点, 在中括号中调用last 方法再减去2即可实现。因为last 方法代表最后一个, 在此基础上减2 得到的就是倒数第三个。
运行结果如下:

['first item']
['fifth item']
['first item', 'second item']
['third item']

        在这个实例中, 我们使用了 last、position等方法。XPath 提供了 100多个方法, 包括存取、数值、字符串、逻辑、节点、序列等处理功能。

        XPath还有一个节点轴的选择方法,但由于很少使用,故在此不在介绍!!!

注:今天,又是深爱Python的一天!!!文章来源地址https://www.toymoban.com/news/detail-834903.html

到了这里,关于网页数据的解析提取(XPath的使用----lxml库详解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python---------xpath提取数据------打破局限

     欢迎小可爱们前来借鉴我的gtiee秦老大大 (qin-laoda) - Gitee.com 为什么要学习XPATH和LXML类库 什么是XPATH 认识XML XML的节点关系 常⽤节点选择⼯具 节点选择语法 节点修饰语法 选择未知节点 lxml库 _____________________________________________________________ 可以利⽤ Xpath 来快速的定位特定元素

    2024年02月09日
    浏览(41)
  • XPath:学习使用XPath语法提取HTML/XML文档中的数据使用语法

    以下是一些XPath语法示例,用于提取HTML/XML文档中的数据: 选择元素: 选择所有p元素: //p 选择根元素: / 属性匹配: 选择class属性为\\\"example\\\"的div元素: //div[@class=\\\'example\\\'] 文本内容提取: 提取所有a元素的文本内容: //a/text() 提取第一个p元素的文本内容: //p[1]/text() 使用逻辑

    2024年02月11日
    浏览(43)
  • 超实用的 Python 库之lxml使用详解

    XML(可扩展标记语言)和HTML(超文本标记语言)是广泛用于数据交换和网页构建的标记语言。在Python中,有许多库可以用来解析和处理XML和HTML文档,其中最强大和常用的之一是lxml。lxml是一个高性能、功能丰富的库,它提供了强大的XML和HTML处理功能。本文将深入介绍Python

    2024年02月03日
    浏览(42)
  • Python beautifulsoup4解析 数据提取 基本使用

    Beautiful Soup是Python的一个网页解析库,处理快捷; 支持多种解析器,功能强大。教程细致讲解Beautiful Soup的深入使用、节点选择器、CSS选择器、Beautiful Soup4的方法选择器等重要知识点,是学好爬虫的基础课程。 提示:以下是本篇文章正文内容,下面案例可供参考 建议把代码复

    2023年04月08日
    浏览(44)
  • python爬虫数据解析xpath

    下载地址:百度网盘 请输入提取码 第一步: 下载好文件后会得到一个没有扩展名的文件,重命名该文件将其改为.rar或者.zip等压缩文件,解压之后会得到一个.crx文件和一个.pem文件。新建一个文件夹,将这两个文件放在该文件夹(本人将其命名为xpath-helper)内。 第二步: 将

    2024年02月10日
    浏览(40)
  • lxml&xpath一站式教学

    XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。它最初是用来搜寻 XML 文档的,现在它同样适用于 HTML 文档的搜索 XPath 的选择功能十分强大,它提供了非常简洁明了的路径选择表达式 。 另外,它还提供了超过100 个内建函数,用于字

    2023年04月21日
    浏览(105)
  • Python爬虫——解析插件xpath的安装及使用

    目录 1.安装xpath 2.安装lxml的库 3.xpath基本语法 4.案例一:获取百度网站的百度一下字样 5.案例二:爬取站长素材网上的前十页照片 打开谷歌浏览器 -- 点击右上角小圆点 -- 更多工具 -- 扩展程序  下载xpath压缩包,下载地址:阿里云盘分享 把压缩包解压到指定目录 -- 选择加

    2024年02月02日
    浏览(44)
  • python爬虫数据解析xpath、jsonpath,bs4

    解析数据的方式大概有三种 xpath JsonPath BeautifulSoup 打开谷歌浏览器扩展程序,打开开发者模式,拖入插件,重启浏览器,ctrl+shift+x,打开插件页面 安装在python环境中的Scripts下边,这里就是python库的位置,例如我的地址为:E:pythonpython3.10.11Scripts 解析本地文件etree.parse( \\\'xx.

    2024年02月13日
    浏览(45)
  • Python使用XPath解析HTML:从入门到精通

    XPath是一种用于选择XML文档中节点的语言,它可以通过路径表达式来定位节点。由于HTML文档的结构与XML文档类似,XPath也可以用于解析HTML文档。Python是一种非常流行的编程语言,它提供了许多库用于解析HTML文档。本文将介绍Python中使用XPath解析HTML文档的方法和技巧。 XPath表达

    2024年02月03日
    浏览(46)
  • Python网络爬虫库:轻松提取网页数据的利器

          网络爬虫是一种自动化程序,它可以通过访问网页并提取所需的数据。Python是一种流行的编程语言,拥有许多强大的网络爬虫库。在本文中,我们将介绍几个常用的Python网络爬虫库以及它们的使用。 Requests库 Requests是一个简单而优雅的HTTP库,可以轻松地发送HTTP请求。

    2024年02月09日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包