python爬虫 xpath入门与lxml库基本使用,我们一同学习xpath

目录

什么是XPath?

xpath语法

知识点

节点

选取节点:

选取a节点下所有的href属性

../ 选取父节点

bookstore/book 选取子元素li

bookstore//book 不管位置 ,选取div节点下的li

谓语(Predicates)

通配符

运算符

选取多个路径:

匹配演示

选取节点

常用函数

lxml解析库

安装

使用流程

读取html文件

文中如有问题,敬请诸位指出,感谢!


什么是XPath?

xpath(XML Path Language)是一门在XML和HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历与匹配。

xpath语法

知识点

  • 掌握元素路径的相关方法
  • 掌握获取获取属性的方法
  • 掌握获取文本的方法

节点

在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。

选取节点:

XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

表达式

描述

示例

结果

nodename

选取此节点的所有子节点

bookstore

选取bookstore下所有的子节点

/

如果是在最前面,代表从根节点选取。否则选择某节点(即当前节点)下的某个节点(取子节点)

/bookstore

选取根元素下所有的bookstore节点

//

从当前节点中选择文档中的直接和间接子节点——这使我们能够“跳过关卡” or 从全局节点中选择节点,随便在哪个位置(取子孙节点)

//book

从全局节点中找到所有的book节点或选取所有 book 子元素,而不管它们在文档中的位置。

@

选取某个节点的属性

//a[@class]

选择拥有class属性的

所有的a节点

.

当前节点

./a

选取当前节点下的a标签

..

选取当前节点的父节点。

//div[@class="book-list list"]//div[@class="title"]/../a

选取div[@class="title"]结点的父节点的a标签

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

路径表达式

结果

bookstore/book

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

bookstore//book

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

//@lang

选取名为 lang 的所有属性。

选取a节点下所有的href属性

//div[@class="book-list list"]//div[@class="title"]/a/@href

../ 选取父节点

bookstore/book 选取子元素li

bookstore//book 不管位置 ,选取div节点下的li

谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

谓语被嵌在方括号中。

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

路径表达式

结果

/bookstore/book[1]

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

/bookstore/book[last()]

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

/bookstore/book[last()-1]

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

/bookstore/book[position()<3]

选取bookstore 元素的最前面两个子元素(book)

//book/title[text()=‘世界上最丑的’]

选择所有book下的title元素,仅仅选择文本为 世界上最丑 的title元素

//title[@lang='eng']

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

/bookstore/book[price>35.00]

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

/bookstore/book[price>35.00]//title

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

通配符

*表示通配符。

通配符

描述

示例

结果

*

匹配任意节点

/bookstore/*

选取bookstore下的所有子元素。

@*

匹配节点中的任何属性

//book[@*]

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

运算符

匹配不同属性的同一标签: or

匹配包含 class="title" 或者 class="pic" 的标签

//div[@class="book-list list"]//div[@class="title" or @class="pic"]/a

and

相信大家也能理解 并且的关系,符合这个的同时又符合另一个

选取多个路径:

xpath表达式1 | xpath1 表达式2 | xpath表达式3

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

示例如下:

路径表达式

结果

//book/title | //book/price

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

//bookstore/book | //book/title

选取所有book元素以及book元素下所有的title元素

/bookstore/book/title | //price

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

匹配演示

<ul class="book_list"> 
    <li> 
        <title class="book_001">Harry Potter</title> 
        <author>J K. Rowling</author> 
        <year>2005</year> 
        <price>69.99</price> 
    </li>
    <li> 
        <title class="book_002">Spider</title>
        <author>Forever</author>
        <year>2019</year>
        <price>49.99</price>
   </li>
</ul>
1、查找所有的li节点
     //li 
2、查找li节点下的title子节点中,class属性值为'book_001'的节点
     //li/title[@class="book_001"] 
3、查找li节点下所有title节点的,class属性的值
     //li//title/@class

只要涉及到条件,加 []

只要获取属性值,加 @

选取节点

1、// :从所有节点中查找(包括子节点和后代节点)
2、@ :获取属性值 
# 使用场景1(属性值作为条件)
    //div[@class="movie"] 
# 使用场景2(直接获取属性值)
    //div/a/@src

常用函数

1、contains() :匹配属性值中包含某些字符串节点 
    # 查找class属性值中包含"book_"的title节点
       //title[contains(@class,"book_")] 
       //div[@class="book-list list"]//a[contains(text(), "世界上最丑")]

    # 如果是多个则可以:

        //div[contains(@class, 'book2') and contains(@class, 'book3')]
    # 如果目标 class 不一定是第一个,可以:

        //div[contains(concat(' ', @class, ' '), 'book2')]

2、text() :获取节点的文本内容
    # 查找所有书籍的名称
       //ul[@class="book_list"]/li/title/text()

3、将对象还原为字符串:etree.tostring()
import requests 
from lxml import etree 
url='https://www.douban.com/' 
headers={ 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36' 
}
req=requests.get(url,headers=headers) 
html=req.text xp=etree.HTML(html) 
a=xp.xpath('//div[@class="book-list list"]//div[@class="title"]/a')[0]

print(etree.tostring(a,encoding='utf-8').decode('utf-8'))

 //div[contains(@class, 'mod_action cf')] 

//div[contains(concat(' ', @class, ' '), 'mod_action cf')]

lxml解析库

安装

pip install lxml

使用流程

1、导入模块
    from lxml import etree 
2、创建解析对象 
    req = etree.HTML(html) 
3、解析对象调用xpath 
    r_list = req.xpath('xpath表达式') # 返回结果类型为列表

我们可以利用他来解析HTML代码,并且在解析HTML代码的时候,如果HTML代码不规范,他会自动的进行补全。示例代码如下:

# 使用 lxml 的 etree 库 
from lxml import etree 
text = ''' <h2>
        新书速递
            &nbsp;·&nbsp;·&nbsp;·&nbsp;·&nbsp;·&nbsp;·
            <span class="pl">&nbsp;(
                
                    <a href="https://book.douban.com/latest" target="_self">更多</a>
                ) </span>
    </h2> ''' 
#利用etree.HTML,将字符串解析为HTML文档 
html = etree.HTML(text) 
# 按字符串序列化HTML文档 
result = etree.tostring(html,encoding='utf-8',pretty_print=True)
print(result.decode('utf8'))

输出结果如下:

 可以看到。lxml会自动修改HTML代码。例子中不仅补全了li标签,还添加了body,html标签。

读取html文件

etree.parse()方法来读取文件

# 获取所有li标签: 
from lxml import etree 
html = etree.parse('hello.html') 
print(type(html)) 
# 显示etree.parse() 返回类型 
result = html.xpath('//li') 
print(result) # 打印<li>标签的元素集合
 
# 获取所有li元素下的所有class属性的值: 
from lxml import etree 
html = etree.parse('hello.html') 
result = html.xpath('//li/@class') 
print(result) 

# 获取li标签下href为www.baidu.com的a标签: 
from lxml import etree 
html = etree.parse('hello.html') 
result = html.xpath('//li/a[@href="www.baidu.com"]') 
print(result) 

# 获取li标签下所有span标签: 
from lxml import etree 
html = etree.parse('hello.html') 
#result = html.xpath('//li/span') #注意这么写是不对的: #因为 / 是用来获取子元素的,而 <span> 并不是 <li> 的子元素,所以,要用双斜杠 
result = html.xpath('//li//span') 
print(result) 

# 获取li标签下的a标签里的所有class: 
from lxml import etree 
html = etree.parse('hello.html') 
result = html.xpath('//li/a//@class') 
print(result) 

# 获取最后一个li的a的href属性对应的值: 
from lxml import etree 
html = etree.parse('hello.html') 
result = html.xpath('//li[last()]/a/@href') # 谓语 [last()] 可以找到最后一个元素 
print(result) 

# 获取倒数第二个li元素的内容: 
from lxml import etree 
html = etree.parse('hello.html') 
result = html.xpath('//li[last()-1]/a')[0]
# text 方法可以获取元素内容 
print(result.text) 
# 获取倒数第二个li元素的内容的第二种方式: 
result = html.xpath('//li[last()-1]/a/text()') 
print(result)

文中如有问题,敬请诸位指出,感谢!

猜你喜欢

转载自blog.csdn.net/q1246192888/article/details/123649072