4

私は簡単なスクリプトを書いています:

  1. URL の大きなリストを読み込みます
  2. リクエストの asyncモジュールを使用して、同時 HTTP リクエストを作成する各 URL のコンテンツを取得します
  3. リンクがページ内にあるかどうかを確認するために、lxml を使用してページのコンテンツを解析します。
  4. ページにリンクが存在する場合、ページに関する情報を ZODB データベースに保存します。

4 つまたは 5 つの URL を使用してスクリプトをテストすると、問題なく動作します。スクリプトが終了すると、次のメッセージのみが表示されます。

 Exception KeyError: KeyError(45989520,) in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored

しかし、約 24000 の URL をチェックしようとすると、リストの最後に向かって失敗し (チェックする URL が約 400 残っている場合)、次のエラーが表示されます。

Traceback (most recent call last):
  File "check.py", line 95, in <module>
  File "/home/alex/code/.virtualenvs/linka/local/lib/python2.7/site-packages/requests/async.py", line 83, in map
  File "/home/alex/code/.virtualenvs/linka/local/lib/python2.7/site-packages/gevent-1.0b2-py2.7-linux-x86_64.egg/gevent/greenlet.py", line 405, in joinall
ImportError: No module named queue
Exception KeyError: KeyError(45989520,) in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored

pypi で入手可能な gevent のバージョンと、 gevent リポジトリから最新バージョン (1.0b2) をダウンロードしてインストールすることの両方を試しました。

なぜこれが起こったのか、そしてたくさんの URL をチェックしたときにのみなぜそれが起こったのか理解できません。助言がありますか?

スクリプト全体は次のとおりです。

from requests import async, defaults
from lxml import html
from urlparse import urlsplit
from gevent import monkey
from BeautifulSoup import UnicodeDammit
from ZODB.FileStorage import FileStorage
from ZODB.DB import DB
import transaction
import persistent
import random

storage = FileStorage('Data.fs')
db = DB(storage)
connection = db.open()
root = connection.root()
monkey.patch_all()
defaults.defaults['base_headers']['User-Agent'] = "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko/20100101 Firefox/11.0"
defaults.defaults['max_retries'] = 10


def save_data(source, target, anchor):
    root[source] = persistent.mapping.PersistentMapping(dict(target=target, anchor=anchor))
    transaction.commit()


def decode_html(html_string):
    converted = UnicodeDammit(html_string, isHTML=True)
    if not converted.unicode:
        raise UnicodeDecodeError(
            "Failed to detect encoding, tried [%s]",
            ', '.join(converted.triedEncodings))
    # print converted.originalEncoding
    return converted.unicode


def find_link(html_doc, url):
    decoded = decode_html(html_doc)
    doc = html.document_fromstring(decoded.encode('utf-8'))
    for element, attribute, link, pos in doc.iterlinks():
        if attribute == "href" and link.startswith('http'):
            netloc = urlsplit(link).netloc
            if "example.org" in netloc:
                return (url, link, element.text_content().strip())
    else:
        return False


def check(response):
    if response.status_code == 200:
        html_doc = response.content
        result = find_link(html_doc, response.url)
        if result:
            source, target, anchor = result
            # print "Source: %s" % source
            # print "Target: %s" % target
            # print "Anchor: %s" % anchor
            # print
            save_data(source, target, anchor)
    global todo
    todo = todo -1
    print todo

def load_urls(fname):
    with open(fname) as fh:
        urls = set([url.strip() for url in fh.readlines()])
        urls = list(urls)
        random.shuffle(urls)
        return urls

if __name__ == "__main__":

    urls = load_urls('urls.txt')
    rs = []
    todo = len(urls)
    print "Ready to analyze %s pages" % len(urls)
    for url in urls:
        rs.append(async.get(url, hooks=dict(response=check), timeout=10.0))
    responses = async.map(rs, size=100)
    print "DONE."
4

3 に答える 3

1

問題の原因はわかりませんが、ファイルの先頭に monkey.patch_all() がないのはなぜですか?

入れてみませんか

from gevent import monkey; monkey.patch_all()

あなたのメインプログラムの一番上で、それが何かを修正するかどうかを確認してください?

于 2012-04-30T14:36:54.423 に答える
0

私はとても大きなn00bですが、とにかく、私は試すことができます...!私はあなたがこれによってあなたのインポートリストを変えることを試みることができると思います:

from requests import async, defaults
import requests
from lxml import html
from urlparse import urlsplit
from gevent import monkey
import gevent
from BeautifulSoup import UnicodeDammit
from ZODB.FileStorage import FileStorage
from ZODB.DB import DB
import transaction
import persistent
import random

これを試して、それが機能するかどうか教えてください..私はそれがあなたの問題を解決できると思います:)

于 2012-04-29T09:07:06.830 に答える