2017-11-03 6 views
1

Wie verschrotten Sie eine Webseite mit unendlichen Blättern, wo die Antwort ist HTML/Text anstelle von JSON.Scraping Infinite Scrolling Seiten mit "mehr laden" -Taste mit Scrapy

Mein erster Versuch Regel und LinkExtractor wurde mit dem mir rund 80% der Arbeitsplätze erhält url

class JobsetSpider(CrawlSpider): 
    name = 'test' 
    allowed_domains = ['jobs.et'] 
    start_urls = ['https://jobs.et/jobs/'] 

    rules = (
     Rule(LinkExtractor(allow='https://jobs.et/job/\d+/'), callback='parse_link'), 
     Rule(LinkExtractor(), follow=True), 
    ) 

    def parse_link(self, response): 
     yield { 
      'url': response.url 
     } 

Mein zweiter Versuch, das Beispiel von SCRAPING INFINITE SCROLLING PAGES zu verwenden war, aber die Antwort ist in text/html nicht json.

Wenn „Last mehr“ Schaltfläche geklickt, kann ich von Netzwerk auf Chrome Developer-Tool finden Sie in der Anfrage-URL

https://jobs.et/jobs/?searchId=1509738711.5142&action=search&page=2 

während der „Seite“ Zahl zu erhöhen.

Meine Frage ist

  1. Wie kann ich die oben URL aus den Antwort-Header mit scrapy extrahieren, wenn die „Last mehr“ Schaltfläche geklickt wird
  2. Gibt es einen besseren Weg, um dieses Problem zu nähern?

Antwort

1

Ignorieren Sie die Schaltfläche "Weitere laden".

Sie können auf alle Seiten von Jobs mithilfe von URLs zugreifen, wie Sie bereits erwähnt haben. Wenn Sie die erste Seite analysieren die Ergebnisse die Gesamtzahl der Arbeitsplätze aus dem Kopfelement

<h1 class="search-results__title "> 
268 jobs found 
</h1> 

Die Seite zeigt 20 Jobs pro Seite finden, so dass Sie kratzen müssen 268/20 = 13,4 (aufgerundet auf 14) Seiten .

Wenn Sie mit der Analyse der ersten Seite fertig sind, erstellen Sie einen Generator, um URLs für die nachfolgenden Seiten zu erhalten (in einer Schleife bis zu 14) und parsen Sie das Ergebnis mit einer anderen Funktion. Sie benötigen die searchId, die Sie nicht von der URL erhalten können, sondern in einem versteckten Feld auf der Seite.

<input type="hidden" name="searchId" value="1509738711.5142"> 

verwenden, und die Seitenzahl können Sie Ihre URLs bauen

https://jobs.et/jobs/?searchId=<id>&action=search&page=<page> 

Ja, die Parse-Funktion die gleiche wie die erste Seite Parser genau tun werden, aber wenn Sie es arbeiten alle bekommen es ist Es ist gut, mit der Code-Duplizierung zu leben, um die Dinge im Kopf zu behalten.

Der Code dafür könnte so etwas wie

class JobsetSpider(CrawlSpider): 
    ... 
    start_urls = ['https://jobs.et/jobs/'] 
    ... 

    def parse(self, response): 
     # parse the page of jobs 
     ... 
     job_count = xpath(...) 
     search_id = xpath(...) 
     pages = math.ceil(job_count/20.0) 
     for page in range(2, pages): 
      url = 'https://jobs.et/jobs/?searchId={}&action=search&page={}'.format(search_id, page) 
      yield Request(url, callback = self.parseNextPage) 

    def parseNextPage(self, response): 
     # parse the next and subsequent pages of jobs 
     ... 
+1

ich dank sehen, würde ich nur die Seiten zu 'Seiten = Math.ceil bearbeiten (job_count/20,0) + 1 ', da die Dosis nicht das Ende enthält. – sgetachew

1

Sie sich etwas hinzufügen könnte wie:

has_next = response.css('.load-more').extract() 
if has_next: 
    next_page = response.meta.get('next_page', 1) + 1 
    url = response.urljoin(response.css('script').re_first("'(\?searchId.*page=)'") + str(next_page)) 
    yield Request(url , meta={'next_page': next_page}) 
+0

Es gibt das richtige URL-Format zurück, aber die Anzahl der zurückgegebenen URLs ist unendlich. – sgetachew

+0

hmm, man könnte prüfen, ob die Seite tatsächlich "neue" Daten bringt oder wann ein Datumslimit erreicht wurde oder in der Meta die aktuelle Anzahl der Elemente einsenden und anhalten, wenn man sie alle gesehen hat (zB 268) Tony zeigte und ging zum meta '268-20' und so weiter (zB: mach weiter bis du 0 erreichst). – Wilfredo