Errno 10054在使用Python抓取HTML时:如何重新连接

时间:2014-04-25 16:56:11

标签: python html runtime-error screen-scraping

我是一名新手Python程序员,试图使用Python从fanfiction.net中抓取大量页面,并将页面的HTML源的特定行存入.csv文件。我的程序工作正常,但最终遇到停止运行的障碍。我的IDE告诉我该程序遇到了“Errno 10054:远程主机强行关闭现有连接”。

我正在寻找一种让我的代码重新连接的方法,并在每次收到错误时继续。我的代码每次运行时都会抓几十页;这对网站来说可能太过分了吗?该网站似乎不会阻止抓取。我已经对这个问题进行了大量的研究,并试图实现重试装饰器,但装饰器似乎不起作用。这是我的代码的相关部分:

def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):

    def deco_retry(f):

        @wraps(f)
        def f_retry(*args, **kwargs):
            mtries, mdelay = tries, delay
            while mtries > 1:
                try:
                    return f(*args, **kwargs)
                except ExceptionToCheck as e:
                    msg = "%s, Retrying in %d seconds..." % (str(e), mdelay)
                    if logger:
                        logger.warning(msg)
                    else:
                        print(msg)
                    time.sleep(mdelay)
                    mtries -= 1
                    mdelay *= backoff
            return f(*args, **kwargs)

        return f_retry  # true decorator

    return deco_retry


@retry(urllib.error.URLError, tries=4, delay=3, backoff=2)
def retrieveURL(URL):
    response = urllib.request.urlopen(URL)
    return response


def main():
    # first check: 5000 to 100,000 
    MAX_ID = 600000
    ID = 400001
    URL = "http://www.fanfiction.net/s/" + str(ID) + "/index.html"
    fCSV = open('buffyData400k600k.csv', 'w')
    fCSV.write("Rating, Language, Genre 1, Genre 2, Character A, Character B, Character C,     Character D, Chapters, Words, Reviews, Favorites, Follows, Updated, Published, Story ID, Story Status, Author ID, Author Name" + '\n')    

    while ID <= MAX_ID:

        URL = "http://www.fanfiction.net/s/" + str(ID) + "/index.html"
        response = retrieveURL(URL)

每当我在IDE之外运行.py文件时,它最终会锁定并在大约一小时后停止抓取新页面。我也在我的IDE中运行同一文件的不同版本,现在看起来已经运行了近12个小时,如果不是更长的话 - 该文件是否可以在我的IDE中运行但不能独立运行?

我的装饰师设置错了吗?我还有什么办法可以让python重新连接?我也看到声称SQL本机客户端过时可能会导致像我这样的Window用户出现问题 - 这是真的吗?我试图更新,但没有运气。

谢谢!

2 个答案:

答案 0 :(得分:2)

你正在捕获URLErrors,Errno:10054不是,所以你的@retry装饰器不会重试。试试这个。

@retry(Exception, tries=4)
def retrieveURL(URL):
    response = urllib.request.urlopen(URL)
    return response

这应该在任何Exception上重试4次。您的@retry装饰器已正确定义。

答案 1 :(得分:1)

您重新连接的代码看起来很好,除了一部分 - 您尝试捕获的例外情况。根据{{​​3}},Errno 10054socket.error。您需要做的就是import socket并在重试处理程序中添加except socket.error语句。