当前位置:   article > 正文

Python爬虫——使用XPath和lxml库解析HTML_lis = html.xpath('//*[@id="skinbody"]/div[10]/div[

lis = html.xpath('//*[@id="skinbody"]/div[10]/div[1]/div[1]/ul/li')是什


在re、bs4、xpath等解析库中,re库运行起来效率最高,但用起来太麻烦;XPath 使用较为方便,而且效率损失不大。因此应某人的需求(?),本人开始学习 XPath。

0 安装 XPath Helper 插件

在这里插入图片描述

在 edge 浏览器的“扩展”中,开启“开发者模式”和“允许来自其他应用商店的扩展”,将文件夹《chrome_Xpath_v2.0.2》拖入到“扩展”页面中即可完成安装。

本人设置键盘快捷方式为“Ctrl+Shift+C”,这样每次想用时就可以快速打开这玩意了,再按下“F12”查看代码,就可以开玩 XPath 了。这个插件是真的好用,强烈推荐安装。

1 XPath 语法

1.1 节点

表达式描述用法举例用法举例说明
nodename选取此节点下的所有节点div选取div下的所有标签
//全局节点(可粗略理解为“绝对路径”)//div选取整个HTML页面的所有div标签
//nodename//选取某个节点下的所有节点(包括子节点、子节点的子节点…)//header//div选取header标签下的所有div标签,不管是不是header标签的第一级节点
/选取某个节点下的子节点(可粗略理解为“相对路径”)(只能一级)//div/a选取div标签下的a标签(而非整个页面的a标签)
@选取带有某个属性(attr)的节点//div[@class]选取带有class属性的div标签
@获取属性的内容//div/span/@title选取span标签的属性title的内容
@attr=str选取带有某个属性(attr)为str的节点//div[@class=“menv”]选取带有class属性为menv的div标签
.当前节点下./span当前节点下的span标签

1.2 谓语

表达式描述用法举例用法举例说明
[n]当选取有多个标签时,可以指定选取第n个标签(注意n从1开始)//div[@class=“menv”][2]选取第二个带有class属性为menv的div标签
[last()]选取最后一个标签//div[last()]选取最后一个div标签
[last()-n]选取倒数第n个标签//div[last()-3]选取倒数第三个div标签
[position()<n]选取前n个标签//div[position()❤️]选取前三个div标签
[element表达式条件]元素值符合表达式条件的标签//div[price<35.00]选取div标签且price元素需小于35.00

2 lxml 库使用实例

lxml 库的作用:将 html 字符串进行解析,供 XPath 语法进行数据提取。

现在我们通过一个实例来初步认知 lxml 的用法,如下为一个 HTML 字符串:

text = \
"""
<ul class="ullist" padding="1" spacing="1">
    <li>
        <div id="top">
            <span class="position" width="350">职位名称</span>
            <span>职位类别</span>
            <span>人数</span>
            <span>地点</span>
            <span>发布时间</span>
        </div>
        <div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=33824&amp;keywords=python&amp;tid=87&amp;lid=2218">python开发工程师</a>
            </span>
            <span>技术类</span>
            <span>2</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        <div id="odd">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=29938&amp;keywords=python&amp;tid=87&amp;lid=2218">python后端</a>
            </span>
            <span>技术类</span>
            <span>2</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        <div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=31236&amp;keywords=python&amp;tid=87&amp;lid=2218">高级Python开发工程师</a>
            </span>
            <span>技术类</span>
            <span>2</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        <div id="odd">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=31235&amp;keywords=python&amp;tid=87&amp;lid=2218">python架构师</a>
            </span>
            <span>技术类</span>
            <span>1</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        <div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=34531&amp;keywords=python&amp;tid=87&amp;lid=2218">Python数据开发工程师</a>
            </span>
            <span>技术类</span>
            <span>1</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        <div id="odd">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=34532&amp;keywords=python&amp;tid=87&amp;lid=2218">高级图像算法研发工程师</a>
            </span>
            <span>技术类</span>
            <span>1</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        <div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=31648&amp;keywords=python&amp;tid=87&amp;lid=2218">高级AI开发工程师</a>
            </span>
            <span>技术类</span>
            <span>4</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        <div id="odd">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=32218&amp;keywords=python&amp;tid=87&amp;lid=2218">后台开发工程师</a>
            </span>
            <span>技术类</span>
            <span>1</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        <div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=32217&amp;keywords=python&amp;tid=87&amp;lid=2218">Python开发(自动化运维方向)</a>
            </span>
            <span>技术类</span>
            <span>1</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        <div id="odd">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=34511&amp;keywords=python&amp;tid=87&amp;lid=2218">Python数据挖掘讲师 </a>
            </span>
            <span>技术类</span>
            <span>1</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
    </li>
</ul>
"""
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

2.1 解析字符串为 HTML

这一步的操作是将字符串转化为可识别的 HTML,并且还会进行“查缺补漏”,修复不规范标签。

from lxml import etree

'''
0. 解析字符串为 HTML
'''
html = etree.HTML(text)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.2 获取 div 标签

XPath 表达式://div

'''
1. 获取 div 标签
'''
# 获取 div 标签,div1 是一个列表
div1 = html.xpath('//div')
# 列表遍历,转化为字符串输出
for div in div1:
    d = etree.tostring(div, encoding='utf-8').decode('utf-8')
    print(d)
    print('*' * 50)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

注意 1:div1 是一个列表,因此需要使用 for 对其进行访问遍历。

注意 2:若转化字符串和解析 HTML 时不用 utf8,则默认为 byte 流数据。

输出结果:

<div id="top">
            <span class="position" width="350">职位名称</span>
            <span>职位类别</span>
            <span>人数</span>
            <span>地点</span>
            <span>发布时间</span>
        </div>
        
**************************************************
<div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=33824&amp;keywords=python&amp;tid=87&amp;lid=2218">python开发工程师</a>
            </span>
            <span>技术类</span>
            <span>2</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        
**************************************************
<div id="odd">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=29938&amp;keywords=python&amp;tid=87&amp;lid=2218">python后端</a>
            </span>
            <span>技术类</span>
            <span>2</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        
**************************************************

(后面结果省略)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

2.3 获取某个指定的 div 标签

假设我们想要获取第 1 个 div 标签,那么 XPath 表达式://div[1]

'''
2. 获取某个指定的 div 标签
'''
# div2 是一个列表
div2 = html.xpath('//div[1]')[0]
DIV2 = etree.tostring(div2, encoding='utf-8').decode('utf-8')
print(DIV2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意:div2 依然是一个列表,而且是只有一个元素的列表,存放了第一个 div 标签。

输出结果:

<div id="top">
            <span class="position" width="350">职位名称</span>
            <span>职位类别</span>
            <span>人数</span>
            <span>地点</span>
            <span>发布时间</span>
        </div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.4 获取属性为 id=‘even’ 的 div 标签

XPath 表达式://div[@id=“even”]

'''
3. 获取属性为 id='even' 的 div 标签
'''
# div3 是一个列表
div3 = html.xpath('//div[@id="even"]')
# 列表遍历,转化为字符串输出
for div in div3:
    d = etree.tostring(div, encoding='utf-8').decode('utf-8')
    print(d)
    print('*' * 50)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

输出结果:

<div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=33824&amp;keywords=python&amp;tid=87&amp;lid=2218">python开发工程师</a>
            </span>
            <span>技术类</span>
            <span>2</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        
**************************************************
<div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=31236&amp;keywords=python&amp;tid=87&amp;lid=2218">高级Python开发工程师</a>
            </span>
            <span>技术类</span>
            <span>2</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        
**************************************************
<div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=34531&amp;keywords=python&amp;tid=87&amp;lid=2218">Python数据开发工程师</a>
            </span>
            <span>技术类</span>
            <span>1</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        
**************************************************
<div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=31648&amp;keywords=python&amp;tid=87&amp;lid=2218">高级AI开发工程师</a>
            </span>
            <span>技术类</span>
            <span>4</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        
**************************************************
<div id="even">
            <span class="l square">
              <a target="_blank" href="position_detail.php?id=32217&amp;keywords=python&amp;tid=87&amp;lid=2218">Python开发(自动化运维方向)</a>
            </span>
            <span>技术类</span>
            <span>1</span>
            <span>上海</span>
            <span>2018-10-23</span>
        </div>
        
**************************************************
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

2.5 获取标签下的属性值

2.5.1 初步想法

XPath 表达式://div/@id//a/@href

'''
4. 获取标签下的属性值
'''
# div4 是一个列表
div4 = html.xpath('//div/@id')
print(div4)

# hrefs 是一个列表
hrefs = html.xpath('//a/@href')
print(hrefs)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

输出结果:

['top', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']
['position_detail.php?id=33824&keywords=python&tid=87&lid=2218', 'position_detail.php?id=29938&keywords=python&tid=87&lid=2218', 'position_detail.php?id=31236&keywords=python&tid=87&lid=2218', 'position_detail.php?id=31235&keywords=python&tid=87&lid=2218', 'position_detail.php?id=34531&keywords=python&tid=87&lid=2218', 'position_detail.php?id=34532&keywords=python&tid=87&lid=2218', 'position_detail.php?id=31648&keywords=python&tid=87&lid=2218', 'position_detail.php?id=32218&keywords=python&tid=87&lid=2218', 'position_detail.php?id=32217&keywords=python&tid=87&lid=2218', 'position_detail.php?id=34511&keywords=python&tid=87&lid=2218']
  • 1
  • 2
2.5.2 改进程序

很多时候,在获取属性时,我们不想要这样一个长长的列表(因为处理起来有点麻烦),如果我们需要获取一个 url 字符串,那该怎么办呢?

观察 HTML,发现 a 标签都在 div 标签里。我们可以先获取 div 标签(这样就会得到一个 div 列表),遍历这个列表,再在里面获取 a 标签,这样就可以分离出每一个 url 了。

先选取 div 标签://div(得到一个许多元素的列表)

然后在以上基础选取 a 标签:.//a/@href(得到多个元素只有一个的列表)

注意:.表示上一个路径,意思是在 div
标签下进行全局选取。如果直接写成//a/@href,意思是在整个页面下进行全局选取 a 标签。

# div4 是一个列表,从元素 1 开始取
div4 = html.xpath("//div")[1:]
for div in div4:
    url = div.xpath(".//a/@href")
    print(url)
  • 1
  • 2
  • 3
  • 4
  • 5

输出结果:

['position_detail.php?id=33824&keywords=python&tid=87&lid=2218']
['position_detail.php?id=29938&keywords=python&tid=87&lid=2218']
['position_detail.php?id=31236&keywords=python&tid=87&lid=2218']
['position_detail.php?id=31235&keywords=python&tid=87&lid=2218']
['position_detail.php?id=34531&keywords=python&tid=87&lid=2218']
['position_detail.php?id=34532&keywords=python&tid=87&lid=2218']
['position_detail.php?id=31648&keywords=python&tid=87&lid=2218']
['position_detail.php?id=32218&keywords=python&tid=87&lid=2218']
['position_detail.php?id=32217&keywords=python&tid=87&lid=2218']
['position_detail.php?id=34511&keywords=python&tid=87&lid=2218']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这时我们得到的是许多列表,但是每个列表只有一个元素(字符串),处理起来方便多了。所以可以继续改进,url 列表获取 0 号元素,直接得到字符串:

# div4 是一个列表,从元素 1 开始取
div4 = html.xpath("//div")[1:]
for div in div4:
    url = div.xpath(".//a/@href")[0]
    print(url)
  • 1
  • 2
  • 3
  • 4
  • 5

输出结果:

position_detail.php?id=33824&keywords=python&tid=87&lid=2218
position_detail.php?id=29938&keywords=python&tid=87&lid=2218
position_detail.php?id=31236&keywords=python&tid=87&lid=2218
position_detail.php?id=31235&keywords=python&tid=87&lid=2218
position_detail.php?id=34531&keywords=python&tid=87&lid=2218
position_detail.php?id=34532&keywords=python&tid=87&lid=2218
position_detail.php?id=31648&keywords=python&tid=87&lid=2218
position_detail.php?id=32218&keywords=python&tid=87&lid=2218
position_detail.php?id=32217&keywords=python&tid=87&lid=2218
position_detail.php?id=34511&keywords=python&tid=87&lid=2218
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.6 获取标签下的文本信息

假设我们想要获取 a 标签下的文本信息,那么:

先选取 div 标签://div(得到一个许多元素的列表)

然后在以上基础选取 a 标签的文本信息:.//a/text()(得到多个元素只有一个的列表)

'''
5. 获取标签下的文本
'''
# div5 是一个列表,从元素 1 开始取
div5 = html.xpath("//div")[1:]
for div in div5:
    work = div.xpath(".//a/text()")[0]
    print(work)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

输出结果:

python开发工程师
python后端
高级Python开发工程师
python架构师
Python数据开发工程师
高级图像算法研发工程师
高级AI开发工程师
后台开发工程师
Python开发(自动化运维方向)
Python数据挖掘讲师
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

写在后面

搞了一晚上和一个白天,因为使用 PyCharm 调用 lxml 库时输出的结果完全不符合预期,今天重装了一次 lxml 库后居然恢复正常了,一直没有搞懂是怎么回事…

暂时就写这么多吧。

---EOF---
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/109110
推荐阅读
相关标签
  

闽ICP备14008679号