jak filtrować zduplikowane żądania na podstawie adresu url w Scrappy
Piszę crawler dla strony internetowej za pomocą Scrappy z CrawlSpider.
Scrapy dostarcza wbudowany filtr duplikatów żądań, który filtruje duplikaty żądań na podstawie adresów URL. Ponadto, mogę filtrować żądania za pomocą rules członek CrawlSpider.
To, co chcę zrobić, to filtrować żądania w stylu:
http:://www.abc.com/p/xyz.html?id=1234&refer=5678
Jeśli już odwiedziłem
http:://www.abc.com/p/xyz.html?id=1234&refer=4567
Uwaga: Referer jest parametrem, który nie wpływa na otrzymaną odpowiedź, więc nie obchodzi mnie, czy wartość zmian tego parametru.
Teraz, jeśli mam zestaw, który gromadzi wszystkie ID mogę zignorować go w mojej funkcji zwrotnej parse_item (to moja funkcja zwrotna), aby osiągnąć tę funkcjonalność.
Ale to by oznaczało, że wciąż przynajmniej pobieram tę stronę, kiedy nie muszę.
Więc w jaki sposób mogę powiedzieć scrapy ' emu, że nie powinien wysyłać konkretnego żądania na podstawie adresu url?
4 answers
Możesz napisać własne oprogramowanie pośrednie do usuwania duplikatów i dodać je w Ustawieniach
import os
from scrapy.dupefilter import RFPDupeFilter
from scrapy.utils.request import request_fingerprint
class CustomFilter(RFPDupeFilter):
"""A dupe filter that considers specific ids in the url"""
def __getid(self, url):
mm = url.split("&refer")[0] #or something like that
return mm
def request_seen(self, request):
fp = self.__getid(request.url)
if fp in self.fingerprints:
return True
self.fingerprints.add(fp)
if self.file:
self.file.write(fp + os.linesep)
Następnie musisz ustawić poprawny DUPFILTER_CLASS w settings.py
DUPEFILTER_CLASS = 'scraper.duplicate_filter.CustomFilter'
Powinno działać po tym
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-11 17:31:17
Idąc za tropem ytomara, napisałem ten filtr, który filtruje wyłącznie na podstawie adresów URL, które były już widoczne, sprawdzając zestaw w pamięci. Jestem noobem Pythona, więc daj znać, jeśli coś spieprzyłem, ale wygląda na to, że działa dobrze: {]}
from scrapy.dupefilter import RFPDupeFilter
class SeenURLFilter(RFPDupeFilter):
"""A dupe filter that considers the URL"""
def __init__(self, path=None):
self.urls_seen = set()
RFPDupeFilter.__init__(self, path)
def request_seen(self, request):
if request.url in self.urls_seen:
return True
else:
self.urls_seen.add(request.url)
Jak wspomniał ytomar, należy dodać DUPEFILTER_CLASS
stałą do settings.py
:
DUPEFILTER_CLASS = 'scraper.custom_filters.SeenURLFilter'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-15 04:56:43
Https://github.com/scrapinghub/scrapylib/blob/master/scrapylib/deltafetch.py
Ten plik może Ci pomóc. Ten plik tworzy bazę danych unikalnego delta fetch key z adresu url, użytkownik przechodzi w scrapie.Reqeust (meta={'deltafetch_key': uniqe_url_key}). To pozwoli Ci uniknąć duplikatów wniosków, które już odwiedziłeś w przeszłości.
Przykładowa implementacja mongodb przy użyciu deltafetch.py
if isinstance(r, Request):
key = self._get_key(r)
key = key+spider.name
if self.db['your_collection_to_store_deltafetch_key'].find_one({"_id":key}):
spider.log("Ignoring already visited: %s" % r, level=log.INFO)
continue
elif isinstance(r, BaseItem):
key = self._get_key(response.request)
key = key+spider.name
try:
self.db['your_collection_to_store_deltafetch_key'].insert({"_id":key,"time":datetime.now()})
except:
spider.log("Ignoring already visited: %s" % key, level=log.ERROR)
yield r
Np. id = 345 scrapy.Request(url, meta = {deltafetch_key: 345},callback=parse)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-19 14:12:59
Oto moja własna baza filtrów na scrapy 0.24.6.
W tym filtrze dba tylko o id w adresie url. na przykład
http://www.example.com/products/cat1/1000.html?p=1
http://www.example.com/products/cat2/1000.html?p=2
Są traktowane jako ten sam adres url. Ale
http://www.example.com/products/cat2/all.html
import re
import os
from scrapy.dupefilter import RFPDupeFilter
class MyCustomURLFilter(RFPDupeFilter):
def _get_id(self, url):
m = re.search(r'(\d+)\.html', url)
return None if m is None else m.group(1)
def request_fingerprint(self, request):
style_id = self._get_id(request.url)
return style_id
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-31 02:40:15