GOOGLE ADS

Dienstag, 3. Mai 2022

Hohe Menge an Request to Yield pro geparster Seite blockiert Crawling

Ich habe einen Crawl, bei dem jede Unterseite mehr als 300 Links enthält, denen ich folgen muss. Der Crawl verlangsamt sich nach ungefähr einer Minute / manchmal werden 0 Seiten / min gecrawlt.

Wenn ich den Crawl mit Seiten 10-50 Links pro Seite durchlaufe, wird das gleiche Problem nicht angezeigt.

Ich habe 10 concurrent_requests und 10 verarbeitete Artikel und einen Reaktor-Threadpool mit 400 konfiguriert. Das bedeutet bis zu 3.000 Erträge pro 10 verarbeiteten Artikeln...

Die Protokollierung zeigt, dass die Parsing-Funktion mehr als 70 Sekunden pro Seite benötigt. Die Protokollierung zeigt, dass die hier benötigte Zeit aus den Erträgen stammt (bis zu 2 Sekunden pro Ertrag).

Es scheint kratzig zu warten, bis der Motor anspringt? oder etwas Ähnliches hat eine Aufgabe erledigt und ist bereit, die neue Ertragsanfrage zu bearbeiten? Das Hinzufügen der Anforderungen zum Scheduler dauert nicht lange, daher scheint es mir, dass der Ertrag auf etwas anderes wartet.

Irgendwelche Hinweise, was zu optimieren ist oder was falsch läuft?

Ist es möglich, die Anforderungen in großen Mengen bereitzustellen, anstatt jede einzeln bereitzustellen? Ist es möglich, sie dem Scheduler hinzuzufügen, ohne sie zu übergeben?

Einige zusätzliche Informationen:


  • Kein Unterschied, ob ich Scrapy-Redis oder nur den Disk-Base-Scheduler verwende.

  • Aufgrund der Darstellung von Javascript kann ein Download einer gecrawlten Seite bis zu 10 Sekunden dauern.

  • Autothrottle ist deaktiviert

  • Wenn ich mehr CPU-Ressourcen gebe, beschleunigt es die Dinge nicht.


telnet-> est()
time()-engine.start_time : 676.0599975585938
engine.has_capacity() : False
len(engine.downloader.active) : 7
engine.scraper.is_idle() : False
engine.spider.name : onetwothree
engine.spider_is_idle(engine.spider): False
engine.slot.closing : False
len(engine.slot.inprogress) : 28
len(engine.slot.scheduler.dqs or []): AttributeError (exception)
len(engine.slot.scheduler.mqs) : AttributeError (exception)
len(engine.scraper.slot.queue) : 0
len(engine.scraper.slot.active) : 21
engine.scraper.slot.active_size : 3878605
engine.scraper.slot.itemproc_size: 0
engine.scraper.slot.needs_backout(): False

AttributeError seems to come from scrapy-redis plugin, 
without scrapy counts up the pages to request in mgs.

est, wenn len(engine.downloader.active) auf 0 geht

 time()-engine.start_time : 7236.464096784592
engine.has_capacity() : False
len(engine.downloader.active) : 0
engine.scraper.is_idle() : False
engine.spider.name : onetwothree
engine.spider_is_idle(engine.spider): False
engine.slot.closing : False
len(engine.slot.inprogress) : 25
len(engine.slot.scheduler.dqs or []): AttributeError (exception)
len(engine.slot.scheduler.mqs) : AttributeError (exception)
len(engine.scraper.slot.queue) : 0
len(engine.scraper.slot.active) : 25
engine.scraper.slot.active_size : 5357134
engine.scraper.slot.itemproc_size: 0
engine.scraper.slot.needs_backout(): True

Crawler Code:

 class robo2Spider(Spider):
http_pass = None
http_user = None
dont_redirect = True
start_urls = []

def __init__(self, *args, **kwargs):

#... some config...

self.start_urls = self.custom_settings["TEST_URLS"]
# Don't Follow links in test mode

def start_requests(self):
for url in self.start_urls:
r = self.get_request(url)
yield r

def parse(self, response):
# some extraction and co...
yield from self.scrape_data(response)

def scrape_data(self, response):
start_time = time.time()

# more extraction, build item

extract_links = util.extract_links_from_response(response, self.query_pars_to_ignore)
logging.info(
"--- logging time 1: %s --- %s seconds ---" % (response.url, time.time() - start_time))

request_links = []
for link in extract_links:

if (not link["nofollow"]) and (l.get_output_value("crawl_meta_nofollow")!= "nofollow"):
r = self.get_request(link["url"])
request_links.append(r)

yield from request_links

logging.info(
"--- logging time 2 (takes up to 70 sec): %s --- %s seconds ---" % (response.url, time.time() - start_time))

yield l.load_item()


def get_request(self, url, rit=None, splash_retry=None):

#... setting meta & co...
meta = {}
splash_args = {}
return SplashRequest(url=url, callback=self.parse, meta=meta,
args=splash_args, http_status_from_error_code=True,
endpoint='execute', slot_policy=scrapy_splash.SlotPolicy.SCRAPY_DEFAULT)

Gleiches Ergebnis wenn ich es so mache:

 for link in extract_links:
if (not link["nofollow"]) and (l.get_output_value("crawl_meta_nofollow")!= "nofollow"):
r = self.get_viu_request(link["url"])
request_links.append(r)
yield r


Lösung des Problems

yieldDie Leistung ist ideal, Splash verlangsamt Sie. Versuchen Sie, Ihre Daten ohne Splash abzurufen. Überprüfen Sie die Registerkarte "Netzwerk" im devtools, um die tatsächliche Anforderung zu finden, die Ihren dynamischen Inhalt lädt, um die Verwendung von Splash zu vermeiden. Wenn Sie eine Seite freigeben können, die Sie sind Wenn ich versuche zu kratzen, kann ich Ihnen helfen, es mit reinem Kratzen zu kratzen, ohne dass Spritzer oder Selen benötigt werden.

Keine Kommentare:

Kommentar veröffentlichen

Warum werden SCHED_FIFO-Threads derselben physischen CPU zugewiesen, obwohl CPUs im Leerlauf verfügbar sind?

Lösung des Problems Wenn ich das richtig verstehe, versuchen Sie, SCHED_FIFO mit aktiviertem Hyperthreading ("HT") zu verwenden, ...