在简单的翻页中,我们可以知道.网页涵盖了以下几个规律
1.offset参数的值是除以30就是当前的页面
2.每个页面只有30个电影信息
打开谷歌开发者调试工具.抓包寻找突破点.
此处假设当前页面 = page
1.url:https://maoyan.com/films?showType=3&offset=str(page*30)
2.页面结构是有规律的。因此可以编写正则表达式来匹配
data-val="{movieId:(.*?)}">(.*?).*?integer">(.*?)<.*?fraction">(.*?)
我认为的突破点就如同上面2点,除了上面2点就没啥难点了.于是乎,让我们开始敲代码吧
A:构造一个Crawl类,同时编写一个__init__方法。我在init方法中初始化了我们需要一次需要爬取多少页的参数page,以及构造了我们的URL列表 URLS
class crawl():
def __init__(self,page):
self.header = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36",
"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3"
}
self.URLS = ["https://maoyan.com/films?showType=3&offset=%s"% ((i+1)*30) for i in range (page)]
B:当我们拥有了URL列表以后,我们应该要有一个访问页面的功能,于是乎,我们的Requests库就需要使用到了。同时编写一个request方法
def request(self,url):
try:
resp = requests.get(url,headers = self.header)
print(resp.status_code)
if resp.status_code == 200:
return resp.content.decode('utf-8')
return None
except RequestException:
return None
C:当我们访问完一个页面,我要就需要思考,如何才能把数据提取出来,这个时候我们就使用到了正则表达式(Regular expression)。编写一个parse_page方法。
def parse_page(self,html):
# 这边的正则表达式还有待优化
pattern = re.compile(r'data-val="{movieId:(.*?)}">(.*?).*?integer">(.*?)<.*?fraction">(.*?)',re.S)
items = re.findall(pattern,html)
for item in items:
yield{
'id':item[0],
'title':item[1],
'score':item[2] + item[3]
}
D:可是东西可以抓取下来,然后我们的数据要如何保存下来呢? 所以我们写一个write_to_file方法。这里用了json库,在dumps方法我选择了ensure_ascii=False
是因为我想输出的内容是中文的,而不是ascii编码的内容。大家可以试试有ensure_ascii和没有ensure_ascii写出来的文件有何不同。
def write_to_file(self,context):
with open('info.txt','a') as f:
f.write(json.dumps(context,ensure_ascii=False) + '\n')
E:这时候我们就可以在测试下,写个main方法,把这几个方法配合的调用起来。
def main(self):
for url in self.URLS:
html = self.request(url)
if html == None:
return None
for item in self.parse_page(html):
print(item)
self.write_to_file(item)
至此,我们的代码就全部编写完毕了。
{'id': '343034', 'title': '速度与激情9', 'score': '6.6'}
{'id': '1262590', 'title': '女王的柯基', 'score': '8.6'}
{'id': '344264', 'title': '战狼2', 'score': '9.7'}
{'id': '1229683', 'title': '铤而走险', 'score': '8.4'}
{'id': '1212492', 'title': '老师·好', 'score': '9.3'}
{'id': '247730', 'title': '终结者:黑暗命运', 'score': '8.8'}
{'id': '248906', 'title': '流浪地球', 'score': '9.2'}
{'id': '1205290', 'title': '检察方的罪人', 'score': '8.4'}
{'id': '1198925', 'title': '蜘蛛侠:英雄远征', 'score': '9.0'}
{'id': '902819', 'title': '死寂逃亡', 'score': '6.2'}
{'id': '894477', 'title': '宝莱坞机器人2.0:重生归来', 'score': '7.1'}
{'id': '1281095', 'title': '紫罗兰永恒花园外传:永远与自动手记人偶', 'score': '8.7'}
{'id': '341578', 'title': '那些女人', 'score': '8.5'}
{'id': '346119', 'title': '死亡通知单之暗黑者', 'score': '7.2'}
{'id': '1290250', 'title': '2019年国际篮联篮球世界杯', 'score': '7.8'}
{'id': '1196202', 'title': '天使陷落', 'score': '8.5'}
{'id': '1294987', 'title': '奉天往事', 'score': '9.3'}
{'id': '670240', 'title': '魔女', 'score': '7.1'}
{'id': '257594', 'title': '小丑回魂', 'score': '7.6'}