我已经建立了一个爬虫,需要运行在大约五百万个页面上(通过增加url ID),然后解析包含所需信息的页面。
使用运行在200K个URL上的算法并保存好的和坏的结果后,我发现浪费了很多时间。我可以看到有一些返回的被减数,可以用来检查下一个有效的URL。
你可以快速看到这些被减数(前几个“good IDs”的小例子)。
在爬取约200K个URL后,只得到了14K个好结果,我知道我正在浪费时间,需要优化它。所以我运行了一些统计并构建了一个函数,将检查URL,同时使用8\18\17\8(返回顶部的减数)等递增ID。
这是该功能 -
基本上它所做的是- checkNextID(ID)获取第一个包含数据减8的ID,因此第一次迭代将匹配第一个“if isValid”子句(isValid(ID + 8)将返回True)。 lastResult是保存最后已知的URL ID的变量,因此我们将运行直到numOfRuns为止。
isValid()是一个函数,它获取ID +其中一个减数并返回True,如果URL包含我需要的内容并将URL的soup对象保存到名为' curRes '的全局变量中,则返回True,如果URL不包含我需要的数据则返回False。 parseHTML是一个函数,它获取soup对象(curRes),解析我需要的数据,然后将数据保存到csv中,然后返回True。
如果isValid()返回True,我们将调用parseHTML(),然后尝试检查下一个ID +减数(通过调用checkNextID(ID + subtrahends),如果没有一个返回我要找的结果,我将增加1并再次检查,直到我找到下一个有效的URL。
您可以在这里看到其余代码
运行代码后,我得到了大约950个好的结果,突然出现了异常 -
"something went wrong:maximum recursion depth exceeded while calling a Python object"
我在WireShark上看到脚本卡在id-510009541(我用510000003启动了我的脚本),在我注意到错误并停止它之前,脚本尝试几次获取该ID的URL。
我非常兴奋地发现,与我的旧脚本相比,使用更少的HTTP请求,速度快25倍至40倍,非常精确,我错过了1000个好结果中的1个结果,这对我来说是可以接受的,运行5M次是不可能的,我的旧脚本运行了30小时,只得到了14-15K个结果,而我的新脚本在5-10分钟内给我提供了960个结果左右。
我读过关于堆栈限制的文章,但我正在尝试在Python中实现的算法必须有解决方案(我不能回到我的旧“算法”,它永远不会结束)。
谢谢!
使用运行在200K个URL上的算法并保存好的和坏的结果后,我发现浪费了很多时间。我可以看到有一些返回的被减数,可以用来检查下一个有效的URL。
你可以快速看到这些被减数(前几个“good IDs”的小例子)。
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个URL后,只得到了14K个好结果,我知道我正在浪费时间,需要优化它。所以我运行了一些统计并构建了一个函数,将检查URL,同时使用8\18\17\8(返回顶部的减数)等递增ID。
这是该功能 -
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 +其中一个减数并返回True,如果URL包含我需要的内容并将URL的soup对象保存到名为' curRes '的全局变量中,则返回True,如果URL不包含我需要的数据则返回False。 parseHTML是一个函数,它获取soup对象(curRes),解析我需要的数据,然后将数据保存到csv中,然后返回True。
如果isValid()返回True,我们将调用parseHTML(),然后尝试检查下一个ID +减数(通过调用checkNextID(ID + subtrahends),如果没有一个返回我要找的结果,我将增加1并再次检查,直到我找到下一个有效的URL。
您可以在这里看到其余代码
运行代码后,我得到了大约950个好的结果,突然出现了异常 -
"something went wrong:maximum recursion depth exceeded while calling a Python object"
我在WireShark上看到脚本卡在id-510009541(我用510000003启动了我的脚本),在我注意到错误并停止它之前,脚本尝试几次获取该ID的URL。
我非常兴奋地发现,与我的旧脚本相比,使用更少的HTTP请求,速度快25倍至40倍,非常精确,我错过了1000个好结果中的1个结果,这对我来说是可以接受的,运行5M次是不可能的,我的旧脚本运行了30小时,只得到了14-15K个结果,而我的新脚本在5-10分钟内给我提供了960个结果左右。
我读过关于堆栈限制的文章,但我正在尝试在Python中实现的算法必须有解决方案(我不能回到我的旧“算法”,它永远不会结束)。
谢谢!