引言
之前数据采集时有2个需求就是url去重与数据的增量爬去(只能够请求增加的url,不然会增加被爬网站的服务器负荷),最开始的想法是指用redis的set实现url去重,但在后面开发中无意的解决了增量爬去的类容。下面贴上主要代码。
具体实现步骤
将每次爬去的链接存入redis(pipeline.py)
class InsertRedis(object):
def __init__(self):
self.Redis = RedisOpera('insert')
def process_item(self,item,spider):
self.Redis.write(item['url'])
return item
注:redis的具体操作此处不表
将即将请求的url判断是否已经爬取(middlewa.py)
class IngoreRequestMiddleware(object):
def __init__(self):
self.Redis = RedisOpera('query')
def process_request(self,request,spider):
if self.Redis.query(request.url):
raise IgnoreRequest("IgnoreRequest : %s" % request.url)
else:
return None
实现增量爬取
def start_requests(self):
yield FormRequest('https://www.demo.org/vuldb/vulnerabilities?page='+str(self.page_num), callback=self.parse_page)#page_num是分页参数
def parse_page(self,response):
urls = response.xpath('//tbody/tr').extract()
for url in urls:
request_url = Selector(text=url).xpath('//td[@class=\'vul-title-wrapper\']/a/@href').extract()[0]
if re.search('/vuldb/ssvid-\d+',request_url):
yield FormRequest('https://www.demo.org'+request_url.strip(),callback=self.parse_item,dont_filter=False)
if len(urls) == 20:
self.page_num += 1
def parse_item(self,response):
item = WebcrawlItem()
self.count += 1
item['url'] = response.url
yield item
yield FormRequest('https://www.demo.org/vuldb/vulnerabilities?page=' + str(self.page_num), callback=self.parse_page)
第三段函数parse_item()回调parse_page(),如果redis数据库中没有一条url数据则会一直将整站的page抓取,但r如果是在某个时间点我们已经爬去完了数据,继续启动程序爬去增加的数据是会去判断每个url是否已经爬去,当url有重复时parse_page不会回调parse_item(url去重),当然也就不会在去执行yield FormRequest('https://www.demo.org/vuldb/vu...' + str(self.page_num), callback=self.parse_page)
,故程序会跳出循环结束。