2013-03-11 22 views
5

Sto scrivendo un crawler e per questo sto implementando il parser robots.txt, sto usando il lib standard robotparser.Robotparser non sembra analizzare correttamente

Sembra che robotparser è non analisi correttamente, io sono il debug mio crawler utilizzando Google di robots.txt.

(esempi che seguono sono da IPython)

In [1]: import robotparser 

In [2]: x = robotparser.RobotFileParser() 

In [3]: x.set_url("http://www.google.com/robots.txt") 

In [4]: x.read() 

In [5]: x.can_fetch("My_Crawler", "/catalogs") # This should return False, since it's on Disallow 
Out[5]: False 

In [6]: x.can_fetch("My_Crawler", "/catalogs/p?") # This should return True, since it's Allowed 
Out[6]: False 

In [7]: x.can_fetch("My_Crawler", "http://www.google.com/catalogs/p?") 
Out[7]: False 

E 'buffo perché a volte sembra di "lavorare" e, talvolta, sembra venire a mancare, ho anche provato lo stesso con il robots.txt da Facebook e StackOverflow. Si tratta di un bug dal modulo robotpaser? O sto facendo qualcosa di sbagliato qui? E allora?

mi chiedevo se this bug aveva tutto ciò che riguarda

+0

Inoltre sto usando Python 2.7.3 su una macchina Linux (Arch Linux) –

risposta

2

Dopo alcune ricerche di Google non ho trovato nulla di robotparser problema. Ho finito con qualcos'altro, ho trovato un modulo chiamato reppy che ho fatto alcuni test e sembra molto potente. È possibile installarlo tramite pip;

pip install reppy 

Ecco alcuni esempi (su IPython) utilizzando Reppy, ancora una volta, utilizzando robots.txt

In [1]: import reppy 

In [2]: x = reppy.fetch("http://google.com/robots.txt") 

In [3]: x.atts 
Out[3]: 
{'agents': {'*': <reppy.agent at 0x1fd9610>}, 
'sitemaps': ['http://www.gstatic.com/culturalinstitute/sitemaps/www_google_com_culturalinstitute/sitemap-index.xml', 
    'http://www.google.com/hostednews/sitemap_index.xml', 
    'http://www.google.com/sitemaps_webmasters.xml', 
    'http://www.google.com/ventures/sitemap_ventures.xml', 
    'http://www.gstatic.com/dictionary/static/sitemaps/sitemap_index.xml', 
    'http://www.gstatic.com/earth/gallery/sitemaps/sitemap.xml', 
    'http://www.gstatic.com/s2/sitemaps/profiles-sitemap.xml', 
    'http://www.gstatic.com/trends/websites/sitemaps/sitemapindex.xml']} 

In [4]: x.allowed("/catalogs/about", "My_crawler") # Should return True, since it's allowed. 
Out[4]: True 

In [5]: x.allowed("/catalogs", "My_crawler") # Should return False, since it's not allowed. 
Out[5]: False 

In [7]: x.allowed("/catalogs/p?", "My_crawler") # Should return True, since it's allowed. 
Out[7]: True 

In [8]: x.refresh() # Refresh robots.txt, perhaps a magic change? 

In [9]: x.ttl 
Out[9]: 3721.3556718826294 

In [10]: # It also has a x.disallowed function. The contrary of x.allowed 
2

domanda interessante di Google. Ho dato un'occhiata alla fonte (ho python 2.4 sorgente disponibile solo, ma scommetto che non è cambiata) e il codice normalizza l'URL che è in fase di test eseguendo:

urllib.quote(urlparse.urlparse(urllib.unquote(url))[2]) 

che è la fonte di i vostri problemi: "?"

>>> urllib.quote(urlparse.urlparse(urllib.unquote("/foo"))[2]) 
'/foo' 
>>> urllib.quote(urlparse.urlparse(urllib.unquote("/foo?"))[2]) 
'/foo' 

quindi è sia un bug nella libreria di Python, o Google sta rompendo le specifiche robot.txt includendo un personaggio in una regola (che è un po 'insolita).

[nel caso non sia chiaro, lo ripeto in un altro modo. il codice sopra è usato dalla libreria robotparser come parte del controllo dell'URL. quindi quando l'URL termina con un "?" quel personaggio è caduto. quindi, quando hai verificato il /catalogs/p?, il test effettivo eseguito era /catalogs/p. quindi il tuo sorprendente risultato.]

suggerirei filing a bug con la gente di Python (puoi inserire un link qui come parte della spiegazione) [modifica: grazie]. e poi usando l'altra libreria che hai trovato ...

+0

Grazie! Hai ragione, ho fatto lo stesso controllo con la lib che ho trovato e sfortunatamente fanno lo stesso, anche se funziona meglio di robotparser, il problema è lo stesso. Ho segnalato il bug -> http://bugs.python.org/issue17403 –

1

Circa una settimana fa abbiamo unito un commit con un bug che causa questo problema. Abbiamo semplicemente spinto la versione 0.2.2 per pip e master nel repository includendo un test di regressione proprio per questo problema.

La versione 0.2 contiene una leggera modifica dell'interfaccia: ora è necessario creare un oggetto RobotsCache che contenga l'interfaccia esatta che aveva originariamente lo reppy. Questo era principalmente per rendere esplicita la memorizzazione nella cache e rendere possibile avere cache differenti all'interno dello stesso processo.Ma ecco, ora funziona di nuovo!

from reppy.cache import RobotsCache 
cache = RobotsCache() 
cache.allowed('http://www.google.com/catalogs', 'foo') 
cache.allowed('http://www.google.com/catalogs/p', 'foo') 
cache.allowed('http://www.google.com/catalogs/p?', 'foo') 
+1

Grazie! È fantastico! +10 per Reppy, ha fatto un rapido problema e in meno di 24 ore è stato risolto! Grazie ancora! –

4

Questo non è un bug, ma piuttosto una differenza nell'interpretazione. Secondo il draft robots.txt specification (che non è mai stato approvato, né è probabile che sia):

Valutare se è consentito l'accesso a un URL, un robot deve cercare di abbinare i percorsi a permettere e impedire che le linee contro il URL, nell'ordine che si verificano nel record. Viene utilizzata la prima corrispondenza trovata. Se non viene trovata alcuna corrispondenza , l'ipotesi predefinita è che l'URL sia consentito.

(Sezione 3.2.2, il permettere e impedire Lines)

Utilizzando questa interpretazione, poi "/ cataloghi/p?" dovrebbe essere rifiutato perché c'è una direttiva "Disallow:/catalogs" in precedenza.

A un certo punto, Google ha iniziato a interpretare robots.txt in modo diverso da tale specifica. Il loro metodo sembra essere:

Check for Allow. If it matches, crawl the page. 
Check for Disallow. If it matches, don't crawl. 
Otherwise, crawl. 

Il problema è che non esiste un accordo formale sull'interpretazione di robots.txt. Ho visto dei crawler che usano il metodo di Google e altri che usano la bozza dello standard dal 1996. Quando gestivo un crawler, ricevevo i nastygram dai webmaster quando usavo l'interpretazione di Google perché ho scansionato le pagine che pensavano non dovessero essere sottoposte a scansione, e ho ottenuto dei brutti scherzi dagli altri se avessi usato l'altra interpretazione perché roba che pensavano dovesse essere indicizzata, non lo era.