4. 解析库的使用

对于网页节点,可以定义id、class或其他属性,且节点之间有曾是关系,可以通过Xpath 或者CSS选择器来定位一个或者多个节点,再调用相应的方法获取它的正文内容或者属性。

python中强大的解析库有:lxml、Beautiful Soup、pyquery

4.1 使用Xpath

4.1.1 Xpath 概览

Xpath的选择功能十分强大,提供了非常简洁明了的路径选择表达式。几乎我们想要定位的节点,都可以用Xpath 来选择。

4.1.2 xpath 基础教程

https://www.runoob.com/xpath/xpath-tutorial.html

(1)常用规则

选取节点
XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。 下面列出了最有用的路径表达式:

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
… 选取当前节点的父节点。
@ 选取属性。
在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点。
/bookstore
选取根元素 bookstore。

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

bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
//book 选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang 选取名为 lang 的所有属性。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ck23VKVJ-1617015912878)(attachment:d622fd58-bdd8-40f6-8284-b0d1ee3da64f.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eDb53adZ-1617015912882)(attachment:6e3f6e52-ae72-48b8-86fa-7b519b016e04.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-njW4PTbL-1617015912884)(attachment:ec0beeaf-750d-4f1b-bf45-107bb4fec799.png)]

(2)准备工作

pip install lxml
Collecting lxmlDownloading lxml-4.6.3-cp37-cp37m-win_amd64.whl (3.5 MB)
Installing collected packages: lxml
Successfully installed lxml-4.6.3
Note: you may need to restart the kernel to use updated packages.

(3)实例引入

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

首先导入了lxml库的etree模块(用于解析DOM树),然后声明了一段HTML文本,调用HTML类进行初始化。注意这里HTML文本中最后一个li节点是没有的,使用etree.tostring()方法进行修正,但是输出的结果是Bytes型,所以利用decode()方法将其转换成str类型。

另外可以直接读取文本文件进行解析。:

from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=etree.tostring(html)
print(result.decode('utf-8'))
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><div>
<ul>
<li class="item-0"><a herf="link0.html">first item</a></li>
<li class="item-1"><a href="link1.html">second item</a></li>
<li class="items-2"><a herf="link2.html">third item</a></li>
<li class="item-3"><a href="link3.html">fourth item</a></li>
<li class="item-4"><a href="link4.html">fourth item</a></li><li>
</li></ul>
</div></body></html>

(4)所有节点

  • 一般会使用//开头的Xpath规则来选取所有符合要求的节点。
from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//*')
print(result)
[<Element html at 0x22f1233c3c8>, <Element body at 0x22f1233c608>, <Element div at 0x22f1233c6c8>, <Element ul at 0x22f1233ca08>, <Element li at 0x22f1233cb08>, <Element a at 0x22f1233cd88>, <Element li at 0x22f1233ce48>, <Element a at 0x22f1233f108>, <Element li at 0x22f1233f388>, <Element a at 0x22f1233cb88>, <Element li at 0x22f1233f4c8>, <Element a at 0x22f1233f588>, <Element li at 0x22f1233f5c8>, <Element a at 0x22f1233f608>, <Element li at 0x22f1233f648>]

备注:*代表匹配所有节点

  • 获取指定节点名称
from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//li')
print(result)
print(result[0])
[<Element li at 0x22f1234a708>, <Element li at 0x22f1234a7c8>, <Element li at 0x22f1234ab08>, <Element li at 0x22f1234abc8>, <Element li at 0x22f1234ad08>, <Element li at 0x22f1234ae88>]
<Element li at 0x22f1234a708>

(5)子节点

from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//li/a')
print(result)
print(result[0])
[<Element a at 0x22f1234d388>, <Element a at 0x22f1234d788>, <Element a at 0x22f1234d888>, <Element a at 0x22f1234d908>, <Element a at 0x22f1234d948>]
<Element a at 0x22f1234d388>

注意:/用于选取直接子节点,如果想要获取所有子孙节点,可以使用//,如下要获取ul节点下的所有子孙节点a

from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//ul/a')
print(result)
print(result[0])
[]---------------------------------------------------------------------------IndexError                                Traceback (most recent call last)<ipython-input-18-68eb1d35d42c> in <module>3 result=html.xpath('//ul/a')4 print(result)
----> 5 print(result[0])IndexError: list index out of range
from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//ul//a')
print(result)
print(result[0])
[<Element a at 0x22f12356f48>, <Element a at 0x22f119820c8>, <Element a at 0x22f11982348>, <Element a at 0x22f119823c8>, <Element a at 0x22f11982408>]
<Element a at 0x22f12356f48>

(6)父节点

如果知道了子节点,如何来找父节点的?

  • 这可以使用… 来实现。

如先选中 href 属性为link4.html 的a节点,然后再获取其父节点,再获取其class属性

from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//a[@href="link4.html"]/../@class')
print(result)
['item-4']
  • 通过parent:: 来获取父节点
from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//a[@href="link4.html"]/parent::*/@class')
print(result)
['item-4']

(7)属性匹配

用@符号进行属性过滤,比如选取class为item-0 的li节点

from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//li[@class="item-0"]')
print(result)
[<Element li at 0x22f119af8c8>]

(8) 文本获取

用text()可以获取节点内部文本
两种方式:

  • 先取节点再取文本
  • //
from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//li[@class="item-0"]/a/text()')
print(result)
['first item']
from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//li[@class="item-0"]//text()')
print(result)
['first item']

如果想要获取子孙节点内部的所有文本,可以直接用//加text()的方式,这样可以保证获取最全面的文本信息,但是可能会夹杂一些换行符等特殊字符。如果想获取某些特定子孙节点下的所有文本,可以先选取到特定的子孙节点,然后再调用text()方法获取其内容,这样可以保证获取结果是整洁的

(9)属性获取

@

from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//li/a/@href')
print(result)
['link0.html', 'link1.html', 'link2.html', 'link3.html', 'link4.html']

(10)属性多值匹配

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

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)
[]

li中 class 有两个属性值,用以前的办法无法匹配,需要用 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)
['first item']
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")]//text()')
print(result)
['first item']

(11) 多属性匹配

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)
['first item']

li 中多了一个name 属性

(12)按序选择

from lxml import etree
html = etree.parse("./test.html",etree.HTMLParser())
result=html.xpath('//li[1]//text()')
print(result)
result1=html.xpath('//li[last()]//text()')
print(result1)
result2=html.xpath('//li[position()<3]//text()')
print(result2)
['first item']
['\n']
['first item', 'second item']

(13)节点轴选择

Xpath 提供了很多节点轴的选择方法,包括获取子元素、兄弟元素、父元素、祖先元素等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RFTmucXJ-1617015912888)(attachment:6e6e2d45-63e3-4297-8eec-883c444d9a5b.png)]


爬虫-解析库的使用-Xpath相关推荐

  1. Python爬虫 解析库的使用

    已写章节 第一章 网络爬虫入门 第二章 基本库的使用 第三章 解析库的使用 第四章 数据存储 第五章 动态网页的抓取 文章目录 已写章节 第三章 解析库的使用 3.1BeautifulSoup 3.1 ...

  2. beautifulsoup解析动态页面div未展开_两个资讯爬虫解析库的用法与对比

    " 阅读本文大概需要 10 分钟. " 舆情爬虫是网络爬虫一个比较重要的分支,舆情爬虫往往需要爬虫工程师爬取几百几千个新闻站点.比如一个新闻页面我们需要爬取其标题.正文.时间.作者 ...

  3. python爬虫解析库(Xpath、beautiful soup、Jsonpath)

    1. HTML解析 HTML的内容返回给浏览器,浏览器就会解析它,并对它渲染. HTML 超文本表示语言,设计的初衷就是为了超越普通文本,让文本表现力更强. XML 扩展标记语言,不是为了代替HTML ...

  4. 爬虫解析库xpath

    # xpath简介 XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言.用于在 XML 文档中通过元素和属性进行导航. XPath基于XM ...

  5. 爬虫解析库之xpath、Beautifulsoup的对比使用

    1 xpath XPath 是一门在 XML 文档中查找信息的语言.XPath 可用来在 XML 文档中对元素和属性进行遍历. (1)基本介绍 / 从根节点选取, // 从所有匹配的节点选取 . 当前 ...

  6. python xpath语法-Python爬虫 | 解析库Xpath的使用

    first itemsecond itemthird itemfourth itemfifth item

  7. 爬虫之网络数据解析的三种方式---正则表达式、XPath数据解析库、BeautifulSoup数据解析库

    1.正则表达式 爬虫的四个主要步骤: 明确目标(要知道你准备取哪个范围或者网站上取搜索) 爬(将所有网站的内容全部爬下来) 取(取掉对我们没用的数据) 处理数据(按照我们想要的方式存储和使用) 什么是 ...

  8. python爬虫xpath提取数据_python爬虫三大解析库之XPath解析库通俗易懂详讲

    @(这里写自定义目录标题) 使用XPath解析库 1.简介 ??XPath(全称XML Path Languang),即XML路径语言,是一种在XML文档中查找信息的语言.适用于XML和HTML文档的 ...

  9. 浅谈解析库XPath,bs4和pyquery

    <浅谈解析库XPath,bs4和pyquery> 作者:墨非墨菲非菲 前几天在CSDN看到一篇帖子,题目是"如何让自己像打王者一样发了疯,拼了命,石乐志的学习".这里面 ...

最新文章

  1. LeetCode 217 Contains Duplicate--python,java解法--set--简单
  2. 饥荒 死亡后不删存档的办法
  3. 搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务
  4. new/delete与malloc/free的区别与联系详解
  5. centos 多个yum源,系统怎么选择
  6. MyBatis源码-解读Executor的三个实现类之SimpleExecutor(简单执行器)
  7. shellcode模板(使用hash获取API)
  8. 如何用excel筛选相似内容_excel如何筛选出相同内容,excel怎么用公式筛选
  9. eclipse下tomcat临时目录位置
  10. 世界杯:裁判看了视频后判罚更重?
  11. iPhone 二手手机到底去哪了
  12. java 医疗监护_医疗监护仪解决方案
  13. 用计算机处理表格信息教案,表格信息的加工与表达教案
  14. 0基础转行3D建模,从月薪3000到15k,我整理的超全学习指南
  15. 米发,免费域名转发 301重定向 URL跳转服务
  16. Easy-Pay一行代码解决支付宝微信支付功能
  17. 泸州职业技术学院计算机单招试题,2021年泸州职业技术学院单招语文考试模拟试题库...
  18. 俄罗斯将基于开源的Sailfish自主研发手机操作系统
  19. Linux进程的详细内容
  20. 华为面试Android岗;群面+技术面+综合面+英语面

热门文章

  1. jconsole本地连接失败
  2. 鼠标右键点击桌面计算机,鼠标右键点击电脑桌面没有反应的解决方法
  3. Arduino Uno R3 communication
  4. [Hexo]Hexo+github搭建静态博客
  5. wpf 语音通话_WPF---语音合成与语音识别
  6. 软件定义汽车—箭在弦上的变革
  7. 【Android】动态获取当前背景图,根据背景图色动态改变字体颜色
  8. Xue Bin Peng获SIGGRAPH 2022最佳博士论文,太极胡渊鸣获提名
  9. 痛心!36岁比亚迪员工连上夜班猝死
  10. 基于Matlab搭建单站雷达扫描天空仿真平台(附源码)