Python爬虫-PyQuery
一些看法
关于数据提取的四个主流方法就回顾完了,当然不用也不必全会。我个人认为正则是一定要OK的,其余三个拣一个上手即可。剩下部分,总得达到“开书了然”的境界吧。毕竟说不定什么时候就需要阅览别人的代码,你怎么管得找人家用xpath呢还是用PyQuery呢?
这是最后一次在句子迷实战,此次目标书籍:《年华是无效信》——是我钟爱!
使用
from pyquery import PyQuery as pq
doc = pq(html)
语法
初始化
- 除了直接初始化拿到的网页,还可以有以下两种方法
a.pq(url="")
直接获取网页(不建议,没有隐藏爬虫信息吧)
b.pq(filename="")
针对本地文件
<html><head><title>The Dormouse's story</title>title></head>head>
<body>
<p class="title"><b>The Dormouse's story</b>b></p>p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a>a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>a>;
and they lived at the bottom of a well.</p>p>
<p class="story">...</p>p>
下面,仍用之前使用过的残缺的爱丽丝文档演示
选择标签
doc("p")
直接选择p标签doc(".title")
通过类名选择标签doc("#link1")
通过id名选择标签- 如果需要,可以一级一级的筛选
doc("body .story #link3")
表示body标签下class为story的标签、下的id为link3的标签 如果通过标签寻找返回太多,需要标签中其他属性值来精确定位,可以参数里多个值,中间不需要空格
doc("a.sister#link2")
(为什么我只返回两个?因为之前忘了,现在才加的,而我已经移除了id=#link1的标签了)find()
查找所有符合的标签,可以标签名,类,idchildren()
返回子标签,且只返回子标签(不管孙子标签)parent()
返回父标签,parents()
返回父级以上标签siblings()
返回兄弟标签
遍历
doc("a").items()
返回的是一个迭代器
对标签操作
上述操作之后拿到的是由对象组成的列表,现在我们要对它进一步操作
doc.(".title").html()
class为title的标签下的内容
需要注意的是,如果返回的列表中对象不止一个,该方法默认只对第一个起作用;并且同BeautifulSoup一样,会自行补充缺失的标签。所以使用时,最好精确到返回对象只有一个,除非你很清楚自己在做什么- 获取属性值的两种方法
doc("#link1").attr("href")
或者doc("#link1".attr.href)
- 也可以修改属性的值
doc("#link1").attr("href", "baidu.com")
如果标签的属性存在,就修改属性的值;如果属性不存在,就添加该属性和对应的值 - 也能删除你定位的标签
doc("#link1").remove()
- 提取标签中的文本信息
doc("#link2").text()
- 增删标签的class值
doc("#link2").addClass()
/doc("#link2").removeClass()
伪类选择器
为了更精确定位元素,还有以下操作
1. doc("p:first-child")
定位第一个p标签
2. doc("p:last-child")
定位第最后一个p标签
3. doc("p:gt(2)")
定位索引大于2的p标签(从0开始计数)
4. doc("p:nth-child(2)")
定位第二个p标签
5. doc("p:nth-child(2n)")
定位索引为偶数的p标签
6. doc("p:contains(story)")
定位文本信息中有“story”的p标签
*eq()的使用
区别于BeautifulSoup,我们拿到返回列表之后,不能单纯的使用列表的索引方式取出列表中的对象进行操作,这样返回的是字符串类型,需要用eq()
代码
网址目标:句子迷。
def parse_html(html):
data = {}
doc = pq(html)
sentences = doc(".xlistju")
loveds = doc(".views-field-ops a.flag-action")
comments = doc(".comment-link")
# 对于这种查找结果直接返回列表,最好保存数据前打印各自的长度
# 网页中可能出现class值相同,但不是需要的标签
with open("Invalid_letter.txt", "a", encoding="utf-8") as ob:
for i in range(len(sentences)):
data["sentence"] = sentences.eq(i).text()
data["loved"] = loveds.eq(i).text()
data["comment"] = comments.eq(i).text()
ob.write(json.dumps(data, ensure_ascii=False))
ob.write("\n")
完整代码已经上传GitHub,包括前面使用xpth,”美丽汤”,正则的实战案例,放在一起可以比较四个优劣。