**在帖子末尾添加了问题摘要**
我写了一个抓取和解析网址的爬虫程序。在
在第一个版本中,为了得到下一个有效的页面,我增加了URL ID并将无效ID保存到一个文件中,有效的URL被移动到解析我需要的内容的解析器中,过了一会儿,我发现大多数有效的ID都有一个返回的子线程。在
我做了一些统计,得到了一系列的副标题-[8,18,7,17,6,16,5,15],按重复次数最多到最少排序。在
所以我changed my code来-
def checkNextID(ID):
numOfRuns = 0
global curRes, lastResult
while ID < lastResult:
try:
numOfRuns += 1
if numOfRuns % 10 == 0:
time.sleep(7) # sleep every 10 iterations
numOfRuns = 0
if isValid(ID + 8):
parseHTML(curRes, ID)
ID = ID + 8
elif isValid(ID + 18):
parseHTML(curRes, ID)
ID = ID + 18
elif isValid(ID + 7):
parseHTML(curRes, ID)
ID = ID + 7
elif isValid(ID + 17):
parseHTML(curRes, ID)
ID = ID + 17
elif isValid(ID+6):
parseHTML(curRes, ID)
ID = ID + 6
elif isValid(ID + 16):
parseHTML(curRes, ID)
ID = ID + 16
elif isValid(ID + 5):
parseHTML(curRes, ID)
ID = ID + 5
elif isValid(ID + 15):
parseHTML(curRes, ID)
ID = ID + 15
else:
if isValid(ID + 1):
parseHTML(curRes, ID)
ID = ID + 1
except Exception, e:
print "something went wrong: " + str(e)
isValid()是一个函数,它获取一个ID+其中一个子线程,如果url包含我需要的内容,则返回True,并将url的soup对象保存到名为“curRes”的全局变量中;如果url不包含我需要的数据,则返回False,并将ID保存到“baddfile”。在
parseHTML是一个函数,它获取soup对象(curRes),解析我需要的数据,然后将数据保存到csv,然后返回True。在
在一个完美的世界里,这段代码就是我在所有有效ID上运行所需的一切(5M范围内大约有400K个),它让我在更短的时间内获得更好的结果(x50更快)。在
但是,当到达不包含任何有效URL的范围时,我的代码效率非常低,在每次迭代中我都会一遍又一遍地爬行相同的URL,这是因为我将ID增加一个,以便继续前进,直到找到下一个有效的URL,然后检查ID+8,然后检查18,17等',有时给我相同的网址,我在上一次迭代检查。在
所以我去修改了代码,这样它将保留一组无效的url,我将避免再次检查,我不能让它工作,我打破了我的头几个小时,它没有正常工作。在
这是我的新功能-
^{pr2}$我将每个无效的ID保存到一个集合中,在每次调用isValid()之前,我会检查是否已经尝试过该ID,如果没有,则调用isValid(),否则,ID将增加一个。在
坏的ID文件就是这样-
513025328
513025317
513025327
513025316
513025326
513025312
513025320
513025330
513025319
513025329
513025318
513025328
513025317
513025327
513025313
513025321
513025331
513025320
513025330
513025319
513025329
513025318
513025328
513025314
513025322
513025332
513025321
513025331
513025320
513025330
513025319
513025329
513025315
513025323
513025333
513025322
513025332
513025321
513025331
513025320
513025330
513025316
513025324
513025334
513025323
513025333
513025322
513025332
513025321
513025331
513025317
513025325
513025335
513025324
513025334
513025323
513025333
513025322
513025332
513025318
513025326
513025336
513025325
513025335
513025324
513025334
513025323
513025333
513025319
513025327
513025337
513025326
513025336
513025325
513025335
513025324
513025334
513025320
513025328
513025338
513025327
513025337
513025326
513025336
513025325
513025335
513025321
513025329
513025339
513025328
513025338
513025327
513025337
513025326
513025336
513025322
513025330
513025340
513025329
513025339
513025328
513025338
513025327
513025337
513025323
513025331
513025341
513025330
513025340
513025329
513025339
513025328
513025338
513025324
513025332
513025342
513025331
513025341
513025330
513025340
513025329
513025339
513025325
513025333
513025343
513025332
513025342
513025331
513025341
513025330
513025340
513025326
513025334
513025344
513025333
513025343
513025332
513025342
513025331
513025341
513025327
513025335
513025345
513025334
513025344
513025333
513025343
513025332
513025342
513025328
513025336
513025346
513025335
513025345
513025334
513025344
513025333
513025343
513025329
513025337
513025347
513025336
513025346
513025335
513025345
513025334
513025344
513025330
513025338
513025348
513025337
513025347
513025336
513025346
513025335
513025345
513025331
513025339
513025349
513025338
513025348
513025337
513025347
513025336
513025346
513025332
513025340
513025350
513025339
513025349
513025338
513025348
513025337
513025347
513025333
513025341
513025351
513025340
513025350
513025339
513025349
513025338
513025348
513025334
513025342
513025352
513025341
513025351
513025340
513025350
513025339
513025349
513025335
513025343
513025353
513025342
513025352
513025341
513025351
513025340
513025350
513025336
513025344
513025354
513025343
513025353
513025342
513025352
513025341
513025351
513025337
513025345
513025355
513025344
513025354
513025343
513025353
513025342
513025352
513025338
513025346
513025356
513025345
513025355
513025344
513025354
513025343
513025353
513025339
513025347
513025357
513025346
513025356
513025345
513025355
513025344
513025354
513025340
513025348
513025358
513025347
513025357
513025346
513025356
513025345
513025355
513025341
513025349
513025359
513025348
513025358
513025347
513025357
513025346
513025356
513025342
513025350
513025360
513025349
513025359
513025348
513025358
513025347
513025357
513025343
513025351
513025361
513025350
513025360
513025349
513025359
513025348
513025358
513025344
513025352
513025362
513025351
513025361
513025350
513025360
513025349
513025359
513025345
513025353
513025363
513025352
513025362
513025351
513025361
513025350
513025360
513025346
513025354
513025364
513025353
513025363
513025352
513025362
513025351
513025361
513025347
513025355
513025365
513025354
513025364
513025353
513025363
513025352
513025362
513025348
513025356
513025366
513025355
513025365
513025354
513025364
513025353
513025363
513025349
513025357
513025367
513025356
513025366
513025355
513025365
513025354
513025364
513025350
513025358
513025368
513025357
513025367
513025356
513025366
513025355
513025365
513025351
513025359
513025369
513025358
513025368
513025357
513025367
513025356
513025366
513025352
513025360
513025370
513025359
513025369
513025358
513025368
513025357
513025367
513025353
513025361
513025371
513025360
513025370
513025359
513025369
513025358
513025368
513025354
513025362
513025372
513025361
513025371
513025360
513025370
513025359
513025369
513025355
513025363
513025373
513025362
513025372
513025361
513025371
513025360
513025370
513025356
513025364
513025374
513025363
513025373
513025362
513025372
513025361
513025371
513025357
513025365
513025375
513025364
513025374
513025363
513025373
513025362
513025372
513025358
513025366
513025376
513025365
513025375
513025364
513025374
513025363
513025373
513025359
513025367
513025377
513025366
513025376
513025365
513025375
513025364
513025374
513025360
513025368
513025378
513025367
513025377
513025366
513025376
513025365
513025375
513025361
513025369
513025379
513025368
513025378
513025367
513025377
513025366
513025376
513025362
513025370
513025380
513025369
513025379
513025368
513025378
513025367
513025377
513025363
513025371
513025381
513025370
513025380
513025369
513025379
513025368
513025378
513025364
513025372
513025382
513025371
513025381
513025370
513025380
513025369
513025379
513025365
513025373
513025383
513025372
513025382
513025371
513025381
513025370
513025380
513025366
513025374
513025384
513025373
513025383
513025372
513025382
513025371
513025381
513025367
513025375
513025385
513025374
513025384
513025373
513025383
513025372
513025382
513025368
513025376
513025386
513025375
513025385
513025374
513025384
513025373
513025383
513025369
513025377
513025387
513025376
513025386
513025375
513025385
513025374
513025384
513025370
513025378
513025388
513025377
513025387
513025376
513025386
513025375
513025385
513025371
513025379
513025389
513025378
513025388
513025377
513025387
513025376
513025386
513025372
513025380
513025390
513025379
513025389
513025378
513025388
513025377
513025387
513025373
513025381
513025391
513025380
513025390
513025379
正如你所看到的,它不起作用,我知道我在整个设计中有一个缺陷,但我找不到它,我真的很感谢你的帮助。在
问题摘要-
我有一个diff list[8,18,7,17,6,16,5,15]程序从获取一个id开始,每次我需要检查下一个id是-id+diff[I](I=0) 如果(id+diff[i])不是有效的id,我将检查下一个id,即(id+diff[i+1])。在
如果在那个迭代(id+diff[i..n])上没有有效的id,我将将id增加1,并检查id+1是否是有效的id,如果不是,我将使用id+diff[i..n]再次检查,直到找到下一个有效的id
在每一次迭代中,我都要检查在上一次迭代中已经检查过的ID(这需要花费大量的时间并且效率低下),我需要避免检查已经检查过的ID,并不断增加ID,直到找到下一个有效的ID为止
现在,如果id=1(并且它是一个有效的id)并且diff=[8,18,7,17,6,16,5,15]。在
第一次迭代看起来像(我用粗体标记id,我可以避免检查)- 第一个-id=1
9,19,8,18,7,17,6,16,2
秒-id=2
10,20,9,19,8,18,7,17,3
第三个-id=3
11,21,10,20,9,19,8,18,4
第四个-id=4
12,22-没错,下一个有效ID是22!
这花费了我29个请求,而不是-17个,这是一个小例子,我的范围是从最后一个有效id到300-600个id
我拿不到我的代码,以避免检查以前检查过的ID和一个智能和有效的方式。在
谢谢!在
首先,你应该把工作分成两个过程。一个用于确定有效的id,另一个用于检索数据。在
确定有效id的程序只需要使用httphead命令,并且比检索页面的程序工作得更快。在
对于检查页面,在检查
diff
中的id增量之后,再将18添加到导致您开始使用diff
的id中。您甚至可以使用diff
记录只部分检查过的范围,然后在进程结束时返回,并检查所有这些范围。在如果不能跳过任何id,那么保存最近检查的n个id的缓存,其中n等于len(diff)。使用类似这样的环形缓冲器:
。。。在
从表面上看,这样一个简单的循环应该检查所有ID:
^{pr2}$这将检查所有可能的页面。但当你被击中时,你要提前阅读,如果我理解正确的话,也要部分回溯。在任何情况下,您所要做的基本工作是从xrange返回的简单序列中更改id的范围,因此我认为您需要编写一个生成器并执行以下操作:
你可能仍然想使用一个环形缓冲区,这取决于你在18个可能的额外点击范围内做了什么。如果您需要检查
diff
中的所有可能性,然后返回到diff中小于maximum元素的值,那么在checkpage中使用环形缓冲区是很有用的。在但诀窍是编写myrange()。在
这三个全局变量允许您影响id的范围。如果您在
checkpage()
内设置hitfound = True
,那么您将影响myrange开始应用diff
中的增量。然后,您可以设置nextnum
来影响它在开始应用diff增量后开始递增的位置。例如,在检查diff增量时,您可能决定将其设置为比第一次(或最后一次)命中大1。或者您可以不使用它,使用环缓冲区来确保不再请求任何diff增量页。在我建议您提取id递增逻辑,并像上面的代码一样单独测试它。调整生成器
myrange()
直到它产生正确的序列,然后将其弹出到您的web抓取程序中。在我想我明白了。在
首先,基于您的想法的代码:
结果
^{pr2}$一。在
以下是基于我想法的代码:
结果
有
在这段代码中,但是消息“already seen”在执行过程中从不打印;但是,valids ID的检测有相同的结果;这意味着在我的代码中不需要使用set seen。在
一。在
编辑1
代码#1与指令定期清空SEEN
结果
上面的代码显示了记录和清空已经看到的ID值的过程。这是一个很好的代码,因为该算法包括定期清空SEEN,因为在给定要测试的id数量的情况下,清空是必要的。在
但从一开始,我的观点是,在这个算法中,与SEEN有关的记录和测试指令在程序的每一步都会重复执行,这对性能有很大的影响。在
这就是为什么我认为应该有另一个算法没有这个缺点。我终于成功地写了这样一个替代代码,现在我们有两个代码,有两个不同的算法。在
关于你的问题,“你确定没有必要在第二个问题中使用所见的逻辑吗?”
我回答‘是的,我想我可以肯定’。用指令管理SEEN来运行我的代码#2的目的是在验证了什么是一个思想概念和一个概念算法之后,让我确定。如果你想确定,你必须这样做: -从概念上和精确地研究算法 -尽可能多地写两个代码的执行过程,并比较它们的结果,只要你需要实验证明,改变lastResult,valid_one和diff的值 对我来说,只要没有矛盾的实际案例证明我的结论是错误的,这一点就结束了。在
我继续另一个答案,因为这个答案中的字符数是有限的
当一个标识符在执行修改的函数之外时,如果想要引起对它的修改,那么就可以将它声明为
global
。在因此,使最后结果和当前
global
是一种畸变:第一个,lastResult,因为它是完整代码中的常量。最好的方法是定义函数checkNextID()的参数lastResult,默认参数为lastResult。
第二个,出现在中,因为在checkNextID()中没有关于该标识符的修改
现在,将curRes定义为函数isValid()中的
global
也是一个错误的做法:1)将isValid()的新值从isValid()的内部发送到外部;2)然后,程序在函数checkNextID()之外搜索curRes的值。这是一个奇怪而无用的迂回路线,你可以让curRes成为函数checkNextID()中的一个自由变量(参见doc),这个函数会自动走出去解析这个名称并获得它的值。在一。在
就个人而言,我更喜欢重组通用算法。在下面的代码中,curRes被定义为一个局部对象,直接从函数isValid()的返回中获取其值。这需要重新定义isValid():在我的代码中,isValid()返回对象soup或False
我希望我能理解你的需要。请告诉我我的方法有什么问题。在
一。在
此外,要加快您的计划:
您应该使用regex工具(modulere)而不是BeautifulSoup,后者大约比使用regex慢10倍左右
您不应该在checkNextID中定义和使用所有这些函数(saveToCSV,parseHTML,isValid):与直接代码相比,每次调用函数都需要额外的时间
一。在
最终编辑
为了结束对你问题的长期研究,我做了一个基准测试。下面的代码和结果表明我的直觉是正确的:我的代码2比你的代码1运行时间至少少20% . 您的代码#1:
^{pr2}$我的代码2
结果:
0.268061164198/0.398804596674=67.3%
我也尝试过lastResult=100,得到72%。
当lastResult=480时,我得到了80%。在
相关问题 更多 >
编程相关推荐