【学习笔记】XPath入门

1. HTML、XML和XPath简介

2. XPath语法介绍

3. lxml库的使用

1. HTML、XML和XPath简介

  • HTML是Hyper Text Markup Language(超文本标记语言)的缩写,我们在浏览器中看到的内容都是HTML代码经过浏览器渲染的结果。

  • XML是EXtensible Markup Language(可扩展标记语言)的缩写,XML是一种很类似HTML的标记语言,不过XML的设计宗旨是传输数据,而非显示数据。

XML的标签我们可以自行定义,具有自我描述性。我们可以根据XML中的标签来获取对应的数据。

  • XPath是XML Path Language(XML路径语言)的缩写,是一门在XML文档中查找信息的语言,用来提取XML文档中的元素和属性

用XPath语言获取HTML中的内容时,先将HTML转换成XML文档,然后根据XML的树形结构来定位到指定的元素和属性,提取数据。如果有数据结构树的基础知识,理解起来很容易。

2. XPath语法介绍

2.1 路径表达式

nodename   选取此节点的所有子节点。
/   从根节点选取。正斜杠也是路径分隔符。
//  从任意位置选取文档中的节点。
.   选取当前节点。
..  选取当前节点的父节点。
@   选取当前节点的属性

2.2 谓语

谓语用来查找某个特定的节点,或包含某个指定值的节点,语法写在元素名后的方括号中,可以写元素的位置编号、函数、用@选取属性等。

//a[n] n为1开始的整数,选取排在第n个位置的<a>元素。
//a[last()] last()表示选取排在最后位置的<a>元素。
//a[last()-1] 和上面同理,表示选取倒数第二个<a>元素。
//a[position()<3] 选取第一个和第二个<a>元素。
//a[@href] 选取拥有href属性的<a>元素。
//a[@href='www.baidu.com'] 选取href属性值为'www.baidu.com'的<a>元素。
//a[@price>10] 选取price属性值大于10的<a>元素。
//a[@price>10]/span  选取price属性值大于10的<a>元素下的<span>元素。

2.3 选取多个路径

//book/title | //book/price  选取<book>元素的所有<title>和<price>元素。
//title | //price  选取所有<title>和<price>元素。
/bookstore/book/title | //price  选取属于<bookstore>元素的<book>元素的所有<title>元素,以及所有的<price>元素。

2.4 常用函数

contains(@属性,string) 选取属性里包含字符串string的元素。
text()  获取元素中的内容。
last()  选取最后一个元素。
position() 用于选取多个元素中某些位置(数字编号)的元素。
count()  返回元素的数量。
max() 返回最大的元素,min(),avg(),sum()同理。

3. lxml库的使用

lxml是Python中用来解析HTML/XML的第三方库,lxml的主要功能是生成一个解析器,解析和提取HTML/XML中的数据。先用lxml生成解析器,然后用XPath语法从解析器中提取HTML/XML中的内容。

3.1 lxml安装命令

pip install lxml

3.2 如何实例化一个etree对象

如何实例化一个etree对象:

from lxml import etree

1.将本地的html文件中的远吗数据加载到etree对象中:

etree.parse(filePath)

2.可以将从互联网上获取的原码数据加载到该对象中:

etree.HTML(‘page_text’)

使用from lxml import etree从lxml库中导入etree解析器,利用etree.HTML将HTML格式的字符串解析成树状的结构,然后用XPath语法从中提取数据。


爬虫获取到的HTML内容一般是response.text中返回的,可以用etree.HTML解析,也可以用etree.parse解析本地的HTML文件


直接打印etree.HTML或etree.parse解析的结果是一个Element对象,可以用etree.tostring将Element中的内容序列化,打印出来。

from lxml import etree

text = '''

<li id="sogou_vr_11002601_box_0" d="ab735a258a90e8e1-6bee54fcbd896b2a-442f386c2a1e6e8e53a1fe6d19345af3">
<div class="img-box">
<a data-z="art" target="_blank" id="sogou_vr_11002601_img_0" href="/link?url=dn9a_-gY295K0Rci_xozVXfdMkSQTLW6cwJThYulHEtVjXrGTiVgS3Bv-Lq4Cfv1alBAAThvPOSrWI9qY-p8VlqXa8Fplpd9ZicvanQ_maqrOSTc9yc_G8v2dLLeZM3m-BK6Fm62i7geWcuIBXVMLgU7snaflYE64fsEBRdq_BJ2UtypbAn-KvPdi0hxtJjA9A1z39aKYwIccB3JIzt4QFE8LsVlRCuKYfzLKXeERIx4Qk8A88RI4RbhJyDRSOfTyU22yEyZwbrdrgozfSg6bw..&amp;type=2&amp;query=xpath%E8%A7%A3%E6%9E%90%E6%9C%AC%E5%9C%B0html%E6%96%87%E4%BB%B6&amp;token=C00104932DBF85F8676380249A914787677678F462FDE2D6" uigs="article_image_0"><img src="//img01.sogoucdn.com/v2/thumb?appid=201147&amp;url=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2F51ZibibjOlXq0AaIWsYWlAznRz4A1oLlhk1ow7vdvGEPg4BRBEIgGSAOpwSIoInypZibc14jZvSLn92G9a01PibOaQ%2F0%3Fwx_fmt%3Djpeg&amp;sign=1832e5c246705f3723268e8aed653d8e" onload="resizeImage(this,140,105)" onerror="errorImage(this)" style="height: 105px; width: auto; margin-left: -54px;"></a>
</div>
<div class="txt-box">
<h3>
<a target="_blank" href="https://weixin.sogou.com/link?url=dn9a_-gY295K0Rci_xozVXfdMkSQTLW6cwJThYulHEtVjXrGTiVgS3Bv-Lq4Cfv1alBAAThvPOSrWI9qY-p8VlqXa8Fplpd9ZicvanQ_maqrOSTc9yc_G8v2dLLeZM3m-BK6Fm62i7geWcuIBXVMLgU7snaflYE64fsEBRdq_BJ2UtypbAn-KvPdi0hxtJjA9A1z39aKYwIccB3JIzt4QFE8LsVlRCuKYfzLKXeERIx4Qk8A88RI4RbhJyDRSOfTyU22yEyZwbrdrgozfSg6bw..&amp;type=2&amp;query=xpath%E8%A7%A3%E6%9E%90%E6%9C%AC%E5%9C%B0html%E6%96%87%E4%BB%B6&amp;token=C00104932DBF85F8676380249A914787677678F462FDE2D6&amp;k=33&amp;h=B" id="sogou_vr_11002601_title_0" uigs="article_title_0">快速入门<em><!--red_beg-->XPath<!--red_end--></em>语法,轻松<em><!--red_beg-->解析<!--red_end--></em>爬虫时的<em><!--red_beg-->HTML<!--red_end--></em>内容</a>
</h3>
<p class="txt-info" id="sogou_vr_11002601_summary_0">也可以用etree.parse<em><!--red_beg-->解析本地<!--red_end--></em>的<em><!--red_beg-->HTML文件<!--red_end--></em>.直接打印etree.HTML或etree.parse解析的结果是一个Element对象,可以用etree.tostring将...</p>
<div class="s-p" t="1659744048">
<a class="account" target="_blank" id="sogou_vr_11002601_account_0" i="oIWsFtzMxTm9ZwUcYH-QHj-s1ues" href="/link?url=dn9a_-gY295K0Rci_xozVXfdMkSQTLW6EzDJysI4ql5MPrOUp16838dGRMI7NnPqb7KADwam4jecFvuY98cx-gwvDqyjOWdzlz2LWrb6gwyCXxLo05fx66G7B2bPh3MRrJF2ApjhFKnGaV_2YJWkVvWNk8AkYmi_QXmGu1hsfvHAOvcgc2SUTwXsXLv13Arp824bG0NxDieto-JqSkFXy24OZCnxixtX&amp;type=2&amp;query=xpath%E8%A7%A3%E6%9E%90%E6%9C%AC%E5%9C%B0html%E6%96%87%E4%BB%B6&amp;token=C00104932DBF85F8676380249A914787677678F462FDE2D6" data-headimage="http://wx.qlogo.cn/mmhead/Q3auHgzwzM5da7WuxJibxsdPvPQVZbIq4M4CcmiaazsRaHnyEcfl1t2Q/0" data-isv="0" uigs="article_account_0">小斌哥ge</a><span class="s2"><script>document.write(timeConvert('1659744048'))</script>2022-8-6</span>
</div>
</div>
</li>

'''

html = etree.HTML(text)
# 按字符串序列化HTML文档
for i, a in enumerate(html.xpath('//div[contains(@class,"txt-box")]/h3/a')):
    print('i和a分别为',i,a)
    title = a.xpath('.//text()')
    print('页面标题是',title)

XPath解析同级目录下HTML本地文件66.html

from lxml import etree

fp = open('66.html','rb')
html = fp.read().decode('utf-8')   #.decode('gbk')

# 利用etree.HTML将HTML格式的字符串解析成树状的结构,然后用XPath语法从中提取数据
selector = etree.HTML(html)
print(selector)
for i, a in enumerate(selector.xpath('//div[contains(@class,"txt-box")]/h3/a')):
    print('i和a分别为',i,a)
    title = a.xpath('.//text()')
    print('页面标题是',title)

将该页面转换为markdown格式链接

csdnsum.py(将部分html内容赋值给text变量,输出csdnsum.txt文本)


from lxml import etree

text = '''

<div id="content_views" class="htmledit_views">
                    <p><img alt="" height="469" src="https://img-blog.csdnimg.cn/3c7e8b66a9f14cdb921f99e220b5d338.png" width="938"></p> 
<p></p> 
<p><br><a href="https://mp.weixin.qq.com/s/TyGKX5wnWL6qSm2EnBCLFg" title="这个Python游戏库,打开就能玩一天!">这个Python游戏库,打开就能玩一天!</a></p> 
<p><a href="https://mp.weixin.qq.com/s/cFE1V2-FjEjlumSU_Lrz7Q" title="介绍一款能取代 Scrapy 的爬虫框架 - feapder">介绍一款能取代 Scrapy 的爬虫框架 - feapder</a><br><br><a href="https://mp.weixin.qq.com/s/7teN4ApgR--E_OmSwy_MFg" title="20 个关于程序员的笑话,看懂了,你就不会笑了,也不会羡慕他们工资高了!">20 个关于程序员的笑话,看懂了,你就不会笑了,也不会羡慕他们工资高了!</a></p> 
<p><a href="https://mp.weixin.qq.com/s/ohDGR0gbQDS2wh3zjWyGcg" title="Python | 细数知乎上值得关注的Python大佬">Python | 细数知乎上值得关注的Python大佬</a></p> 
<p><a href="https://mp.weixin.qq.com/s/5q0G0dvnqqbPUE_Cf16_ZQ" title="68 个 Python 内置函数详解">68 个 Python 内置函数详解</a></p> 
<p><a href="https://mp.weixin.qq.com/s/oXkNieuj7-hZMkw6u8BlBQ" title="15 个让新手爱不释手的 Python 高级库">15 个让新手爱不释手的 Python 高级库</a></p> 
<p><a href="https://mp.weixin.qq.com/s/VuPJdLYNw6AiZpX9kl8tnw" title="用 Markdown 做的 PPT,真的太强了!">用 Markdown 做的 PPT,真的太强了!</a></p> 
<p><a href="https://mp.weixin.qq.com/s/4znu-46IMeJVmhrKUAruvA" title="零代码爬虫神器 -- Web Scraper 的使用">零代码爬虫神器 -- Web Scraper 的使用</a></p> 
<p><a href="https://mp.weixin.qq.com/s/v_mAN_XjK4ar2Tln-xEmrA" title="花了两天,终于把 Python 的 setup.py 给整明白了">花了两天,终于把 Python 的 setup.py 给整明白了</a></p> 
<p><a href="https://mp.weixin.qq.com/s/bR-jPBH5LZeQlcS2NHy46Q" title="推荐一款超棒的抓包分析工具 - Burp Suite">推荐一款超棒的抓包分析工具 - Burp Suite</a></p> 
<p><a href="https://mp.weixin.qq.com/s/X1o_dooM8pNA1OCZNIlr0w" title="分享几段祖传的 Python 代码,拿来直接使用!">分享几段祖传的 Python 代码,拿来直接使用!</a></p> 
<p><a href="https://mp.weixin.qq.com/s/dtEMpAthqLRQkZH2OlcwNA" title="DockerHub上最受欢迎的151个官方镜像,相传掌握第17个可以主宰宇宙!">DockerHub上最受欢迎的151个官方镜像,相传掌握第17个可以主宰宇宙!</a></p> 
<p><a href="https://mp.weixin.qq.com/s/jfpODiVTn4HZWWvTKzKxOg" title="秀!这应该是最好的 “re正则表达式” 使用教程了">秀!这应该是最好的 “re正则表达式” 使用教程了</a></p> 
<p><a href="https://mp.weixin.qq.com/s/wt5hNJOENfQV66A4GpquSw" title="卧槽!我写的 Docker 镜像下载量居然突破了一百万...">卧槽!我写的 Docker 镜像下载量居然突破了一百万...</a></p> 
<p><a href="https://mp.weixin.qq.com/s/OxBV3yTCZgiUTQ5X6WPNdA" title="用Python解决高数所有计算题--sympy求解极限、积分、微分、二元一次方程等">用Python解决高数所有计算题--sympy求解极限、积分、微分、二元一次方程等</a></p> 
<p><a href="https://mp.weixin.qq.com/s/hVCrTCT3T3QOY9z_mZu_Xg" title="30 个Python代码实现的常用功能(附案例源码)">30 个Python代码实现的常用功能(附案例源码)</a></p> 
<p><a href="https://mp.weixin.qq.com/s/Qp12DRURa2I9AVjQ7gpxVw" title="吐血整理!140种Python标准库、第三方库和外部工具都有了">吐血整理!140种Python标准库、第三方库和外部工具都有了</a></p> 
<p></p> 
<p></p> 
<p></p> 
<p></p> 
<p></p> 
<p></p>
                </div>

'''

html = etree.HTML(text)
print(html)

result = etree.tostring(html, pretty_print=True)
print(result)
# 按字符串序列化HTML文档
for i, a in enumerate(html.xpath('//div[contains(@class,"htmledit_views")]/p/a')):
    title = a.xpath('.//text()')
    url = a.xpath('@href')
    string = str(i+1)+':'+ ' ' +'['+ title[0] +']'+'('+ url[0] + ')'+ '\n'
    print(string)
    with open('csdnsum.txt', 'a') as new_file:
        new_file.write(string)


csdn.py(输入csdn.html本地文件,输出csdn.txt文本) 

from lxml import etree
 
fp = open('csdn.html','rb')
html = fp.read().decode('utf-8')   #.decode('gbk')
 
# 利用etree.HTML将HTML格式的字符串解析成树状的结构,然后用XPath语法从中提取数据
selector = etree.HTML(html)
print(selector)
for i, a in enumerate(selector.xpath('//div[contains(@class,"htmledit_views")]/p/a')):
    title = a.xpath('.//text()')
    url = a.xpath('@href')
    string = str(i+1)+':'+ ' ' +'['+ title[0] +']'+'('+ url[0] + ')'+ '\n'
    print(string)
    with open('csdn.txt', 'a') as new_file:
        new_file.write(string)

参考资料

快速入门XPath语法,轻松解析爬虫时的HTML内容

一个Python爬虫案例,带你掌握xpath数据解析方法!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值