2016-07-06 55 views
0

我试图从数千页的页面中抓取数据。我的代码工作正常约100页,但后来显着减慢。我很确定我的Tarzan-like代码可以改进,这样网页捕获过程的速度就会提高。任何帮助,将不胜感激。 TIA!优化此Python代码 - 网页扫描并将结果输出到CSV文件

下面是简化的代码:

csvfile=open('test.csv', 'w', encoding='cp850', errors='replace') 
writer=csv.writer(csvfile) 

list_url= ["http://www.randomsite.com"] 
i=1 

for url in list_url: 
base_url_parts = urllib.parse.urlparse(url) 
while True: 
    raw_html = urllib.request.urlopen(url).read() 
    soup = BeautifulSoup(raw_html, "lxml") 

    #### scrape the page for the desired info 

    i=i+1 
    n=str(i) 

    #Zip the data 
    output_data=zip(variable_1, variable_2, variable_3, ..., variable_10) 

#Write the observations to the CSV file 
    writer=csv.writer(open('test.csv','a',newline='', encoding='cp850', errors='replace')) 
    writer.writerows(output_data) 
    csvfile.flush() 

    base="http://www.randomsite.com/page" 
    base2=base+n 
    url_part2="/otherstuff" 
    url_test = base2+url_part2 

    try: 
     if url_test != None: 
      url = url_test 
      print(url) 
     else: 
      break 
    except: 
     break 

csvfile.close() 

编辑:感谢所有的答案,我学到了很多,从他们。我(慢慢地)学习了Scrapy的方式。但是,我发现这些页面可以通过批量下载获得,这将是解决性能问题的更好方法。

+1

如果你的代码有效,但可以使用一些imprvement,代码审查论坛是地方。 [HTTP://codereview.stackexchange。com/questions/tagged/python] –

+0

啊,好的,我不知道这个资源。谢谢,我会在那里发帖。 –

回答

0

主要的瓶颈是你的代码是同步的(阻塞)。直到完成当前的处理,您才会继续到下一个URL。

您需要通过切换到Scrapy来异步创建,这可以立即解决此问题,也可以通过自行构建某些内容(例如grequests)来完成。

+0

感谢您指出scrapy;从我所看到的看来,它似乎非常有前途(对于未批量下载的未来项目)。 –

0

如果您想要在没有太多复杂代码的情况下实现非常快的速度,您需要:A)分离来自解析的请求(因为解析阻塞了您用来发出请求的线程),而B )同时发出请求并同时解析它们。所以,我会做几件事情:

  1. 使用eventlets异步请求所有页面。我一直在Python中使用异步http框架,并且发现最容易学习的eventlet。
  2. 每当您成功获取页面时,都将html存储在某处。 A)你可以把它写到本地的html文件中,但你手上会有很多文件。 B)你可以将这些很多记录存储为字符串(str(source_code)),只要它被哈希(可能是一个集或字典),就把它们放在一个本地数据存储中。 C)你可以使用超级轻量级​​但不是特别高性能的数据库,如TinyDB,并将页面源代码粘贴到JSON文件中。 D)您可以使用第三方库的数据结构进行高性能计算,例如Pandas DataFrame或NumPy数组。他们可以很容易地存储这么多的数据,但可能会矫枉过正。
  3. 检索后分别解析每个文档。使用lxml进行解析将会非常快速,所以根据您需要的速度,您可能能够按顺序解析文件。如果你想加快速度,请在python中查找关于多处理的教程。这很容易学习,并且您可以同时解析X文档,其中X是计算机上可用内核的数量。
+0

谢谢。如果时间允许,我一定会回到你的建议。 –

0

也许这只是简化中的一个错误,但看起来好像多次打开'test.csv',但是只关闭一次。当URL的数量超过100时,不确定这是导致意外减速的原因,但是如果您希望所有数据都放在一个CSV文件中,您应该坚持在顶部打开文件和作者一次,就像您已经在做,而不是在循环内部进行。

另外,在构建新URL的逻辑中:是不是url_test != None总是正确的?那你怎么退出循环?当例外urlopen失败?那么你应该尝试一下,除此之外。这不是一个性能问题,但任何清晰度都有帮助。