增量爬虫
- 增量爬虫
- 案例---->猫眼演员信息爬取
- 网站
- 需求
- 代码实现
增量爬虫
通过爬虫程序监测某网站数据更新的情况,以便可以爬取到该网站更新出的新数据。如 何进行增量式的爬取工作:
- 在发送请求之前判断这个 URL 是否爬取过。
- 在解析内容后判断这部分内容是否爬取过。
- 写入存储介质时判断内容是否在介质中。
不难发现,其实增量爬取的核心是去重,至于去重的操作在哪个步骤起作用,只能说各 有利弊。在我看来,前两种思路需要根据实际情况取一个(也可能都用)。
- 第一种思路适合不断有新页面出现的网站,例如:小说的新章节,每天的最新新闻等等。
- 第二种思路则适合页面内容会更新的网站。
- 第三个思路是相当于是最后的一道防线。
这样做可以最大程度上达到去重的目的。去重方法:
- 将爬取过程中产生的 url 进行存储,存储在 redis 的 set 中。当下次进行数据爬取时, 首先判断即将要发起请求的 url 是否在存储 url 的 set 中存在,如果不存在则进行请求。
- 对爬取到的网页内容进行唯一标识的限定,然后将该唯一标识存储至 redis 的 set 中。 当下次爬取到网页数据的时候,在进行持久化存储之前,首先可以先判断该数据的唯一标识 在 redis 的 set 中是否存在,进一步决定是否进行持久化存储.
案例---->猫眼演员信息爬取
网站
需求
(1)该案例爬取策略是通过多个演员作为起始任务,后面的演员主要从相关影人处获 取。
(2)相关影人有可能重复,设计好去重。
(3)自定义调度器来设置下载的任务。
代码实现
import hashlib
import threading
import requests
from lxml import etree
from queue import Queue
import redis
class MaoYanActor(threading.Thread):
def __init__(self,q_actors,name):
super().__init__()
self.name=name
self.q_actors=q_actors
self.redis_=redis.Redis()
self.s=requests.session()
self.headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36 Maxthon/5.2.6.1000',
'Host':'maoyan.com',
'Connection':'keep-alive',
}
self.s.headers=self.headers
def get_md5(self,value):
return hashlib.md5(bytes(value, encoding='utf-8')).hexdigest()
def get_xpath(self,url):
rep=self.s.get(url).text
return etree.HTML(rep)
def url_seen(self,url):
fp=self.get_md5(url)
add=self.redis_.sadd('maoyan_actor:actor_urls',fp)
return add==0
def parse_actor(self,tree):
actor_name=tree.xpath('//div[@class="shortInfo"]/p[1]/text()')[0]
def run(self):
while True:
if q_actors.empty():
break
# 获取url
url = q_actors.get()
print(f"{self.name}==========@{url.split('/')[-1]}")
if not self.url_seen(url):
# 请求,得到相应内容
tree = self.get_xpath(url)
# 解析当前演员信息并保存
self.parse_actor(tree)
# 获取响应电影人的信息--url
relation_actors = tree.xpath('//div[@class="rel-item"]/a/@href')
for actors in relation_actors:
self.q_actors.put('https://maoyan.com' + actors)
if __name__ == '__main__':
# 处理url列表
start_urls = [
'https://maoyan.com/films/celebrity/29410',
'https://maoyan.com/films/celebrity/789',
'https://maoyan.com/films/celebrity/28383',
'https://maoyan.com/films/celebrity/33280',
'https://maoyan.com/films/celebrity/28449'
]
q_actors = Queue()
for url in start_urls:
q_actors.put(url)
name_list=['线程1','线程2','线程3','线程4']
for name in name_list:
print(name)
m=MaoYanActor(q_actors,name)
m.start()