Python 如何根据现有的JSON列表防止重复抓取
在这只蜘蛛身上Python 如何根据现有的JSON列表防止重复抓取,python,json,filter,scrapy,duplicates,Python,Json,Filter,Scrapy,Duplicates,在这只蜘蛛身上 import scrapy class RedditSpider(scrapy.Spider): name = 'Reddit' allowed_domains = ['reddit.com'] start_urls = ['https://old.reddit.com'] def parse(self, response): for link in response.css('li.first a.comments::att
import scrapy
class RedditSpider(scrapy.Spider):
name = 'Reddit'
allowed_domains = ['reddit.com']
start_urls = ['https://old.reddit.com']
def parse(self, response):
for link in response.css('li.first a.comments::attr(href)').extract():
yield scrapy.Request(url=response.urljoin(link), callback=self.parse_topics)
def parse_topics(self, response):
topics = {}
topics["title"] = response.css('a.title::text').extract_first()
topics["author"] = response.css('p.tagline a.author::text').extract_first()
if response.css('div.score.likes::attr(title)').extract_first() is not None:
topics["score"] = response.css('div.score.likes::attr(title)').extract_first()
else:
topics["score"] = "0"
if int(topics["score"]) > 10000:
author_url = response.css('p.tagline a.author::attr(href)').extract_first()
yield scrapy.Request(url=response.urljoin(author_url), callback=self.parse_user, meta={'topics': topics})
else:
yield topics
def parse_user(self, response):
topics = response.meta.get('topics')
users = {}
users["name"] = topics["author"]
users["karma"] = response.css('span.karma::text').extract_first()
yield users
yield topics
我得到以下结果:
[
{"name": "Username", "karma": "00000"},
{"title": "ExampleTitle1", "author": "Username", "score": "11000"},
{"name": "Username2", "karma": "00000"},
{"title": "ExampleTitle2", "author": "Username2", "score": "12000"},
{"name": "Username3", "karma": "00000"},
{"title": "ExampleTitle3", "author": "Username3", "score": "13000"},
{"title": "ExampleTitle4", "author": "Username4", "score": "9000"},
....
]
,但我每天都运行这个蜘蛛来获取本周的最后一天,因此,如果今天是一周的第7天,我会在今天之前的6天内得到一个副本,如下所示
day1: result_day1
day2: result_day2, result_day1
day3: result_day3, result_day2, result_day1
. . . . . . .
day7: result_day7, result_day6, result_day5, result_day4, result_day3, result_day2, result_day1
所有数据都存储在一个JSON文件中,如前所示,我想做的是告诉爬行器检查JSON文件中已经存在的获取结果,如果存在,则跳过,如果不存在,则添加到文件中
用刮痧可以吗
例如:
如果昨天(06.json)的结果是
[
{"name": "Username", "karma": "00000"},
{"title": "ExampleTitle1", "author": "Username", "score": "11000"},
{"name": "Username2", "karma": "00000"},
{"title": "ExampleTitle2", "author": "Username2", "score": "12000"},
{"name": "Username3", "karma": "00000"},
{"title": "ExampleTitle3", "author": "Username3", "score": "13000"},
{"title": "ExampleTitle4", "author": "Username4", "score": "9000"},
]
今天(07.json)的结果是
[
{"name": "Username", "karma": "00000"},
{"title": "ExampleTitle1", "author": "Username", "score": "11000"},
{"name": "Username2", "karma": "00000"},
{"title": "ExampleTitle2", "author": "Username2", "score": "12000"},
{"name": "Username3", "karma": "00000"},
{"title": "ExampleTitle3", "author": "Username3", "score": "13000"},
{"title": "ExampleTitle4", "author": "Username4", "score": "9000"},
{"title": "ExampleTitle5", "author": "Username5", "score": "16700"}
]
今天的列表(07.json)的结果是
过滤后Scrapy实际上只提供了一种查找“重复”的方法(用于数据,而不是重复的请求):通过使用项目管道中的项目和重复过滤器收集数据。见: 当检测到重复项时,它会删除项目。我对这种方法有两个问题:(1)您必须编写duplicate filter方法,以根据您使用的数据定义什么是重复的;(2)此方法实际上只帮助在爬行器的相同“运行”中检查重复 在两天之间运行spider的另一种方法是在两次运行之间持久化数据。见: 使用这种方法,您的
spider.state
将是上次运行(前一天)的数据。然后,当您再次运行spider时,您就知道上次运行得到了什么数据。因此,您可以实现逻辑来提取仅对当前日期唯一的数据(给每天的数据加上时间戳,并使用最后一天作为比较)。您可以快速实现这一点。而且,这可能足以解决您的问题
但是,如果您必须比较当天之前所有天的数据,这种方法将变得难以控制。这意味着您将使爬行器在当前数据之前的一周中的所有天都保持数据。因此,您的spider.state
字典(它只是每天的JSON结果)会变得非常大,因为它充满了第7天之前所有天的数据
如果您需要使为当天添加的数据与之前的所有数据相比都是唯一的,我将完全抛弃Scrapy的内置机制。我只需将所有数据写入一个数据库,并带有数据被刮取的时间戳。然后,您可以使用数据库查询来找出为每一天添加的唯一数据。Scrapy实际上只提供了一种查找“重复数据”的方法(对于数据,而不是重复请求):通过使用项目管道中的项目和使用重复过滤器来收集数据。见: 当检测到重复项时,它会删除项目。我对这种方法有两个问题:(1)您必须编写duplicate filter方法,以根据您使用的数据定义什么是重复的;(2)此方法实际上只帮助在爬行器的相同“运行”中检查重复 在两天之间运行spider的另一种方法是在两次运行之间持久化数据。见: 使用这种方法,您的
spider.state
将是上次运行(前一天)的数据。然后,当您再次运行spider时,您就知道上次运行得到了什么数据。因此,您可以实现逻辑来提取仅对当前日期唯一的数据(给每天的数据加上时间戳,并使用最后一天作为比较)。您可以快速实现这一点。而且,这可能足以解决您的问题
但是,如果您必须比较当天之前所有天的数据,这种方法将变得难以控制。这意味着您将使爬行器在当前数据之前的一周中的所有天都保持数据。因此,您的spider.state
字典(它只是每天的JSON结果)会变得非常大,因为它充满了第7天之前所有天的数据
如果您需要使为当天添加的数据与之前的所有数据相比都是唯一的,我将完全抛弃Scrapy的内置机制。我只需将所有数据写入一个数据库,并带有数据被刮取的时间戳。然后,您可以使用数据库查询来找出为每一天添加的唯一数据
[
{"title": "ExampleTitle5", "author": "Username5", "score": "16700"}
]