小编典典

Python:调用Python对象时超出了最大递归深度

algorithm

我建立了一个必须在大约500万个页面上运行的搜寻器(通过增加url ID),然后解析包含我需要的信息的页面。

使用在网址(200K)上运行并保存好坏结果的算法后,我发现我在浪费大量时间。我可以看到有一些返回的子代换代码,可用于检查下一个有效的URL。

您可以很快地看到子交易(一些最初的“好ID”的前几位)

510000011 # +8
510000029 # +18
510000037 # +8
510000045 # +8
510000052 # +7
510000060 # +8
510000078 # +18
510000086 # +8
510000094 # +8
510000102 # +8
510000110 # etc'
510000128
510000136
510000144
510000151
510000169
510000177
510000185
510000193
510000201

在抓取大约200K网址后,我只得到了14K好的结果,我知道我在浪费时间,需要对其进行优化,因此我运行了一些统计信息,并构建了一个函数来检查网址,同时使用8
\ 18 \ 17 \来增加id 8(返回的最差子)等。

这是功能-

def checkNextID(ID):
    global numOfRuns, curRes, lastResult
    while ID < lastResult:
        try:
            numOfRuns += 1
            if numOfRuns % 10 == 0:
                time.sleep(3) # sleep every 10 iterations
            if isValid(ID + 8):
                parseHTML(curRes)
                checkNextID(ID + 8)
                return 0
            if isValid(ID + 18):
                parseHTML(curRes)
                checkNextID(ID + 18)
                return 0
            if isValid(ID + 7):
                parseHTML(curRes)
                checkNextID(ID + 7)
                return 0
            if isValid(ID + 17):
                parseHTML(curRes)
                checkNextID(ID + 17)
                return 0
            if isValid(ID+6):
                parseHTML(curRes)
                checkNextID(ID + 6)
                return 0
            if isValid(ID + 16):
                parseHTML(curRes)
                checkNextID(ID + 16)
                return 0
            else:
                checkNextID(ID + 1)
                return 0
        except Exception, e:
            print "somethin went wrong: " + str(e)

基本的作用是-checkNextID(ID)正在获取包含数据减去8的第一个ID,因此第一次迭代将匹配第一个“ if
isValid”子句(isValid(ID + 8)将返回True)。

lastResult 是一个变量,该变量保存最后一个已知的URL ID,因此我们将运行直到numOfRuns为

isValid() 是一个获取ID +子代数之一的函数,如果该URL包含我需要的内容,则返回True,并将该URL的汤对象保存到名为’
curRes ‘ 的全局变量中,如果该URL不 包含 ,则返回False没有包含我需要的数据。

parseHTML 是一个获取汤对象(curRes),解析我需要的数据,然后将数据保存到csv,然后返回True的函数。

如果isValid()返回True,我们将调用parseHTML(),然后尝试检查下一个ID +
subtrahends(通过调用checkNextID(ID +
subtrahends)),如果它们都不返回我要查找的内容,将其增加1,然后再次检查,直到找到下一个有效网址。

您可以在此处查看其余代码

运行代码后,我得到了大约950个好的结果,并突然引发了异常-

“出了点问题:调用Python对象时超出了最大递归深度”

我可以在WireShark上看到scipt卡在id上-510009541(我用510000003启动了我的脚本),该脚本尝试几次获取具有该ID的url,然后才注意到该错误并停止了该错误。

我真的很高兴看到我得到了相同的结果,但是比我的旧脚本快25到40倍,并且HTTP请求减少了,这非常准确,我错过了1000个好结果中只有1个结果,这是我发现的,不可能朗读5M次,我的旧脚本运行了30个小时,而新脚本在5-10分钟内给我960〜的结果时,我得到了14-15K的结果。

我读到了有关堆栈限制的信息,但是对于要在Python中实现的算法必须有一个解决方案(我不能回到原来的 “算法” ,永远不会结束)。

谢谢!


阅读 741

收藏
2020-07-28

共1个答案

小编典典

这将递归变成一个循环:

def checkNextID(ID):
    global numOfRuns, curRes, lastResult
    while ID < lastResult:
        try:
            numOfRuns += 1
            if numOfRuns % 10 == 0:
                time.sleep(3) # sleep every 10 iterations
            if isValid(ID + 8):
                parseHTML(curRes)
                ID = ID + 8
            elif isValid(ID + 18):
                parseHTML(curRes)
                ID = ID + 18
            elif isValid(ID + 7):
                parseHTML(curRes)
                ID = ID + 7
            elif isValid(ID + 17):
                parseHTML(curRes)
                ID = ID + 17
            elif isValid(ID+6):
                parseHTML(curRes)
                ID = ID + 6
            elif isValid(ID + 16):
                parseHTML(curRes)
                ID = ID + 16
            else:
                ID = ID + 1
        except Exception, e:
            print "somethin went wrong: " + str(e)
2020-07-28