1.pyquery概述:
PyQuery是一个类似于jQuery的解析网页工具,使用lxml操作xml和html文档,它的语法和jQuery很像。和XPATH,BeautifulSoup比起来,PyQuery更加灵活,提供增加节点的class信息,移除某个节点,提取文本信息等功能。
使用pip安装pyquery库。
pip install pyquery
一般采用如下方式引用:
from pyquery import PyQuery as pq
更多内容可以查看pyquery官方文档。
2.初始化PyQuery对象:
pyquery
对HTML
文档的所有操作都需要PyQuery
对象来完成,初始化PyQuery
对象主要有三种方式,分别是通过网址、字符串和文件名创建。
2.1 URL初始化
首先引入PyQuery类,然后将要解析的URL网址当做参数传递给PyQuery类,这样就完成了初始化。再将初始化的对象传入CSS选择器。
from pyquery import PyQuery as pq
doc = pq(url='https://www.baidu.com' , encoding='utf-8')
print(type(doc))
print('---------')
print(doc)
print('---------')
print(doc('title'))
运行结果如下:
<class 'pyquery.pyquery.PyQuery'>
---------
<html> <head><meta http-equiv="content-type" content="text/html;charset=utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=Edge"/><meta content="always" name="referrer"/><link rel="stylesheet" type="text/css" href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css"/><title>百度一下,你就知道</title></head> <body link="#0000cc"> <div id="wrapper"> <div id="head"> <div class="head_wrapper"> <div class="s_form"> <div class="s_form_wrapper"> <div id="lg"> <img hidefocus="true" src="//www.baidu.com/img/bd_logo1.png" width="270" height="129"/> </div> <form id="form" name="f" action="//www.baidu.com/s" class="fm"> <input type="hidden" name="bdorz_come" value="1"/> <input type="hidden" name="ie" value="utf-8"/> <input type="hidden" name="f" value="8"/> <input type="hidden" name="rsv_bp" value="1"/> <input type="hidden" name="rsv_idx" value="1"/> <input type="hidden" name="tn" value="baidu"/><span class="bg s_ipt_wr"><input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off" autofocus="autofocus"/></span><span class="bg s_btn_wr"><input type="submit" id="su" value="百度一下" class="bg s_btn" autofocus=""/></span> </form> </div> </div> <div id="u1"> <a href="http://news.baidu.com" name="tj_trnews" class="mnav">新闻</a> <a href="https://www.hao123.com" name="tj_trhao123" class="mnav">hao123</a> <a href="http://map.baidu.com" name="tj_trmap" class="mnav">地图</a> <a href="http://v.baidu.com" name="tj_trvideo" class="mnav">视频</a> <a href="http://tieba.baidu.com" name="tj_trtieba" class="mnav">贴吧</a> <noscript> <a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1" name="tj_login" class="lb">登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');
</script> <a href="//www.baidu.com/more/" name="tj_briicon" class="bri" style="display: block;">更多产品</a> </div> </div> </div> <div id="ftCon"> <div id="ftConw"> <p id="lh"> <a href="http://home.baidu.com">关于百度</a> <a href="http://ir.baidu.com">About Baidu</a> </p> <p id="cp">©2017 Baidu <a href="http://www.baidu.com/duty/">使用百度前必读</a> <a href="http://jianyi.baidu.com/" class="cp-feedback">意见反馈</a> 京ICP证030173号 <img src="//www.baidu.com/img/gs.gif"/> </p> </div> </div> </div> </body> </html>
---------
<title>百度一下,你就知道</title>
2.2 字符串初始化
直接将HTML内容当做初始化参数递给PyQuery类。
html_text = """
<div>
<div>
<a>
The Dormouse's story
<p>this is something</p>
</a>
</div>
</div>
"""
from pyquery import PyQuery as pq
doc = pq(html_text)
print(type(doc))
print('---------')
print(doc)
print('---------')
# 选择a节点
print(doc('a'))
print('---------')
# 选择p节点
print(doc('p'))
运行结果如下:
<class 'pyquery.pyquery.PyQuery'>
---------
<div>
<div>
<a>
The Dormouse's story
<p>this is something</p>
</a>
</div>
</div>
---------
<a>
The Dormouse's story
<p>this is something</p>
</a>
---------
<p>this is something</p>
2.3 文件初始化
可以传递本地的文件,此时只需要使用参数filename
指定本地文件。
from pyquery import PyQuery as pq
doc = pq(filename='index.html')
print(type(doc))
print('---------')
print(doc)
print('---------')
print(doc('a'))
print('---------')
print(doc('p'))
运行结果如下:
<class 'pyquery.pyquery.PyQuery'>
---------
<div>
<div>
<a>
The Dormouse's story
<p>this is something</p>
</a>
</div>
</div>
---------
<a>
The Dormouse's story
<p>this is something</p>
</a>
---------
<p>this is something</p>
3.查找节点
以如下html为例:
html_text = """
<html>
<head>
<title>
The Dormouse's story
<p>this is something</p>
</title>
</head>
<body>
<div class="story" id="container">
<ul class="list_elements ul_first" id="list_eng" name="elements">
<li class="item_1 item_active">
<a href='link1.html'><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href='link2.html'>BBB</a></li>
<li class="item_3"><a href='link3.html'><span>CCC</span></a></li>
<li class="item_4"><a href='link4.html'>DDD</a></li>
</ul>
</div>
</body>
</html>
"""
3.1 子节点
children()
方法
可以通过已经查找的节点,查找这个标签下的直接子节点,而不用从头开始查找。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul')
# 获取ul节点下的所有直接子节点
print(type(item.children()))
print('---------')
print(item.children())
print('---------')
# 通过传入CSS选择器的方式,筛选子节点
print(item.children('.item_two'))
运行结果如下:
<class 'pyquery.pyquery.PyQuery'>
---------
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
---------
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
find()
方法
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul')
print(item.find('*'))
print('---------')
print(item.find('li'))
print('---------')
print(item.find('a'))
print(item.find('a').text())
运行结果如下:
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<a href="link1.html"><span class="blod">AAA</span></a>
<span class="blod">AAA</span><li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<a href="link2.html">BBB</a><li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<a href="link3.html"><span>CCC</span></a><span>CCC</span><li class="item_4"><a href="link4.html">DDD</a></li>
<a href="link4.html">DDD</a>
---------
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
---------
<a href="link1.html"><span class="blod">AAA</span></a>
<a href="link2.html">BBB</a><a href="link3.html"><span>CCC</span></a><a href="link4.html">DDD</a>
AAA BBB CCC DDD
3.2 父节点
使用parent()
方法获取某个节点的父节点。
使用parents()
方法获取某个节点的祖先节点。
也可以通过传入CSS选择器的方式,筛选节点。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul .item_active a')
print('当前选择的节点为:\n' , item)
print('---------')
print('当前节点的父节点为:\n' , item.parent())
print('---------')
print('当前节点的祖先节点为:\n' , item.parents())
print('---------')
print('class属性为story的祖先节点为:\n' , item.parents('.story'))
运行结果如下:
当前选择的节点为:
<a href="link1.html"><span class="blod">AAA</span></a>
---------
当前节点的父节点为:
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
---------
当前节点的祖先节点为:
<html>
<head>
<title>
The Dormouse's story
<p>this is something</p>
</title>
</head>
<body>
<div class="story" id="container">
<ul class="list_elements ul_first" id="list_eng" name="elements">
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
</ul>
</div>
</body>
</html><body>
<div class="story" id="container">
<ul class="list_elements ul_first" id="list_eng" name="elements">
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
</ul>
</div>
</body>
<div class="story" id="container">
<ul class="list_elements ul_first" id="list_eng" name="elements">
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
</ul>
</div>
<ul class="list_elements ul_first" id="list_eng" name="elements">
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
</ul>
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
---------
class属性为story的祖先节点为:
<div class="story" id="container">
<ul class="list_elements ul_first" id="list_eng" name="elements">
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
</ul>
</div>
3.3 兄弟节点
使用siblings()
方法获取某个节点的兄弟节点。
也可以通过传入CSS选择器的方式,筛选节点。
from pyquery import PyQuery as pq
# ------兄弟节点
doc = pq(html_text)
item = doc('ul .item_active')
print(item)
print('---------')
print(item.siblings())
运行结果如下:
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
---------
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
4.获取信息:
选择到节点后,需要获取该节点所包含的信息,主要为节点属性、节点内部文本。
4.1 获取节点属性
- 调用attr()方法获取节点属性
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul')
print(item)
print('---------')
# 获取节点的name属性值
print(item.attr('name'))
print('---------')
# 获取节点的class属性值
print(item.attr('class'))
print('---------')
# 获取节点的id属性值
print(item.attr('id'))
运行结果如下:
<ul class="list_elements ul_first" id="list_eng" name="elements">
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
</ul>
---------
elements
---------
list_elements ul_first
---------
list_eng
- 调用attr属性获取节点属性
需要注意的是class
在Python中是关键字,因此在获取节点class
属性时需使用class_
。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul')
print(item)
# 获取节点的name属性值
print(item.attr.name)
print('---------')
# 获取节点的class属性值
print(item.attr.class_)
print('---------')
# 获取节点的id属性值
print(item.attr.id)
运行结果如下:
<ul class="list_elements ul_first" id="list_eng" name="elements">
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
</ul>
elements
---------
list_elements ul_first
---------
list_eng
- 获取多个节点的属性
当返回结果包含多个节点时,调用attr方法,只返回第一个节点的属性值。如果要获取多个节点的属性值,需要使用遍历的方式获取。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('a')
print(item)
print('---------')
# 当返回结果包含多个节点时,调用attr方法,只返回第一个节点的属性值。
print(item.attr('href'))
print('---------')
# 如果要获取多个节点的属性值,需要使用遍历的方式获取。
for i in item.items():
print(i.attr('href'))
运行结果如下:
<a href="link1.html"><span class="blod">AAA</span></a>
<a href="link2.html">BBB</a><a href="link3.html"><span>CCC</span></a><a href="link4.html">DDD</a>
---------
link1.html
---------
link1.html
link2.html
link3.html
link4.html
4.2 获取节点内部文本
- 获取节点内部文本
调用text()
方法获取节点内部文本,调用html()
方法获取节点内部html文本。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul .item_active')
print(item)
print('---------')
print(item.text())
print('---------')
print(item.html())
运行结果如下:
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
---------
AAA
---------
<a href="link1.html"><span class="blod">AAA</span></a>
- 获取多个节点的文本
当返回结果包含多个节点时,text()
方法返回的是内部所有节点的内部纯文本,各个节点文本内容由空格分隔。
而html()
方法返回的是第一个节点内部的html文本,如若获取所有节点的html文本,就需要遍历所以节点。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul li')
print(item)
print('---------')
print(item.text())
print('---------')
print(item.html())
print('---------')
for i in item.items():
print(i.html())
print('---------')
运行结果如下:
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
---------
AAA BBB CCC DDD
---------
<a href="link1.html"><span class="blod">AAA</span></a>
---------
<a href="link1.html"><span class="blod">AAA</span></a>
---------
<a href="link2.html">BBB</a>
---------
<a href="link3.html"><span>CCC</span></a>
---------
<a href="link4.html">DDD</a>
---------
5.节点操作:
5.1 增加删除节点class属性
调用remove_class()
方法,删除节点的class属性。
调用add_class()
方法,增加节点的class属性。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul .item_2')
print(item)
print('---------')
item.remove_class('item_two')
print(item)
print('---------')
item.add_class('item_two')
print(item)
运行结果如下:
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
---------
<li class="item_2"><a href="link2.html">BBB</a></li>
---------
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
5.2 修改节点属性
调用atrr()
方法对节点属性进行操作。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul .item_3')
print(item)
print('---------')
item.attr('name' , 'list_ccc')
print(item)
print('---------')
item.attr('id' , 'list_3')
print(item)
运行结果如下:
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
---------
<li class="item_3" name="list_ccc"><a href="link3.html"><span>CCC</span></a></li>
---------
<li class="item_3" name="list_ccc" id="list_3"><a href="link3.html"><span>CCC</span></a></li>
5.3 修改节点文本
调用text()
方法修改节点内部纯文本内容。
调用html()
方法修改节点内部html文本内容。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul .item_3')
print(item)
print('---------')
item.text('GGG')
print(item)
print('---------')
item.html('<p>GGG</p>')
print(item)
运行结果如下:
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
---------
<li class="item_3">GGG</li>
---------
<li class="item_3"><p>GGG</p></li>
5.4 修改节点css
调用css()
方法修改节点css内容。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('ul .item_3')
print(item)
print('---------')
item.css('font-size' , '24px')
print(item)
运行结果如下:
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
---------
<li class="item_3" style="font-size: 24px"><a href="link3.html"><span>CCC</span></a></li>
5.4 删除节点
调用remove()
方法删除节点。
from pyquery import PyQuery as pq
doc = pq(html_text)
item = doc('title')
print(item)
print('---------')
print(item.text())
print('---------')
item.find('p').remove()
print(item)
print('---------')
print(item.text())
运行结果如下:
<title>
The Dormouse's story
<p>this is something</p>
</title>
---------
The Dormouse's story
this is something
---------
<title>
The Dormouse's story
</title>
---------
The Dormouse's story
6.伪类选择器:
CSS选择器之所以功能强大,是因为其包含了多种伪类选择器。
方法 | 说明 |
---|---|
:first-child | 获取第一个节点 |
:last-child | 获取最后一个节点 |
:nth-child(N) | 获取第N个节点,N=1,2,… |
:nth-child(2n) | 获取偶数位置的全部节点 |
:nth-child(2n-1) | 获取奇数位置的全部节点 |
:gt(N) | 获取索引大于N的节点,N=0,1,… |
:contains('str') | 获取文本包含”str”的节点 |
from pyquery import PyQuery as pq
doc = pq(html_text)
# 获取所有li节点
print(doc('li'))
print('---------')
# 获取第一个li节点
print(doc('li:first-child'))
print('---------')
# 获取最后一个li节点
print(doc('li:last-child'))
print('---------')
# 获取第二个li节点
print(doc('li:nth-child(2)'))
print('---------')
# 获取偶数位置上的li节点
print(doc('li:nth-child(2n)'))
print('---------')
# 获取奇数位置上的li节点
print(doc('li:nth-child(2n-1)'))
print('---------')
# 获取第二个li节点
print(doc('li:gt(1)'))
print('---------')
# 获取包含CCC文本的li节点
print(doc('li:contains(CCC)'))
print('---------')
运行结果如下:
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
---------
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
---------
<li class="item_4"><a href="link4.html">DDD</a></li>
---------
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
---------
<li class="item_2 item_two"><a href="link2.html">BBB</a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
---------
<li class="item_1 item_active">
<a href="link1.html"><span class="blod">AAA</span></a>
</li>
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
---------
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
<li class="item_4"><a href="link4.html">DDD</a></li>
---------
<li class="item_3"><a href="link3.html"><span>CCC</span></a></li>
---------