我建立了一个必须在大约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中实现的算法必须有一个解决方案(我不能回到原来的 “算法” ,永远不会结束)。
谢谢!
这将递归变成一个循环:
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)