01
进入正文
对于喜好电影的同学来说,猫眼电影和豆瓣电影应该是比较熟悉的电影评分的平台。但是,如何通过Python抓取猫眼电影评分前100的信息呢?
URL获取
我们还是先分析URL。打开猫眼电影TOP100榜,可以看到如下页面:
URL为:http://maoyan.com/board/4。但是,这一页只有排名前10的电影,如何获取下页的URL呢?
点击下方的下一页,可以跳转到第二页:
URL为:http://maoyan.com/board/4?offset=10。由此,可以猜测offset的取值范围为0,10,20,...,90。由此,我们可以构造出10个页面的URL:
for i in range(10):
offset = 10*i
url = 'http://maoyan.com/board/4?offset=' + str(offset)
获取到页面后,下一步就是对页面进行解析了。
页面解析
下面看一下具体的页面,在查看网页源码可以看到具体的内容。以排名第一的霸王别姬为例,HTML码如下:
本文是通过正则表达式来获取影片的信息,所以先要生成正则表达式的Pattern。我们想要提前的信息有:排名,影片名称,演员,上映时间,评分。
匹配的表达式的写法很简单,需要找到一些关键的标签,然后在需要的信息处加入(.*?),若匹配到表达式,就会返回相应的项。
另外,还需要对响应的字段进行截取,获取真正需要的信息。具体代码如下:
def parse_one_page(html):
'''
通过正则表达式解析html,并格式化数据
:param html:
:return:
'''
pat = re.compile(
'<dd>.*?board-index.*?">(.*?)</i>.*?"name"><a.*?">(.*?)</a>.*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>',
re.S)
# 正则表达式找到所有匹配的内容
items = re.findall(pat, html)
#格式化数据
for item in items:
yield {
'排名': item[0],
'影片名称': item[1],
'演员': item[2].strip()[2:],
'上映时间': item[3].strip()[5:],
'评分': item[4] + item[5]
}
数据存储与保存
接下来需要将抓取的数据进行保存了,可以保存到CSV文件,文本文件,关系型数据库MySQL或者是非关系型数据库MongoDB。这里以存储文本文件为例,打开文件的方式为a即追加写文件。
这里要注意的是,因为写入的内容包括汉字,所以需要设置系统编码,设置为UTF-8,如下代码前三行所示:
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
def write_into_file(conrent):
'''
将抓取的内容写入文件
:param conrent:
:return:
'''
with open('result', 'a') as f:
f.write(json.dumps(conrent, ensure_ascii=False) + '\n')
f.close()
伪装成浏览器
对于猫眼电影,有反爬虫策略,如果不设置header,将无法获取到HTML页面,所以,在进行抓取页面的时候,需要设置header:
def get_response(url):
'''
抓取HTML页面
:param url:
:return:
'''
try:
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
referer = 'http://www.baidu.com'
headers = {"User-Agent": user_agent, 'Referer': referer}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
文件数据
抓取好的文件的数据如下:
{"上映时间": "1993-01-01(中国香港)", "影片名称": "霸王别姬", "排名": "1", "演员": ":张国荣,张丰毅,巩俐", "评分": "9.6"}
{"上映时间": "1994-10-14(美国)", "影片名称": "肖申克的救赎", "排名": "2", "演员": ":蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿", "评分": "9.5"}
{"上映时间": "1953-09-02(美国)", "影片名称": "罗马假日", "排名": "3", "演员": ":格利高利·派克,奥黛丽·赫本,埃迪·艾伯特", "评分": "9.1"}
{"上映时间": "1994-09-14(法国)", "影片名称": "这个杀手不太冷", "排名": "4", "演员": ":让·雷诺,加里·奥德曼,娜塔莉·波特曼", "评分": "9.5"}
{"上映时间": "1998-04-03", "影片名称": "泰坦尼克号", "排名": "5", "演员": ":莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩", "评分": "9.5"}
{"上映时间": "1972-03-24(美国)", "影片名称": "教父", "排名": "6", "演员": ":马龙·白兰度,阿尔·帕西诺,詹姆斯·凯恩", "评分": "9.3"}
{"上映时间": "1988-04-16(日本)", "影片名称": "龙猫", "排名": "7", "演员": ":日高法子,坂本千夏,糸井重里", "评分": "9.2"}
{"上映时间": "1993-07-01(中国香港)", "影片名称": "唐伯虎点秋香", "排名": "8", "演员": ":周星驰,巩俐,郑佩佩", "评分": "9.2"}
{"上映时间": "2001-07-20(日本)", "影片名称": "千与千寻", "排名": "9", "演员": ":柊瑠美,入野自由,夏木真理", "评分": "9.3"}
{"上映时间": "1940-05-17(美国)", "影片名称": "魂断蓝桥", "排名": "10", "演员": ":费雯·丽,罗伯特·泰勒,露塞尔·沃特森", "评分": "9.2"}
完整代码
# coding:utf-8
import requests
from flask import json
from requests.exceptions import RequestException
import re
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
def get_response(url):
'''
抓取HTML页面
:param url:
:return:
'''
try:
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
referer = 'http://www.baidu.com'
headers = {"User-Agent": user_agent, 'Referer': referer}
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
def parse_one_page(html):
'''
通过正则表达式解析html,并格式化数据
:param html:
:return:
'''
pat = re.compile(
'<dd>.*?board-index.*?">(.*?)</i>.*?"name"><a.*?">(.*?)</a>.*?class="star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>',
re.S)
# 正则表达式找到所有匹配的内容
items = re.findall(pat, html)
#格式化数据
for item in items:
yield {
'排名': item[0],
'影片名称': item[1],
'演员': item[2].strip()[2:],
'上映时间': item[3].strip()[5:],
'评分': item[4] + item[5]
}
def write_into_file(conrent):
'''
将抓取的内容写入文件
:param conrent:
:return:
'''
with open('result', 'a') as f:
f.write(json.dumps(conrent, ensure_ascii=False) + '\n')
f.close()
def get_and_save_one_page(offset):
'''
读取并保存第offset页的数据
:param offset:
:return:
'''
url = 'http://maoyan.com/board/4?offset=' + str(offset)
html = get_response(url)
for item in parse_one_page(html):
write_into_file(item)
if __name__ == '__main__':
for i in range(10):
offset = 10*i
get_and_save_one_page(offset)
本文来源于:python那些事
文部分来源网络,如有侵权请第一时间联系删除。