Web爬虫|入门实战之猫眼电影
Posted 南柯树下
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Web爬虫|入门实战之猫眼电影相关的知识,希望对你有一定的参考价值。
一、爬虫任务
任务背景:爬取猫眼电影Top100数据
任务目标:运用正则表达式去解析网页源码并获得所需数据
二、解析
任务URL:https://maoyan.com/board/4?offset=0
下图为猫眼电影的第一页:
再看看第二页:
最后看看第三页:
我们把这三页的URL复制下来,看一下URL规律:
1 https://maoyan.com/board/4?offset=0 2 https://maoyan.com/board/4?offset=10 3 https://maoyan.com/board/4?offset=20
从上面的URL可以看出,只有offset变化,offset意为偏移量,从中可以看出每一页的偏移量为10,可以把该参数定义为自变量,然后用循环爬取前10页的数据,也就是top100的数据
爬取任务
爬取猫眼电影top100电影的电影排名,图片地址,演员,电影名,上映时间以及电影评分
解析网页源代码
点击箭头打开dd标签块,看看具体的信息:
再看看network中的真实数据:
从以上的图中可以看出猫眼电影的数据都保存在dd标签块中,接下来就要用正则表达式去匹配所需的数据,再把这些数据以json格式保存到文本文件中以及MongoDB数据库中
三、编码
获取网页源码
定义一个去获取html源码的方法
1 import requests 2 from requests import exceptions 3 4 def get_one_page(url): 5 \'\'\' 6 headers表示要传递的头信息,\'User-Agent\'表示伪装浏览器 7 \'\'\' 8 try: 9 headers = {\'User-Agent\':\'Mozilla/5.0\'} 10 response = requests.get(url,headers=headers) 11 if response.status_code == 200: 12 return response.text 13 else: 14 return None 15 except exceptions.RequestException: 16 return None
解析源码并获得数据
1 import re 2 3 def parse_one_page(html): 4 \'\'\' 5 re.compile()方法会将正则表达式字符串转换为正则表达式对象,方便以后的复用 6 re.S表示修饰符,可以忽略换行符 7 re.findall()方法会将所有符合匹配模式的数据返回,并且以列表形式返回 8 yield是Python中的关键字,表示生成器,类似于return 9 strip()方法可以把空的部分去掉,包括空格,换行符等,但它的操作对象必须是字符串 10 \'\'\' 11 pattern = re.compile(\'<dd>.*?board-index.*?>(\\d+)</i>.*?data-src="(.*?)".*?name"><a\' 12 + \'.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>\' 13 + \'.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>\',re.S) 14 movies_information = re.findall(pattern,html) 15 for movie_information in movies_information: 16 yield { 17 \'电影排名\':movie_information[0], 18 \'图片地址\':movie_information[1], 19 \'电影名\':movie_information[2].strip(), 20 \'演员\':movie_information[3].strip()[3:] if len(movie_information) > 3 else \'\', 21 \'上映时间\':movie_information[4].strip()[5:] if len(movie_information) > 5 else \'\', 22 \'评分\':movie_information[5].strip() + movie_information[6].strip() 23 }
保存数据到文本文件
1 import json 2 3 def write_movies_data_to_file(movie_information): 4 \'\'\' 5 \'a\'表示以追加方式把数据写入文件中,这样就不会覆盖之前写入的数据 6 json.dumps()方法可将json文本字符串序列化为json对象 7 ensure_ascii=False表示忽略ASCII码,默认也为False 8 indent表示json格式的缩进 9 \'\'\' 10 with open(\'../txt_file/maoyan_movies_information.txt\',\'a\',encoding=\'utf-8\') as f: 11 f.write(json.dumps(movie_information,indent=2,ensure_ascii=False) + \'\\n\')
保存数据到MongoDB数据库
1 import pymongo 2 3 def insert_to_mongodb(content): 4 \'\'\' 5 client表示操作MongoDB数据库的对象 6 db表示数据库对象 7 collection表示集合对象,类似于mysql中的table 8 \'\'\' 9 client = pymongo.MongoClient(host=\'localhost\',port=27017) 10 db = client[\'spiders\'] 11 collection = db[\'maoyan_movies_data\'] 12 try: 13 if content: 14 collection.insert(content) 15 print(\'Success to insert!\') 16 except: 17 print(\'Failed to insert!\')
定义main()方法控制程序的运行
1 def main(offset): 2 \'\'\' 3 offset={offset}表示页数偏移量,这里用f-string函数把它设置为自变量,从而可以循环爬取 4 \'\'\' 5 url = f\'https://maoyan.com/board/4?offset={offset}\' 6 html = get_one_page(url) 7 for movie_information in parse_one_page(html): 8 print(movie_information) 9 write_movies_data_to_file(movie_information) 10 insert_to_mongodb(movie_information)
主程序运行
1 import time 2 3 if __name__ == \'__main__\': 4 \'\'\' 5 time模块延迟爬取时间,猫眼已经加了反爬 6 \'\'\' 7 for i in range(10): 8 main(offset=i*10) 9 time.sleep(1)
完整源码如下
1 import requests 2 import re 3 import time 4 from requests import exceptions 5 import json 6 import pymongo 7 8 def get_one_page(url): 9 try: 10 headers = {\'User-Agent\':\'Mozilla/5.0\'} 11 response = requests.get(url,headers=headers) 12 if response.status_code == 200: 13 return response.text 14 else: 15 return None 16 except exceptions.RequestException: 17 return None 18 19 def parse_one_page(html): 20 pattern = re.compile(\'<dd>.*?board-index.*?>(\\d+)</i>.*?data-src="(.*?)".*?name"><a\' 21 + \'.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>\' 22 + \'.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>\',re.S) 23 movies_information = re.findall(pattern,html) 24 for movie_information in movies_information: 25 yield { 26 \'电影排名\':movie_information[0], 27 \'图片地址\':movie_information[1], 28 \'电影名\':movie_information[2].strip(), 29 \'演员\':movie_information[3].strip()[3:] if len(movie_information) > 3 else \'\', 30 \'上映时间\':movie_information[4].strip()[5:] if len(movie_information) > 5 else \'\', 31 \'评分\':movie_information[5].strip() + movie_information[6].strip() 32 } 33 34 def write_movies_data_to_file(movie_information): 35 with open(\'../txt_file/maoyan_movies_information.txt\',\'a\',encoding=\'utf-8\') as f: 36 f.write(json.dumps(movie_information,indent=2,ensure_ascii=False) + \'\\n\') 37 38 def main(offset): 39 url = f\'https://maoyan.com/board/4?offset={offset}\' 40 html = get_one_page(url) 41 for movie_information in parse_one_page(html): 42 print(movie_information) 43 write_movies_data_to_file(movie_information) 44 insert_to_mongodb(movie_information) 45 46 def insert_to_mongodb(content): 47 client = pymongo.MongoClient(host=\'localhost\',port=27017) 48 db = client[\'spiders\'] 49 collection = db[\'maoyan_movies_data\'] 50 try: 51 if content: 52 collection.insert(content) 53 print(\'Success to insert!\') 54 except: 55 print(\'Failed to insert!\') 56 57 if __name__ == \'__main__\': 58 for i in range(10): 59 main(offset=i*10) 60 time.sleep(1)
运行效果
控制台输出:
json格式的txt文本结果:
MongoDB输出结果:
四、总结
请求库requests及exceptions模块
标准库re
time模块
json模块
Python与MongoDB数据库对接的pymongo库
更多独家精彩内容 请扫码关注个人公众号,一起Coding吧!
—— —— —— —— — END —— —— —— —— ————
欢迎扫码关注我的公众号
小鸿星空科技
Python爬虫实战之Requests+正则表达式爬取猫眼电影Top100
import requests from requests.exceptions import RequestException import re import json # from multiprocessing import Pool # 测试了下 这里需要自己添加头部 否则得不到网页 headers = { ‘User-Agent‘:‘Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36‘ } # 得到html代码 def get_one_page(url): try: response = requests.get(url, headers = headers) if response.status_code == 200: return response.text return None except RequestException: return None # 解析html代码 def parse_one_page(html): pattern = re.compile(‘<dd>.*?board-index.*?>(d+)</i>.*?data-src="(.*?)".*?name"><a.*?">(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?(/dd)‘, re.S) items = re.findall(pattern, html) for item in items: # 将元组形式变为字典 yield { ‘【排名】‘: item[0], ‘【图片】‘: item[1], ‘【标题】‘: item[2], ‘【主演】‘: item[3].strip()[3:], ‘【上映时间】‘: item[4].strip()[5:], ‘【评分】‘: item[5] + item[6] } # 写入文件 def write_to_file(content): # 注意encoding = ‘utf-8‘和ensure_ascii = False,不写的话不能输出汉字 with open(‘电影.txt‘, ‘a‘, encoding = ‘utf-8‘) as f: f.write(json.dumps(content, ensure_ascii = False) + ‘ ‘) f.close() # 主函数 def main(offset): url = ‘http://maoyan.com/board/4?offset=‘ + str(offset) html = get_one_page(url) for item in parse_one_page(html): print(item) write_to_file(item) if __name__ == ‘__main__‘: for i in range(10): main(i * 10) # 多进程(测试有bug) # if __name__ == ‘__main__‘: # pool = Pool() # pool.map(main, [i * 10 for i in range(10)]) # pool.join() # pool.close()
代码来自崔庆才
以上是关于Web爬虫|入门实战之猫眼电影的主要内容,如果未能解决你的问题,请参考以下文章
Python爬虫应用实战案例-pyquery在爬虫中的应用,爬取猫眼电影数据