Crawler - pyquery解析模块

一、pyquery安装与介绍


1.安装pyquery

  • pip install pyquery
  • #pyquery依赖cssselect和lxml包

2.pyquery简介
pyquery是一个类似jquery的python库,它实现能够在xml文档中进行jQuery查询,pyquery使用lxml解析器进行快速在xml和html文档上操作,它提供了和jQuery类似的语法来解析HTML文档,支持CSS选择器。

二、pyquery对象初始化


1.字符串初始化
from pyquery import PyQuery as pq

html='''
<div>
    <ul>
         <li class="item-0"><a href="link1.html">第一个</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-0"><a href="link5.html">a属性</a>
     </ul>
 </div>
'''
doc=pq(html)   #初始化并创建pyquery对象
print(type(doc))
print(doc('ul').text())

2.url初始化
from pyquery import PyQuery as pq
doc=pq(url='https://www.cnblogs.com/zhangxinqi/p/9218395.html')
print(type(doc))
print(doc('title'))

PyQuery能够从url加载一个html文档,之际上是默认情况下调用python的urllib库去请求响应,如果requests已安装的话它将使用requests来请求响应,使用request的请求参数来构造请求了,实际请求如下:
from pyquery import PyQuery as pq
import requests
doc=pq(requests.get(url='https://www.cnblogs.com/zhangxinqi/p/9218395.html').text)
print(type(doc))
print(doc('title'))

3.文件初始化
from pyquery import PyQuery as pq
doc=pq(filename='demo.html',parser='html')
#doc=pq(open('demo.html','r',encoding='utf-8').read(),parser='html') 
#注意:在读取有中文的HTML文件时,请使用此方法,否则会报解码错误
print(type(doc))
print(doc('p'))


三、CSS选择器与查找节点


1.CSS选择器
在使用属性选择器中,使用属性选择特定的标签,标签和CSS标识必须引用为字符串,它会过滤筛选符合条件的节点打印输出,返回的是一个PyQuery类型对象
from pyquery import PyQuery as pq
import requests
html='''
<div id="container">
    <ul class="list">
         <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>
'''
doc=pq(html,parser='html')
print(doc('#container .list .item-0 a'))
print(doc('.list .item-1'))

结果:
print(doc('#container .list .item-0 a'))
<a href="link3.html"><span class="bold">third item</span></a><a href="link5.html">fifth item</a>
print(doc('.list .item-1'))
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>

扫描二维码关注公众号,回复: 12412207 查看本文章

2.CSS用法详解

语法

说明

*

选择所有节点

#container

选择id为container的节点

.container

选择所有class包含container的节点

div,p

选择所有 div 元素和所有 p 元素

li a

选取所有li 下所有a节点

ul + p

选取ul后面的第一个p元素

div#container > ul

选取id为container的div的第一个ul子元素

ul ~p

选取与ul相邻的所有p元素

a[title]

选取所有有title属性的a元素

a[href=”http://baidu.com”]

选取所有href属性为http://baidu.com的a元素

a[href*=”baidu”]

选取所有href属性值中包含baidu的a元素

a[href^=”http”]

选取所有href属性值中以http开头的a元素

a[href$=”.jpg”]

选取所有href属性值中以.jpg结尾的a元素

input[type=radio]:checked

选择选中的radio的元素

div:not(#container)

选取所有id为非container 的div属性

li:nth-child(3)

选取第三个li元素

li:nth-child(2n)

选取第偶数个li元素

a::attr(href)

选取a标签的href属性

a::text

选取a标签下的文本

#container 选择id为container的元素

.container 选择所有class包含container的元素

* 选择所有元素

div a 选取所有div下所有a元素

ul + p 选取ul后面的第一个p元素

ul ~p 选取与ul相邻的所有p元素

a:nth-child(2) 选取下面第二个标签,如果是a的话则选取,不是则不取

a:nth-child(2n) 选取第偶数个a元素

a:nth-child(2n+1) 选取第奇数个a元素

li.multi-chosen > a 选取class为multi-chosen的li的所有a元素

a[title] 选取所有拥有title属性的a元素

a[href=”https://www.lagou.com”] 选取所有href属性为https://www.lagou.com的a元素

a[href*=”www.lagou.com”] 选取所有href属性值中包含www.lagou.com的a元素

a[href^=”http”] 选取所有href属性值中以http开头的a元素

a[href$='.jap'] 选取所有href属性值以.jpg结尾的a元素

div:not(#content-container) 选取所有id为非content-container的div

3.CSS查找节点

PyQuery使用查询函数来查询节点,同jQuery中的函数用法完全相同

(1)查找子节点和子孙节点

find()的查找范围是节点的所有子孙节点,若只想查找子节点,用children()

使用find()方法获取子孙节点,children()获取子节点,使用以上的HTML代码测试

from pyquery import PyQuery as pq import requests doc=pq(html,parser='html') print('find:',doc.find('a')) print('children:',doc('li').children('a'))

(2)获取父节点和祖先节点

parent()方法获取父节点,parents()获取祖先节点

doc(.list).parent() doc(.list).parents()

如果筛选某个祖先节点的话,可以向parents()方法传入CSS选择器,如下:

doc(.list).parents('.wrap')

(3)获取兄弟节点

siblings()方法用来获取兄弟节点

doc('.list .item-0 .active').siblings()

上语句返回active节点的所有兄弟节点,若筛选某个兄弟节点,则可传入CSS选择器即可继续匹配

doc('.list .item-0 .active').siblings('.active')

四、遍历与获取信息

 1.遍历

使用items()来遍历所有节点,它会返回一个生成器,循环得到的每个节点类型依然是PyQuery类型,所以我们可以继续方法来选择节点或属性,内容等。

from pyquery import PyQuery as pq

doc=pq(html)

lis=doc('li').items() for i in lis: print(i('a')) #继续获取节点下的子节点

遍历其中的对象,还可以调用前面所说的方法进行选择,如css,查找父子节点等

2.获取信息

比较重要的信息,一是获取属性,二是获取文本

(1)获取属性

提取到某个PyQuery类型的节点后,就可以调用attr()方法来获取属性

attr()方法用来获取属性,如返回的结果有多个时可以调用items()方法来遍历获取

from pyquery import PyQuery as pq
doc=pq(html)
a=doc('.item-0 .active a') 
print(a.attr('href'))   #结果:link3.html
此外,也可以通过调用 attr属性来获取属性,用法如下:
print(a.attr.href) #结果:link3.html

遍历获取所有a的节点属性
from pyquery import PyQuery as pq
doc = pq(html)
a = doc ('a')
for item in a.items():
    print(item.attr('href'))

(2)获取信息
text()方法用来获取纯文本内容,不包括HTML文本内容,若想返回包括HTML的文本内容可以使用html()方法,如果结果有多个,text()方法会方法所有节点的文本信息内容并将它们拼接用空格分开返回字符串内容,html()方法只会返回第一个节点的HTML文本,如果要获取所有就需要使用items()方法来遍历获取了
from pyquery import PyQuery as pq
html='''
<div id="container">
    <ul class="list">
         <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>
'''
doc=pq(html,parser='html')
print('text:',doc('li').text())  #获取li节点下的所有文本信息
lis=doc('li').items()
for i in lis:
    print('html:',i.html()) #获取所有li节点下的HTML文本

#结果
text: first item second item third item fourth item fifth item
html: first item
html: <a href="link2.html">second item</a>
html: <a href="link3.html"><span class="bold">third item</span></a>
html: <a href="link4.html">fourth item</a>
html: <a href="link5.html">fifth item</a>
 
 五、节点操作与伪类选择器
 1.节点操作
pyquery提供了一系列方法来对节点进行动态修改,如添加一个class,移除某个节点,修改某个属性的值
addClass()增加Class,removeClass()删除Class
attr()增加属性和值,text()增加文本内容,html()增加HTML文本,remove()移除

from pyquery import PyQuery as pq
import requests
html='''
<div id="container">
    <ul class="list">
         <li id="1">first item</li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-2 active"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-3 active"><a href="link4.html">fourth item</a></li>
         <li class="item-4"><a href="link5.html">fifth item</a></li>
     </ul>
 </div>
'''
doc=pq(html,parser='html')
print(doc('#1'))
print(doc('#1').add_class('myclass'))  #增加Class
print(doc('.item-1').remove_class('item-1'))  #删除Class
print(doc('#1').attr('name','link'))  #添加属性name=link
print(doc('#1').text('hello world'))   #添加文本
print(doc('#1').html('<span>changed item</span>')) #添加HTML文本
print(doc('.item-2.active a').remove('span'))  #删除节点

#结果
<li id="1">first item</li>
<li id="1" class="myclass">first item</li>         
<li class=""><a href="link2.html">second item</a></li>         
<li id="1" class="myclass" name="link">first item</li>         
<li id="1" class="myclass" name="link">hello world</li>         
<li id="1" class="myclass" name="link"><span>changed item</span></li>
<a href="link3.html"/>

after()在节点后添加值
before()在节点之前插入值
append()将值添加到每个节点
contents()返回文本节点内容
empty()删除节点内容
remove_attr()删除属性
val()设置或获取属性值
另外还有很多节点操作方法,它们和jQuery的用法完全一致,详细请参考:http://pyquery.readthedocs.io/en/latest/api.html

2.伪类选择器
CSS选择器支持多种多样的伪类选择器,如:选择第一个节点,最后一个节点,奇偶数节点等。
#!/usr/bin/env python
#coding:utf-8
from pyquery import PyQuery as pq
html='''
<div id="container">
    <ul class="list">
         <li id="1">first item</li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-2 active"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-3 active"><a href="link4.html">fourth item</a></li>
         <li class="item-4"><a href="link5.html">fifth item</a></li>
     </ul>
     <div><input type="text" value="username"/></div> 
</div>
'''
doc=pq(html,parser='html')
print('第一个li节点:',doc('li:first-child')) #第一个li节点
print('最后一个li节点:',doc('li:last_child')) #最后一个li节点
print('第二个li节点:',doc('li:nth-child(2)'))  #第二个li节点
print('第三个之后的所有li节点:',doc('li:gt(2)'))  #第三个之后的所有li节点
print('偶数的所有li节点:',doc('li:nth-child(2n)'))  #偶数的所有li节点
print('包含文本内容的节点:',doc('li:contains(second)')) #包含文本内容的节点
print('索引第一个节点:',doc('li:eq(0)'))
print('奇数节点:',doc('li:even'))
print('偶数节点:',doc('li:odd'))

#结果
第一个li节点: <li id="1">first item</li>         
最后一个li节点: <li class="item-4"><a href="link5.html">fifth item</a></li>     
第二个li节点: <li class="item-1"><a href="link2.html">second item</a></li>
第三个之后的所有li节点: <li class="item-3 active"><a href="link4.html">fourth item</a></li>
         <li class="item-4"><a href="link5.html">fifth item</a></li>
偶数的所有li节点: <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-3 active"><a href="link4.html">fourth item</a></li>
包含文本内容的节点: <li class="item-1"><a href="link2.html">second item</a></li>
索引第一个节点: <li id="1">first item</li>
奇数节点: <li id="1">first item</li>
         <li class="item-2 active"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-4"><a href="link5.html">fifth item</a></li>
偶数节点: <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-3 active"><a href="link4.html">fourth item</a></li>

猜你喜欢

转载自blog.csdn.net/helunqu2017/article/details/112756834