0.前言
本文为《Python3网络爬虫开发实战》的学习笔记。先是跟着书上敲了一遍抓取猫眼排行的代码,但是感觉re正则表达式用起来不大方便,后面自己用PyQuery解析了下。
1.书上的例子(requests+re)目标地址https://maoyan.com/board/4,top100的排行分为了十页,每个分页只是url增加了一个offset参数,假如要查看top21-30,那么url就是https://maoyan.com/board/4?offset=20,以此类推。通过浏览器查看html内容,每个电影的信息在列表下的标签里,每个节点下面有三个子节点,为前面的标号,包裹该电影图片信息,
包裹该电影具体信息。
对于请求,由于该网站比较简单,直接requests.get就行了,也不需要设置headers什么的。
对于解析,作者使用的正则表达式来匹配字符串,小括号"()"为要提取的子字符串,".*"后面的问号"?"表示非贪婪匹配(点匹配任意字符,星号表示匹配前面的字符无限次),re.S修饰符表示点号可以匹配换行符。
import requests
import re
import json
def get_one_page(url):
response=requests.get(url)
if response.status_code == 200:
return response.text
return None
def parse_one_page(html):
pattern = re.compile(
'.*?board-index.*?>(.*?).*?data-src="(.*?)".*?name.*?a.*?>(.*?)'
+'.*?star.*?>(.*?).*?releasetime.*?>(.*?).*?integer.*?>(.*?).*?fraction.*?>(.*?).*?',
re.S)
items=re.findall(pattern,html)
for item in items:
yield{
'index':item[0],
'image':item[1],
'title':item[2].strip(),
'actor':item[3].strip()[3:] if len(item[3])>3 else '', #[:]去掉里面多余的文字信息
'time':item[4].strip()[5:] if len(item[4])>5 else '',
'score':item[5].strip()+item[6].strip()
}
def write_to_file(content):
with open('result.txt','a',encoding='utf-8') as f:
f.write(json.dumps(content,ensure_ascii=False)+'\n')
if __name__ == "__main__":
url='https://maoyan.com/board/4'
for i in range(10):
html=get_one_page(url+'?offset='+str(i*10))
for item in parse_one_page(html):
write_to_file(item)
2.使用PyQuery解析
使用PyQuery的好处就是不用再费心去写正则表达式了,调试也更方便,就是代码貌似更长了。不过选择器匹配出来的字符串信息可能是有无效信息的,这时候还是需要正则表达式来剔除。比如该例子中的主演和时间两项,原字符串是有中文“主演:”和“上映时间:”这样的文字的,作者用的切片来去掉前面固定长度的文字,但是并不完美,因为有些时间后面跟了地区信息,有时候可能想要去掉或者拆分开来,这时候就需要用到正则表达式了。
from pyquery import PyQuery as pq
def parse_one_page(html):
doc=pq(html)
items=doc(".board-wrapper dd").items()
for item in items:
yield{
'index':item.find("i.board-index").text(),
'image':item.find("a img.board-img").attr("data-src"),
'title':item.find("div .movie-item-info p.name a").attr("title"),
'actor':item.find("div .movie-item-info p.star").text().strip()[3:],
'time':item.find("div .movie-item-info p.releasetime").text().strip()[5:],
'score':item.find("div .movie-item-number p.score").text().strip()
}
关注
打赏