2

現在、urllib2 を使用して python2.7 で単純なクローラーを作成しています。これがダウンローダークラスです。

class Downloader:
    def __init__(self, limit = 3):
        self.limit = limit

    def downloadGet(self, url):
        request = urllib2.Request(url)
        retry = 0
        succ = False
        page = None

        while retry < self.limit:
            print "Retry: " + str(retry) + " Limit:" + str(self.limit)
            try:
                response = urllib2.urlopen(request)
                page = response.read()
                succ = True
                break
            except:
                retry += 1

        return succ, page

すべての URL が 3 回試行されます。マルチスレッドも使用されており、スレッドコードは次のとおりです。

class DownloadThread(Thread):
    def __init__(self, requestGet, limit):
        Thread.__init__(self)
        self.requestGet = requestGet
        self.downloader = Downloader(limit)

    def run(self):
        while True:
            url = self.requestGet()
            if url == None:
                break

            ret = self.download(url)
            print ret

    def download(self, url):
        # some other staff
        succ, flv = self.downloader.downloadGet(url)
        return succ

ただし、スレッド数を 5 に設定した実験では、ダウンローダーは 3 回試行しても停止しません。一部のスレッドでは、出力に "Retry: 4280 Limit:3" も表示されます。while 条件が無視されているようです。

どんな助けや提案も大歓迎です。ありがとうございました!

4

3 に答える 3

5

downloadGet:の無限ループの考えられる原因の 1 つlimitは、文字列オブジェクトです。

limit文字列の場合、Python 2.xでretry < self.limit生成されます:True

>>> retry = 4280
>>> limit = '3'
>>> retry < limit
True

limit渡された型を確認してください。

于 2013-11-06T10:57:05.273 に答える
0

DownloadThreadURL が空でない場合、while ループから抜け出すコードは何もありません。

于 2013-11-06T10:53:58.437 に答える
0

より Pythonic な方法でループを定義する必要があります。

def downloadGet(self, url):
    ...
    # do not declare retry before this
    for retry in xrange(self.limit):
        ...
        try:

編集:

whileまたは、ループ状態をより明確に処理するために を利用することもできますbreak(ただし、最初の例はそれほど脆弱ではないように感じます)。

def downloadGt(self, url):
    ...
    while retry in xrange(self.limit) or succ == False:
        ...

これには、より自己文書化できるという利点があります。

ただし、ループをダウンローダではなくダウンロードにリファクタリングすることを検討します。このようなもの:

class DownloadThread(Thread):
    ...
    def download(self, url):
        for retry in xrange(self.downloader.limit):
            succ, flv = self.downloader.downloadGet(url)
            if succ:
                return succ


class Downloader(object):
    ...
    def downloadGet(self, url)
        request = urllib2.Request(url)
        try:
            response = urllib2.urlopen(request)
            page = response.read()

        # always qualify your exception handlers 
        # or you may be masking errors you don't know about
        except urllib2.HTTPError:
            return False, None

        return True, page
于 2013-11-06T10:59:36.083 に答える