利用requests和正则表达式爬取猫眼电影前100排行*
这几天接触了网络爬虫,也是非常开心,也非常感兴趣。今天是爬虫的第一次实战。写的不好望海涵。参考python3网络爬虫开发实战(崔庆才 著)
1、准备工作
在爬取之前先下载**好相应的库,requests,lxml
2、分析页面
此次爬取目标网站链接: http://maoyan.com/board/4 如图所示
当我们点击下一页的时候,URL变成了http://maoyan.com/board/4?offset=10,页面增加一次offset增加10,所有要爬取这100部影片只需要分开请求10次就可以。
3、爬取首页
import requests
def onepage(url):
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
def main():
url = 'http://maoyan.com/board/4'
html = onepage(url)
print(html)
main()
我们会得到下面这样的结果。这其实还是有一点隐患的,有时候我们也可能碰到[猫眼验证中心],只需要在请求头里面加了cookie就可以解决问题。但是有时候还是会弹出猫眼验证中心,只需要将URL中的http改为https。
根据爬取的数据我们可以发现一部电影的信息对应一个dd字节,这里我们爬取的数据排名,图片,电影名,演员,上映时间还有评分。分别对应为board-index,data-src,name,star,releasetime,integer和fraction。
4、解析数据
上图显示的内容明显不是我们全部需要的,接下来就是要将我们需要的数据从里面解析出来。这里我们运用正则表达式解析,以后我们还会使用xpath,Beautiful Soup等解析库进行解析。
#正则表达式<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>
import requests
import re
from requests.exceptions import RequestException
def get_pase(url):
try:
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
'Cookie':'__mta=121355959.1615986057087.1616502692174.1616673129095.32; uuid_n_v=v1; _lxsdk_cuid=1784046063ec8-0716d4053e27b3-59442e11-100200-1784046063ec8; __mta=141907213.1616144294289.1616144423881.1616160940378.3; uuid=BBF4CB208BD111EBBA186FE49672A60C46581868D4F647228357B28CB718591C; _lxsdk=BBF4CB208BD111EBBA186FE49672A60C46581868D4F647228357B28CB718591C; _csrf=17122e2b7f01e474663ca93e0faf596dc77cba50ffec1cf67592fc9349272c00; Hm_lvt_703e94591e87be68cc8da0da7cbd0be2=1616501869,1616502000,1616502691,1616673110; Hm_lpvt_703e94591e87be68cc8da0da7cbd0be2=1616673110; _lxsdk_s=1786939f904-f34-b18-191%7C%7C2'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
def parse_pase(html):
pattern = re.compile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, html)
print(items)
def main():
url = 'https://maoyan.com/board/4'
html = get_pase(url)
items = parse_pase(html)
print(items)
main()
会得到这样的结果,一个列表形式
[('1', 'https://p0.meituan.net/movie/414176cfa3fea8bed9b579e9f42766b9686649.jpg@160w_220h_1e_1c', '我不是药神', '\n 主演:徐峥,周一围,王传君\n ', '上映时间:2018-07-05', '9.', '6'), ('2', 'https://p0.meituan.net/movie/8112a8345d7f1d807d026282f2371008602126.jpg@160w_220h_1e_1c', '肖申克的救赎', '\n 主演:蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿\n ', '上映时间:1994-09-10(加拿大)', '9.', '5'), ('3', 'https://p1.meituan.net/movie/c9b280de01549fcb71913edec05880585769972.jpg@160w_220h_1e_1c', '绿皮书', '\n 主演:维果·莫腾森,马赫沙拉·阿里,琳达·卡德里尼\n ', '上映时间:2019-03-01', '9.', '5'), ('4', 'https://p0.meituan.net/movie/609e45bd40346eb8b927381be8fb27a61760914.jpg@160w_220h_1e_1c', '海上钢琴师', '\n 主演:蒂姆·罗斯,比尔·努恩,克兰伦斯·威廉姆斯三世\n ', '上映时间:2019-11-15', '9.', '3'), ('5', 'https://p1.meituan.net/movie/ac8f0004928fbce5a038a007b7c73cec746794.jpg@160w_220h_1e_1c', '小偷家族', '\n 主演:中川雅也,安藤樱,松冈茉优\n ', '上映时间:2018-08-03', '8.', '1'), ('6', 'https://p0.meituan.net/movie/005955214d5b3e50c910d7a511b0cb571445301.jpg@160w_220h_1e_1c', '哪吒之魔童降世', '\n 主演:吕艳婷,囧森瑟夫,瀚墨\n ', '上映时间:2019-07-26', '9.', '6'), ('7', 'https://p0.meituan.net/movie/61fea77024f83b3700603f6af93bf690585789.jpg@160w_220h_1e_1c', '霸王别姬', '\n 主演:张国荣,张丰毅,巩俐\n ', '上映时间:1993-07-26', '9.', '4'), ('8', 'https://p1.meituan.net/movie/580d81a2c78bf204f45323ddb4244b6c6821175.jpg@160w_220h_1e_1c', '美丽人生', '\n 主演:罗伯托·贝尼尼,朱斯蒂诺·杜拉诺,赛尔乔·比尼·布斯特里克\n ', '上映时间:2020-01-03', '9.', '3'), ('9', 'https://p1.meituan.net/movie/6bea9af4524dfbd0b668eaa7e187c3df767253.jpg@160w_220h_1e_1c', '这个杀手不太冷', '\n 主演:让·雷诺,加里·奥德曼,娜塔莉·波特曼\n ', '上映时间:1994-09-14(法国)', '9.', '4'), ('10', 'https://p0.meituan.net/moviemachine/c2496a7290a72eac6081321898c347693550574.jpg@160w_220h_1e_1c', '盗梦空间', '\n 主演:莱昂纳多·迪卡普里奥,渡边谦,约瑟夫·高登-莱维特\n ', '上映时间:2010-09-01', '9.', '0')]
5、写入文件
我们将提取的数据保存到一个文本文件中,可以通过json库中的dumps方法实现字典的序列化,并且将ensure_ascii参数设置为False,这样就可以保证我们输出的是中文而不是Unicode编码。
代码如下:
import requests
import time
import json
import re
from requests.exceptions import RequestException
def get_pase(url):
try:
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
'Cookie':'__mta=121355959.1615986057087.1616502692174.1616673129095.32; uuid_n_v=v1; _lxsdk_cuid=1784046063ec8-0716d4053e27b3-59442e11-100200-1784046063ec8; __mta=141907213.1616144294289.1616144423881.1616160940378.3; uuid=BBF4CB208BD111EBBA186FE49672A60C46581868D4F647228357B28CB718591C; _lxsdk=BBF4CB208BD111EBBA186FE49672A60C46581868D4F647228357B28CB718591C; _csrf=17122e2b7f01e474663ca93e0faf596dc77cba50ffec1cf67592fc9349272c00; Hm_lvt_703e94591e87be68cc8da0da7cbd0be2=1616501869,1616502000,1616502691,1616673110; Hm_lpvt_703e94591e87be68cc8da0da7cbd0be2=1616673110; _lxsdk_s=1786939f904-f34-b18-191%7C%7C2'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
def parse_pase(html):
pattern = re.compile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, html)
#strip方法用于移除字符串头尾指定的字符(默认空格或者换行符)
for item in items:
yield {
'index':item[0],
'image':item[1],
'name':item[2],
'star':item[3].strip(),
'time':item[4],
'score':item[5].strip() + item[6].strip()
}
def write_to_file(content):
with open('reply.txt', 'a', encoding='utf-8') as f:
f.write(json.dumps(content, ensure_ascii=False) + '\n')
def main(offset):
url = 'https://maoyan.com/board/4?offset=' + str(offset)
html = get_pase(url)
for item in parse_pase(html):
write_to_file(item)
print(item)
if __name__ == '__main__':
for i in range(10):
main(offset=i * 10)
time.sleep(1)
#加time.sleep是为了防止因为速度过快而无响应
结果如下