2017-11-28 13 views
0

Ich lehre mich selbst Python und kam mit dem Aufbau einer einfachen Web-Crawler-Engine. Die Codes sind unten,Einfacher Web-Crawler in Python

def find_next_url(page): 
    start_of_url_line = page.find('<a href') 
    if start_of_url_line == -1: 
     return None, 0 
else: 
    start_of_url = page.find('"http', start_of_url_line) 
    if start_of_url == -1: 
     return None, 0 
    else: 
     end_of_url = page.find('"', start_of_url + 1) 
     one_url = page[start_of_url + 1 : end_of_url] 
     return one_url, end_of_url 

def get_all_url(page): 
p = [] 
while True: 
    url, end_pos = find_next_url(page) 
    if url: 
     p.append(url) 
     page = page[end_pos + 1 : ] 
    else: 
     break 
return p 

def union(a, b): 
    for e in b: 
    if e not in a: 
     a.append(e) 
    return a 

def webcrawl(seed): 
    tocrawl = [seed] 
    crawled = [] 
    while True: 
     page = tocrawl.pop() 
     if page not in crawled: 
      import urllib.request 
      intpage = urllib.request.urlopen(page).read() 
      openpage = str(intpage) 
      union(tocrawl, get_all_url(openpage)) 
      crawled.append(page) 
    return crawled 

Allerdings bekomme ich immer HTTP 403 Fehler.

+2

403 Mittel [** Verbotene **] (https://en.wikipedia.org/wiki/HTTP_403) - ohne zu wissen, auf welche URL (n) Sie zugreifen möchten, ist es schwer zu sagen, ob dies ein * gewünschtes * Verhalten ist. –

+0

was ich versuche zu erreichen, ist zu sehen, ob der Code einige URL von einer Seite holen kann und dann in jede einzelne URL gehen und mehr URLs innerhalb der früher gefundenen Liste von URLs holen kann.Ich werde das wahrscheinlich erreichen, wenn ich eine einfache Webseite mit einigen HTTP-Hyperlinks habe, die mir dann weitere URLs geben und dort aufhören werden. Ich habe es mit https://xkcd.com/353/ versucht. – Sayan

Antwort

1

HTTP 403-Fehler ist nicht mit Ihrem Code verbunden. Es bedeutet, dass die URL, die gecrawlt wird, nicht zugänglich ist. Meistens bedeutet dies, dass die Seite nur angemeldeten Benutzern oder einem bestimmten Benutzer zur Verfügung steht.


Ich habe Ihren Code tatsächlich ausgeführt und 403 mit creativecommons link erhalten. Der Grund ist, dass urllib Host Header nicht standardmäßig sendet und Sie sollten es manuell hinzufügen, um den Fehler nicht zu erhalten (die meisten Server werden überprüfen Sie die Host Header und entscheiden, welchen Inhalt sie dienen sollen). Sie könnten auch Requests python package anstelle der eingebauten urllib verwenden, die Host Header standardmäßig sendet und mehr Pythonons IMO ist.

Ich füge eine try-exept-Klausel hinzu, um Fehler zu erfassen und zu protokollieren, und fahre fort, andere Links zu crawlen. Es gibt viele defekte Links im Internet.

from urllib.request import urlopen 
from urllib.error import HTTPError 
... 
def webcrawl(seed): 
    tocrawl = [seed] 
    crawled = [] 
    while True: 
     page = tocrawl.pop() 
     if page not in crawled: 
      try: 
       intpage = urlopen(page).read() 
       openpage = str(intpage) 
       union(tocrawl, get_all_url(openpage)) 
       crawled.append(page) 
      except HTTPError as ex: 
       print('got http error while crawling', page) 
    return crawled 
+0

was ich versuche zu erreichen, ist zu sehen, ob der Code einige URL von einer Seite holen und dann in jede einzelne URL gehen und mehr URLs innerhalb der früher gefundenen Liste von URLs holen kann. Ich werde das wahrscheinlich erreichen, wenn ich eine einfache Webseite mit einigen HTTP-Hyperlinks habe, die mir dann weitere URLs geben und dort aufhören werden. – Sayan

+0

Versuchen Sie, den genauen URL zu finden, der den Fehler 403 verursacht, und fügen Sie ihn zu Ihrer Frage hinzu. Es ist wahrscheinlicher, dass die URL das Problem ist. Versuchen Sie, die URL vor dem Aufruf von "urlopen" zu drucken. –

+0

Ich fand die URL aus dem ersten Satz der Liste - http://creativecommons.org/licenses/by-nc/2.5/ – Sayan

1

Sie müssen möglicherweise Anforderungsheader oder andere Authentifizierung hinzufügen. Versuchen Sie, Benutzeragenten hinzuzufügen, um ReCaptcha in einigen Fällen zu vermeiden.

Beispiel:

User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36 
0

Wie andere gesagt haben, wird der Fehler nicht durch den Code selbst verursacht, aber Sie können ein paar Dinge

  • Versuchen Hinzufügen Exception-Handler versuchen wollen zu tun , vielleicht sogar die problematischen Seiten insgesamt ignorieren, um sicherzustellen, dass der Crawler wie erwartet funktioniert:

    def webcrawl(seed): 
        tocrawl = [seed] 
        crawled = [] 
        while tocrawl: # replace `while True` with an actual condition, 
            # otherwise you'll be stuck in an infinite loop 
            # until you hit an exception 
         page = tocrawl.pop() 
         if page not in crawled: 
          import urllib.request 
          try: 
           intpage = urllib.request.urlopen(page).read() 
           openpage = str(intpage) 
           union(tocrawl, get_all_url(openpage)) 
           crawled.append(page) 
          except urllib.error.HTTPError as e: # catch an exception 
           if e.code == 401: # check the status code and take action 
            pass # or anything else you want to do in case of an `Unauthorized` error 
           elif e.code == 403: 
            pass # or anything else you want to do in case of a `Forbidden` error 
           elif e.cide == 404: 
            pass # or anything else you want to do in case of a `Not Found` error 
           # etc 
           else: 
            print('Exception:\n{}'.format(e)) # print an unexpected exception 
            sys.exit(1) # finish the process with exit code 1 (indicates there was a problem) 
        return crawled 
    
  • Versuchen Sie, einen User-Agent Header in Ihre Anfrage einzufügen. Von urllib.request docs:

Dies wird häufig verwendet, um „Parodie“ der User-Agent Header, der von einem Browser verwendet wird selbst zu identifizieren - einig HTTP-Server ermöglicht es nur kommen Anfragen von gemeinsamem Browser im Gegensatz zu Skripte. Zum Beispiel kann Mozilla Firefox identifizieren sich als "Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11", während des urllib Standard-String-User-Agent "Python-urllib/2.6" (auf Python 2.6) ist.

So etwas wie dies vielleicht um einige der 403 Fehler zu erhalten helfen:

headers = {'User-Agent':'Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11'} 
    req = urllib.request.Request(page, headers=headers) 
    intpage = urllib.request.urlopen(req).read() 
    openpage = str(intpage)