2017-10-28 1 views
1

Ich habe einen Scraper mit Python geschrieben, um Filmnamen von Yiffy Torrents zu kratzen. Die Webseite hat ungefähr 12 Seiten durchlaufen. Wenn ich meinen Crawler mit der print-Anweisung ausführe, erhält er alle Ergebnisse von allen Seiten. Wenn ich jedoch dasselbe mit return starte, dann gibt es mir nur den Inhalt von der ersten Seite und gehe nicht zur nächsten Seite über, um den Rest zu verarbeiten. Da es mir schwer fällt, das Verhalten von return statement zu verstehen, wenn jemand darauf hinweist, wo ich falsch liege und mir einen Workaround gebe, wäre ich sehr glücklich. Danke im Voraus.Scraper sammelt nur den Inhalt der ersten Seite

Dies ist, was ich mit (den vollständigen Code) bin versucht:

import requests 
from urllib.request import urljoin 
from lxml.html import fromstring    

main_link = "https://www.yify-torrent.org/search/western/" 

# film_storage = [] #I tried like this as well (keeping the list storage outside the function) 

def get_links(link): 
    root = fromstring(requests.get(link).text) 
    film_storage = [] 
    for item in root.cssselect(".mv"): 
     name = item.cssselect("h3 a")[0].text 
     film_storage.append(name) 
    return film_storage 

    next_page = root.cssselect(".pager a:contains('Next')")[0].attrib['href'] if root.cssselect(".pager a:contains('Next')") else "" 
    if next_page: 
     full_link = urljoin(link,next_page) 
     get_links(full_link) 

if __name__ == '__main__': 
    items = get_links(main_link) 
    for item in items: 
     print(item) 

Aber, wenn ich wie unten tun, i (nur geklebt wesentlichen Teil) alle Ergebnisse erhalten:

def get_links(link): 
    root = fromstring(requests.get(link).text) 
    for item in root.cssselect(".mv"): 
     name = item.cssselect("h3 a")[0].text 
     print(name)   ## using print i get all the results from all the pages 

    next_page = root.cssselect(".pager a:contains('Next')")[0].attrib['href'] if root.cssselect(".pager a:contains('Next')") else "" 
    if next_page: 
     full_link = urljoin(link,next_page) 
     get_links(full_link) 

Antwort

1

Ihre return-Anweisung vorzeitig beendet Ihre get_links() Funktion. Bedeutung dieser Teil

next_page = root.cssselect(".pager a:contains('Next')")[0].attrib['href'] if root.cssselect(".pager a:contains('Next')") else "" 
    if next_page: 
     full_link = urljoin(link,next_page) 
     get_links(full_link) 

wird nie ausgeführt.

Quickfix wäre, die return-Anweisung am Ende Ihrer Funktion zu setzen, aber Sie müssen film_storage global (definiert außerhalb der Funktion get_links()).

Edit: Nur realisiert, da Sie Ihre film_storage global machen werden, gibt es keine Notwendigkeit für die Rückkehr Aussage.

Ihr Code in Haupt würde aussehen wie folgt aus:

get_links(main_link) 
for item in film_storage: 
    print(item) 
+0

Dies scheint vielversprechend zu sein. Versuchen Sie es und lassen Sie es wissen. Vielen Dank. – SIM

+0

Btw, dies ist nur eine Quickfix-Lösung, wie Sie erwähnt haben, dass Sie gerade Ihre Scraping-Reise beginnen. Aber ich schlage vor, dass Sie in der Zukunft @ Randomirs Lösung/Vorschläge versuchen. Auf diese Weise können Sie bessere und effizientere Abstreifer herstellen. – jabargas

+0

Sorry, nur realisiert, da film_storage global ist, gibt es keine Notwendigkeit für die Rückkehr Aussage. – jabargas

1

Ihre film_storage Ergebnisliste ist lokal für die Funktion get_links(), die für die nächste Seite rekursiv aufgerufen wird. Nach dem rekursiven Aufruf (für alle folgenden Seiten) gibt die Initialfunktion (Eingabe) nur die Ergebnisse für die erste Seite zurück.

Sie müssen entweder (1) die Tail-Rekursion in eine Schleife auspacken, (2) die Ergebnisliste global machen; (3) Verwenden Sie einen Rückruf (wie Sie print anrufen), oder die beste Option (4) ist die Funktion in einen Generator, die Ergebnisse für alle Seiten ergibt.

Generator Version:

def get_links(link): 
    root = fromstring(requests.get(link).text) 
    for item in root.cssselect(".mv"): 
     name = item.cssselect("h3 a")[0].text 
     yield name 

    next_page = root.cssselect(".pager a:contains('Next')")[0].attrib['href'] if root.cssselect(".pager a:contains('Next')") else "" 
    if next_page: 
     full_link = urljoin(link,next_page) 
     for name in get_links(full_link): 
      yield name 
+0

Danke für den Input randomir. +1 dafür. – SIM

+0

Gern geschehen, aber bitte beachten Sie, dass Sie wirklich versuchen sollten, globale Variablen zu vermeiden. Sie machen Ihren Code weniger lesbar, ** verschiedene Teile des Programms sind auf unerwartete Weise gekoppelt **, und insgesamt sind Ihre Programme viel fehleranfälliger. – randomir

Verwandte Themen