优秀的编程知识分享平台

网站首页 > 技术文章 正文

pyhton爬虫:xpath的使用与语法(py xpath)

nanyue 2024-11-14 16:47:32 技术文章 1 ℃

XPath 可以在XML文档中查找信息,支持HTML,可以用来提取信息。可以把标签文本看作一个树状图,最顶层是html,第二层是head和body,body的下面是许多div,每个div可以用/[@属性=属性名]来进一步细分,也可以通过/@属性来获取对应的信息,提取双标签中的文字则可以用/text()。

安装库

pip3 install lxml

基本使用

from lxml import etree  
wb_data = """  
        <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(wb_data)  
print(html)  
result = etree.tostring(html)  
print(result.decode("utf-8"))

从下面的结果来看,这里的html其实就是一个python对象,etree.tostring(html)则补全了html缺胳膊少腿的标签。

输出结果:

<Element html at 0x39e58f0>  
<html><body><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>  
       </li></ul>  
     </div>  
    </body></html>

语法

选取节点

XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。

下面列出了最有用的路径表达式:

表达式

描述

nodename

选取此节点的所有子节点。

/

表示子级范围

//

表示子孙后代范围

.

选取当前节点。

选取当前节点的父节点。

@

根据属性具体判断某一个标签,可以通过 标签名[属性值判断式] 来定位,

示例

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式

结果

bookstore

选取 bookstore 元素的所有子节点。

/bookstore

选取元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!

bookstore/book

选取属于 bookstore 的子元素的所有 book 元素。

//book

选取所有 book 子元素,而不管它们在文档中的位置。

bookstore//book

选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。

//@lang

选取名为 lang 的所有属性。

谓语(Predicates)

谓语被嵌在方括号中,用来查找某个特定的节点或者包含某个指定的值的节点。

顺序定位

  1. 方式一:[1] 通配标签返回的是一个列表,里面为空或者一些元素。 xpath支持取具体值, 例如去列表的第一个元素,[1]就可以拿到;第二个值就是[2]。 注意列表的下角标从1开始,不像python那样从0开始
  2. 方式二:position() position函数会返回当前的位置值,拿到值之后就可以对值进行判断选取。 举例: 选取当前位置下的所有div标签,然后去掉第一个,取出从2开始,一直到最后 一个div标签。 .//div[position()>1]
  3. 方式三:last() 这个是最简单的,就是取列表的最后一个元素 举例: .//div[last()]

示例

在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

路径表达式

结果

/bookstore/book[1]

选取属于 bookstore 子元素的第一个 book 元素。

/bookstore/book[last()]

选取属于 bookstore 子元素的最后一个 book 元素。

/bookstore/book[last()-1]

选取属于 bookstore 子元素的倒数第二个 book 元素。

/bookstore/book[position()<3]

选取最前面的两个属于 bookstore 元素的子元素的 book 元素。

//title[@lang]

选取所有拥有名为 lang 的属性的 title 元素。

//title[@lang='eng']

选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。

/bookstore/book[price>35.00]

选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。

/bookstore/book[price>35.00]/title

选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

选取未知节点

XPath 通配符可用来选取未知的 XML 元素。

通配符

描述

*

匹配任何元素节点。

@*

匹配任何属性节点。

node()

匹配任何类型的节点。

示例

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式

结果

/bookstore/*

选取 bookstore 元素的所有子元素。

//*

选取文档中的所有元素。

//title[@*]

选取所有带有属性的 title 元素。

选取若干路径

通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

示例

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式

结果

//book/title | //book/price

选取 book 元素的所有 title 和 price 元素。

//title | //price

选取文档中的所有 title 和 price 元素。

/bookstore/book/title | //price

选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

与或非

通过与或非进行更严格的筛选

逻辑

关键字

and

or

not()

示例

.//div[@id and @class]

.//div[@id or @class]

.//div[not(@id)]

示例解释

同时拥有id和class属性的div

有id或者class属性的div

没有id属性的
div

常用函数

contains(属性名,值)

匹配包含对应值的标签或数据

response.xpath('//a[contains(text(),"Next >")]')
response.xpath('.//div[contains(@class,"content")]')

获取某个标签的内容(基本使用),注意,获取a标签的所有内容,a后面就不用再加正斜杠,否则报错。

text()

获取文本 写法一

html = etree.HTML(wb_data)
html_data = html.xpath('/html/body/div/ul/li/a')
print(html)
for i in html_data:
    print(i.text)

输出:

<Element html at 0x12fe4b8>
first item
second item
third item
fourth item
fifth item

写法二 直接在需要查找内容的标签后面加一个/text()就行

html = etree.HTML(wb_data)
html_data = html.xpath('/html/body/div/ul/li/a/text()')
print(html)
for i in html_data:
    print(i)

输出:

<Element html at 0x138e4b8>
first item
second item
third item
fourth item
fifth item

parse(html文件路径)

打开读取html文件

#使用parse打开html的文件
html = etree.parse('test.html')
html_data = html.xpath('//*')#打印是一个列表,需要遍历
print(html_data)
for i in html_data:
    print(i.text)

将文本转码

html = etree.parse('test.html')
html_data = etree.tostring(html,pretty_print=True)
res = html_data.decode('utf-8')
print(res)

示例

打印指定路径下a标签的属性

可以通过遍历拿到某个属性的值,查找标签的内容

html = etree.HTML(wb_data)
html_data = html.xpath('/html/body/div/ul/li/a/@href')
for i in html_data:
    print(i)

相对路径匹配

下面我们查找相对路径,例如,查找所有li标签下的a标签内容。

html = etree.HTML(wb_data)
html_data = html.xpath('//li/a/text()')
print(html_data)
for i in html_data:
    print(i)

打印:

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

使用相对路径,查找一下相对路径下li标签下的a标签下的href属性的值,注意,a标签后面需要双//。

html = etree.HTML(wb_data)
html_data = html.xpath('//li/a//@href')
print(html_data)
for i in html_data:
    print(i)

打印:

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

相对路径下跟绝对路径下查特定属性的方法类似,也可以说相同。

html = etree.HTML(wb_data)
html_data = html.xpath('//li/a[@href="link2.html"]')
print(html_data)
for i in html_data:
    print(i.text)

打印:

[<Element a at 0x216e468>]
second item

查找最后一个li标签里的a标签的href属性

html = etree.HTML(wb_data)
html_data = html.xpath('//li[last()]/a/text()')
print(html_data)
for i in html_data:
    print(i)

打印:

['fifth item']
fifth item

查找倒数第二个li标签里的a标签的href属性

html = etree.HTML(wb_data)
html_data = html.xpath('//li[last()-1]/a/text()')
print(html_data)
for i in html_data:
    print(i)

打印:

['fourth item']
fourth item

Tags:

最近发表
标签列表