0

私はpythonが初めてで、以下のコードで:新しく発見されたリンクを再帰するクローラーがあります。ルートリンクを再帰した後、いくつかのリンクを印刷した後にプログラムが停止したように見えます.これはしばらく続くはずですが、そうではありません. 例外をキャッチして出力していますが、プログラムは正常に終了するため、停止する理由がよくわかりません。

from urllib import urlopen
from bs4 import BeautifulSoup

def crawl(url, seen):
    try:
    if any(url in s for s in seen):
       return 0
    html = urlopen(url).read()

    soup = BeautifulSoup(html)
    for tag in soup.findAll('a', href=True):
        str = tag['href']
        if 'http' in str:
        print tag['href']
        seen.append(str)
        print "--------------"
        crawl(str, seen)
    except Exception, e:
      print e
      return 0

def main ():
    print "$ = " , crawl("http://news.google.ca", [])


if __name__ == "__main__":
    main()
4

2 に答える 2

1
    for tag in soup.findAll('a', href=True):
        str = tag['href']
        if 'http' in str:
            print tag['href']
            seen.append(str)        # you put the newly founded url to *seen*
            print "--------------"
            crawl(str, seen)        # then you try to crawl it

しかし、開始当初はcrawl

if any(url in s for s in seen): # you don't crawl url in *seen*
   return 0

url見つけたときではなく、実際にクロールしたときに追加する必要があります。

于 2012-07-28T09:31:44.307 に答える
0
try:
    if any(url in s for s in seen):
       return 0

その後

seen.append(str)
print "--------------"
crawl(str, seen)

に追加strしてから、とを引数としてseen呼び出します。明らかに、コードは終了します。あなたはそのような方法でそれを設計しました。crawlstrseen

より良い方法は、1 つのページをクロールし、見つかったすべてのリンクをクロール対象のリストに追加してから、そのリスト内のすべてのリンクをクロールし続けることです。

簡単に言えば、深さ優先のクロールではなく、幅優先のクロールを行う必要があります。

このようなものがうまくいくはずです。

from urllib import urlopen
from bs4 import BeautifulSoup

def crawl(url, seen, to_crawl):
    html = urlopen(url).read()
    soup = BeautifulSoup(html)
    seen.append(url)
    for tag in soup.findAll('a', href=True):
        str = tag['href']
        if 'http' in str:
            if url not in seen and url not in to_crawl:
                to_crawl.append(str)
                print tag['href']
                print "--------------"
    crawl(to_crawl.pop(), seen, to_crawl)

def main ():
    print "$ = " , crawl("http://news.google.ca", [], [])


if __name__ == "__main__":
    main()

ただし、クロールする URL の最大深度または最大数に制限を設けたいと思うかもしれません。

于 2012-07-28T09:30:32.137 に答える