[toc]

一、前言

数据定位在爬虫任务中作为重要的一环,旨在从原网页html字符串中提取有效的信息,例如:作者名称、文章标题等。 提取方法有很多,比如正则表达式、解析html等。XPath定位相较于正则表达式而言,具有学习成本低、对新手友好等特点。 本文主要介绍Python3通过lxml模块的简单定位的教程,能够解决爬虫中大部分的数据获取问题,适合新手学习。

二、什么是XPath?

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。 XPath 是 W3C XSLT 标准的主要元素。

XPath解析html也是完全ok的。我们使用python3lxml模块,它的特点是简单易用速度快,缺点是在windows环境下安装起来对新手不太友好。

三、简单快速安装lxml

Linux/Mac 用户推荐执行如下shell,就能搞定。

pip3 install lxml

Windows用户如果cmd直接执行上诉语句可能会报一堆错误,通过百度查询错误,得到的答案应该是教你安装一堆VC库,甚至需要安装VS这个庞然大物来编译一个小小的python模块。正所谓前人栽树,后人乘凉。好在已有人为我们编译好wheel包。

3.1 下载wheel包

我们打开https://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml,等待加载完毕后会自动定位到lxml的位置。

3.2 先不急着下载,看一下python版本

我们打开cmd输入python看一下具体版本,哦,原来是3.7

回到下载页面:
红色框线部分是lxml的版本号,黄色是python版本,绿色是系统版本。都2020年了,不会还有人用32位的系统吧?不会吧? 结合上述我的python版本,我选择lxml‑4.6.2‑cp37‑cp37m‑win_amd64.whl下载就好了。

3.3 安装whl文件

首先在下载的lxml‑4.6.2‑cp37‑cp37m‑win_amd64.whl目录打开一个cmd,再依次执行如下命令即可。

pip install wheel
pip install lxml‑4.6.2‑cp37‑cp37m‑win_amd64.whl

注意第二条命令,后面要与你刚下载的文件名对上。

四、小试牛刀

首先假设有这么一段html文档

html_doc = """
<html><head><title>世界上最远的距离</title></head>
<body>
<div class="content">
<p class="poem">世界上最遥远的距离</p>
<p class="poem">不是我不能说我爱你</p>
<p class="poem">而是想你痛彻心脾</p>
<p class="poem">却只能深埋心底</p>
</div>
<div class="footer">
<a href="http://www.example.com/a" class="link" id="link1">A的博客</a>
<a href="http://www.example.com/b" class="link" id="link2">B的博客</a> 
<a href="http://www.example.com/c" class="link" id="link3">C的博客</a>
</div>
"""

要知道,任意合法的html都可以解析表达为树结构,大概这个样子:

然后简单学习一下我认为最常用的两个XPath语法规则

表达式 描述
@ 选取属性
// 从当前位置选择,而不考虑它在html中的位置

假设我们要这首小诗的文本信息。首先观察html,发现这首诗用四个p标签包围,它们的class都等于poem。 那么我们可以这样写:

# 将html解析为lxml.etree._Element实例
soup = etree.HTML(html_doc)

poem = soup.xpath("//p[@class='poem']")
# 由于解析结果数组类型,我们遍历一下看看
for i in poem:
    # 输入i,以及i的文本内容
    print(i, i.text)

得到结果如下

<Element p at 0x1c73ab174c8> 世界上最遥远的距离
<Element p at 0x1c73ab17bc8> 不是我不能说我爱你
<Element p at 0x1c73ab17c48> 而是想你痛彻心脾
<Element p at 0x1c73ab17e88> 却只能深埋心底

//p[@class='poem'],这句话的意思是,从当前位置出发,不考虑p标签的位置,选取p标签中,属性class的值等于poem的对象。
注意:默认状态下,当前位置是根目录,也即是从html文档最外面一层标签(一般是标签)中包含的范围,废了这么多的话,其实就是从整个html中搜索class是poem的p标签,这些标签被lxml解析成了对象。
重点在于
这些对象又具有一些属性, 比如这个a标签被解析为对象后,就不再是单纯的字符串,而是具有一些属性。
<a href="http://www.example.com/a" class="link" id="link1">A的博客</a>
它所具有的属性,键href的值为http://www.example.com/a,键class的值为link1,键id的值为link1, 还具有text属性,对应的值为A的博客
上面的代码首先得到一组对象,然后分别获取他们的text属性。
更多的实例

序号 表达式 描述
1 //div[@class='content'] 选取所有class=content的div标签
2 //div[@class='content']/p 选取序号1下的所有p标签
3 //p[@class='poem'] 与序号2等价
4 //a[@id='link1'] 选取id=link1的a标签

接着上面的代码演示,

# 我们选取id=link1的a标签,尽管负责条件的a标签只有一个,但返回仍是一个数组,因此我们取第一个元素就得到了这个对象。
link1 = soup.xpath("//a[@id='link1']")[0]
# 获取这个标签的href值,可以这么写
print(link1.get('href'))
# 获取文本
print(link1.text)
"""输出如下:
http://www.example.com/a
A的博客
"""
# 当然也可以用xpath语言直接用@取属性值,如下: print(soup.xpath("//a[@id='link1']/@href")) print(soup.xpath("//a[@id='link1']/text()")) """输出结果:
['http://www.example.com/a']
['A的博客']
同样是数组,别忘了,我们只需要第一个元素即可。
"""

更多的资料请参考: w3cschool的详细xpath语法教程 https://www.w3school.com.cn/xpath/xpath_syntax.asp

标签: xpath, 网络爬虫, 数据清洗, 网页定位

相关文章

添加新评论