爬虫基础之pyquery
爬虫程序中少不了解析库的使用,使用库来解析网页内容的话,效率会很高,常用的解析库有:
lxml
Beautiful Soup
pyquery
十里对三个库都稍微了解了一下,个人比较喜欢pyquery库
,当然这只是个人喜好问题,无关优劣。所以本文中十里将与您一起学习pyquery
库的简单使用。
安装
安装很简单,这里使用pip
包管理工具安装:
pip3 install pyquery
注: pip有时会很慢,可以使用国内源加速,这个需要的话自行google。
使用
初始化内容
pyquery
库可以打开本地html文件,可以初始化字符串,同样可以直接打开指定网址。
初始化字符串
可以编写一个html字符串内容传给PyQuery
,直接看代码:
from pyquery import PyQuery as pq
html = '''<html>
<div>
<p class='ppp'>hello, 5km!</p>
</div>
</html>
'''
d = pq(html)
print(d)
print(type(d))
运行结果:
<html>
<div>
<p class="ppp">hello, 5km!</p>
</div>
</html>
<class 'pyquery.pyquery.PyQuery'>
初始化文件
将上述代码中的html内容写入文件5km.html
,然后按照以下方式可以初始化html文件:
from pyquery import PyQuery as pq
d = pq(filename='5km.html')
print(d)
print(type(d))
执行代码后会发现结果与上述一样,说明成功初始化。
初始化链接
这里以http://www.httpbin.org
为例:
from pyquery import PyQuery as pq
d = pq(url='http://www.httpbin.org')
print(d)
print(type(d))
结果就会返回上述网址对应的html文件内容:
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>httpbin.org</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet"/>
...这里省略部分内容
...
</html>
<class 'pyquery.pyquery.PyQuery'>
CSS选择器
pyquery
支持基本的css选择器,可以按照css选择器的规则找到相应节点,为了方便展示后面的使用,从这儿开始使用文本方式初始化PyQuery
,使用网上常规html范例文本初始化:
from pyquery import PyQuery as pq
html = '''<div>
<ul id = '5km'>
<li class="item-0">first item</li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
'''
d = pq(html)
如果想获得class为 item-0 的li,可以:
result = d('#5km .item-0')
print(result)
print(type(result))
运行结果:
<li class="item-0">first item</li>
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
<class 'pyquery.pyquery.PyQuery'>
尝试其它的选择器使用,非常方便!
遍历节点
如上面CSS选择器的例子,会选择出三个符合条件的,那我们能不能遍历它们逐一做一些处理呢?当然是没问题了。返回结果会有一个items方法,此方法会得到一个结果对应的生成器,就可以使用for-in
进行遍历结果中的每一条li
节点了,使用方法如下:
for item in result.items():
print(item)
print(type(item))
结果:
<li class="item-0">first item</li>
<class 'pyquery.pyquery.PyQuery'>
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<class 'pyquery.pyquery.PyQuery'>
<li class="item-0"><a href="link5.html">fifth item</a></li>
<class 'pyquery.pyquery.PyQuery'>
查询节点
在上面例子中均打印了结果的类型,它们都是PyQuery
对象,包含了节点信息。它们具有查询节点的方法,可供获取子孙节点、父节点和兄弟节点。
子孙节点
子孙节点的查询可以使用find
和children
两种方法,不同点是,前者可以得到所有子孙节点,而后者只关心子节点信息。为了区分这两种的效果,这里稍微改动一下html
内容:
from pyquery import PyQuery as pq
html = '''<div>
<div id="container">
<ul id='5km'>
<li class="item-0">first item</li>
<li class="item-ol">
<ol class='test'>
<li>ol1</li>
<li>ol2</li>
</ol>
</li>
</ul>
</div>
</ddiv>
'''
d = pq(html)
所有子孙节点
使用find
方法查询ul
下的 li
节点,实现代码如下:
ul = d('#5km')
print(ul.find('li'))
运行结果:
<li class="item-0">first item</li>
<li class="item-ol">
<ol class="test">
<li>ol1</li>
<li>ol2</li>
</ol>
</li>
<li>ol1</li>
<li>ol2</li>
看到结果就明白了,此方法把ul
第二个直接子节点下的两个li
节点也查询并入查询结果了。下面我们看一下children
方法的效果。
直接子节点
利用children
方法查询ul
下的li
节点,当然也可以使用CSS选择器:
print(ul.children('li'))
运行结果:
<li class="item-0">first item</li>
<li class="item-ol">
<ol class="test">
<li>ol1</li>
<li>ol2</li>
</ol>
</li>
不出所料,结果中只有直接子节点,其实children
方法可以不加参数,就会返回所有的直接子节点。
祖先节点
按照继承的思路,查询祖先节点就是找父节点、父节点的父节点等等一直按照继承关系向上查询节点。有两个方法:parent
和 parents
,前者用来查找直接父节点,后者用来查询所有祖先节点。继续使用前面的d。
直接父节点
直接父节点可以通过parent
方法进行查询:
print(ul.parent())
运行结果:
<div id="container">
<ul id="5km">
<li class="item-0">first item</li>
<li class="item-ol">
<ol class="test">
<li>ol1</li>
<li>ol2</li>
</ol>
</li>
</ul>
</div>
此方法直接返回了ul
节点的直接父节点<div id='container'
的内容。
所有祖先节点
parents
方法可以查询所有祖先节点,可以使用CSS选择器,也可以不加参数使用:
print(ul.parents('div'))
查询祖先节点中所有的div
节点,返回结果:
<div>
<div id="container">
<ul id="5km">
<li class="item-0">first item</li>
<li class="item-ol">
<ol class="test">
<li>ol1</li>
<li>ol2</li>
</ol>
</li>
</ul>
</div>
</div><div id="container">
<ul id="5km">
<li class="item-0">first item</li>
<li class="item-ol">
<ol class="test">
<li>ol1</li>
<li>ol2</li>
</ol>
</li>
</ul>
</div>
可以看到得到了两层div
节点的内容。
兄弟节点
兄弟节点的获取需要使用方法siblings
,首先我们获取class
为item-ol
的li
节点,然后调用siblings
方法找到所有兄弟节点:
li = d('#5km .item-ol')
print(li.siblings())
运行结果:
<li class="item-0">first item</li>
class
为item-0
的节点即为结果。
获取节点信息
节点信息一般就是节点文本和节点的属性了,分别进行探索。
节点文本
节点文本的获取有两种方法:
text
:获取节点内所有文本及子孙节点的文本内容;html
:获取节点的html文本;
这里以class
为test
的ol
节点为例说明两个方法的使用:
ol = d('#5km .item-ol .test')
print(ol.text())
print(ol.html())
运行结果:
ol1
ol2
<li>ol1</li>
<li>ol2</li>
可以看到按照预期结果分别得到了所有文本信息和html文本。
节点属性
有两种方法可以获取节点属性:
- 使用节点的
attr
方法,参数传入待获取属性的名称,比如class
、id
、href
等,形如attr('class')
; - 使用节点
attr
属性的属性,点语法获取,形如attr.href
,这里要查询class
属性的值比较特殊,因为与python的关键词冲突,所以以此方法查询节点的class
属性的话,应该以attr.class_
的形式访问查询; - 作为字典的形式访问,以属性名作为键值访问,形如
attr['class']
举例说明:
print(ol.attr('class'))
print(ol.attr.class_)
print(ol.attr['class'])
运行结果:
test
test
test
上面用三种形式查询了ol
节点的class
属性。
总结
本文主要一起探索了一下pyquery
使用的冰山一角,主要集中的是初始化和读取的操作,其实还有修改节点的功能,因为爬虫程序中大部分还是只用查询解析功能,所以本文只简单列举了节点解析读取功能的具体操作,后面如果有新的总结会持续更新。