PyQuery详解

在之前写的爬虫入门里,PyQuery一笔带过,这次详细地讲一下。

为什么选择PyQuery?

Python爬虫解析库,主流的有

  • PyQuery
  • Beautifulsoup
  • Scrapy Selectors
  • 正则表达式。

PyQuery和scrapy Selectors都是基于lxml模块,而lxml和正则表达式都是C语言写的,只有Beautifulsoup是用纯Python编写的,所以在实测中,Beautifulsoup 的解析速度比其他几种慢了5倍以上!

正则表达式的构造稍微复杂一点,一般在结构化的网页中没必要用正则(易出错)。Scrapy Selectors支持css,xpath以及正则表达式,PyQuery只支持css(我最开始学的是xpath,后来觉得css语法更精简一些)。Scrapy Selector中的css语法和PyQuery中的略有不同,本文以PyQuery为例(不用Scrapy框架的话,PyQuery就够用了)

如何使用?

首先在命令行里 pip install pyquery 安装一下

我们以果壳首页为例,首先引入,并将源代码实例化

import requests
from pyquery import PyQuery as pq

url = 'https://www.guokr.com/'
r = requests.get(url)
#实例化
doc = pq(r.text)

获取文本

例如你想要各个板块的名字

image

通过f12查看源代码,你发现板块名都在class值为content-title的h2标签下

[图片上传失败...(image-ea4892-1548221385522)]

在PyQuery中,class的值写在小数点 . 后面,标签直接写(ID是写在#后面)

print(doc('h2.content-title'))

[图片上传失败...(image-8ce1d6-1548221385522)]

于是所有满足条件的源代码都出来了,获取标签的文本内容用text()

print(doc('h2.content-title').text())

想遍历的话,

lis = doc('h2.content-title').items()
for li in lis:
    print(li.text())
image

假设我们想要获取所有标题

[图片上传失败...(image-eb88cb-1548221385522)]

看源代码会发现 ,小标题的内容都在div.content下面的ul标签 下面的 第二个li标签 开始(通过缩进来看嵌套关系),而第一个li标签里面是大标题的内容

[图片上传失败...(image-84ab15-1548221385522)]

#用空格表示子孙节点
lis = doc('div.content ul li').items()
#lis = doc('div.content li').items()
for i in lis:
    print(i.text())

空格表示子孙节点,只要在div.content标签下面的节点,都能获取到

所以上面的代码可以省略ul标签,直接到li标签

有时候标签会有多个类名的情况,例如(我随便构造一个):

[图片上传失败...(image-cd7cd3-1548221385522)]

假设类名为cont的标签不唯一,也就是通过cont不能准确地定位这一个标签,还需要加上其他类名

print(doc('div.cont.a.b.c.d'))

[图片上传失败...(image-759eee-1548221385522)]

[图片上传失败...(image-d6955e-1548221385522)]

标签里的空格表示并列,表示这个div标签有cont,a,b,c,d这五个类名,但在css语法里空格表示嵌套,所以我们要添加其他类名的时候不能输入空格,而是直接用小数点来添加其他类名

获取属性

前面说了获取文本用text(),现在介绍获取属性的方法,即attr("属性名"),比方说我们要获取所有标题的链接,一般来说链接都在href属性里

[图片上传失败...(image-db7abc-1548221385522)]

lis = doc('div.content li').items()
for i in lis:
    print(i.text(),i('a').attr('href'))

[图片上传失败...(image-245d6a-1548221385522)]

剩下的一些选择器方法就不赘述了,列出来大家试一下应该就能明白了

lis = doc('div.content ul li')
#父节点,包含父节点的所有子孙节点的内容
#相当于
#print(doc('div.content ul'))
print(lis.parent())
#祖先节点,就相当于所有源代码了
print(lis.parents())
#兄弟节点,即同级节点,不包含自己
print(lis.siblings)
其他技巧

1.伪类选择器

如果想要每个版块的第一条小标题的话

#第二个标签
lis = doc('div.content li:nth-child(2)').items()
for i in lis:
    print(i.text(),i('a').attr('href'))

第一个a标签的语法是 a:first-child,最后一个是a:last-child,其它位置的语法如上图所示,第几个括号里就是几(当然第一个你也可以写成 li:nth-child(1))

类似地,如果你想要只要小标题,也就是从第二个li开始到最后一个li

#div.content 下面第二个(含)之后的li标签
lis = doc('div.content li:gt(1)').items()
for i in lis:
    print(i.text(),i('a').attr('href'))

gt就是greater than,大于的意思,lt (less than)是小于

还可以用伪类选择器来筛选文本

lis = doc('div.content ul').items()
for i in lis:
    #文本包含问号的li标签
    print(i("li:contains('?')").text())

[图片上传失败...(image-4378d9-1548221385522)]

2.修改标签属性

如果我只想要小标题,这里再介绍一种方法

从源代码来看,想要所有小标题就是要排除ul标签下面的第一个li标签,通过观察发现它的特点就是类名(class值)为content-article,而其它li标签没有,所以我们可以利用这点

[图片上传失败...(image-e3208f-1548221385522)]

#用remove把特定标签移除,然后再进行遍历
lis = doc('div.content ul').remove('.content-article').items()
for i in lis:
    print(i.text())

PyQuery里还有一些方法,比如修改属性,增加css之类的一些使用率较低的就不介绍了,详情可参考pyquery官方文档的 PyQuery complete API

直接在Chrome里调试

其实我们的Chrome浏览器自带css的查询方法,按f12或者右键检查,打开Elements面板,按ctrl+f,

[图片上传失败...(image-1d0031-1548221385522)]

这里支持xpath,css语法,以及普通的字符查找

[图片上传失败...(image-b79f66-1548221385522)]

要注意的是右边的数字,显示的是满足条件的标签数量,可以按向下的箭头过一遍,看看是不是自己想要的信息。

稍微认真写一下就有这么多内容,看来这篇详解还是有点意义的,感谢观看!


公众号.jpg
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容