在这只蜘蛛
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"},
....
]
,但是我每天都会运行这只Spider来获得本周的最后一天,因此,例如,如果今天是一周的第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 文件中,如前所示,我要做的是告诉Spider检查 JSON file,如果是,则跳过它,如果不是,则将其添加到文件中,
使用Scrapy可以吗?
例如:
如果昨天(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)的结果
[
{"title": "ExampleTitle5", "author": "Username5", "score": "16700"}
]
过滤后
答案 0 :(得分:1)
Scrapy实际上仅提供一种寻找“重复项”的方式(对于数据,不是重复的请求):使用项目管道中的项目并使用重复过滤器来收集数据。参见:
https://doc.scrapy.org/en/latest/topics/item-pipeline.html#duplicates-filter
当检测到重复项时,它会丢弃项目。这种方法有两个问题:(1)您必须编写重复过滤器方法来根据您使用的数据定义重复的 ,以及(2)此方法仅对在蜘蛛的相同“运行”中检查重复项。
另一种在几天之间运行Spider的方法是在两次运行之间保留数据。参见:
https://doc.scrapy.org/en/latest/topics/jobs.html#keeping-persistent-state-between-batches
使用这种方法,您的spider.state
将是来自上次运行(前一天)的数据。然后,当您再次运行Spider时,您知道从上一次运行中获得了什么数据。因此,您可以实施逻辑以将仅唯一的数据提取到当前日期(将每天的数据加上时间戳,并使用最后一天作为比较)。您可以快速实现这一点。并且,这可能足以解决您的问题。
但是,如果您必须在当天之前的所有天中比较数据,则这种方法将变得不灵活。这意味着您将使Spider在当前数据之前一周的所有天中都保留数据。因此,例如,spider.state
字典(这只是每天的JSON结果)将变得非常大,因为它充满了第7天之前所有天的数据。
如果需要确保当天添加的数据与之前的所有数据相比都是唯一的,我将完全放弃Scrapy的内置机制。我只是将所有数据写入带有刮取数据时间的时间戳的数据库。然后,您可以使用数据库查询来找出每天添加的唯一数据。