Dryscrape / webkit_server内存泄漏

时间:2016-03-29 09:32:42

标签: python html web-scraping

我正在使用dryscrape / webkit_server来抓取启用javascript的网站。

每次调用session.visit()时,进程webkit_server的内存使用量似乎都会增加。我碰巧使用以下脚本:

import dryscrape

for url in urls: 
    session = dryscrape.Session()
    session.set_timeout(10)
    session.set_attribute('auto_load_images', False)
    session.visit(url)
    response = session.body()

我正在迭代约。 300 urls和70-80 urls之后webkit_server占用大约3GB的内存。然而,对我来说这不是真正的内存问题,但似乎dryscrape / webkit_server在每次迭代时都变得越来越慢。在上述70-80次迭代之后,dryscrape速度很慢,导致超时错误(设置超时= 10秒),我需要中止python脚本。重新启动webkit_server(例如,每30次迭代后)可能会有所帮助并且会清空内存,但是我不确定“内存泄漏”是否真的导致干刮越来越慢。

有谁知道如何重新启动webkit_server以便我可以测试它?

我没有为这个问题找到一个可接受的解决方法,但是我也不想切换到另一个解决方案(selenium / phantomjs,ghost.py),因为我简单地喜欢dryscrape。 Dryscrape正在努力工作。如果一个人没有在一个会话中迭代过多的网址。

此问题也在这里讨论

https://github.com/niklasb/dryscrape/issues/41

在这里

Webkit_server (called from python's dryscrape) uses more and more memory with each page visited. How do I reduce the memory used?

5 个答案:

答案 0 :(得分:5)

你所遇到的内存泄漏也可能与webkit_process从未被实际杀死的事实有关(并且你每次迭代都会产生一个新的dryscrape.Session,它会在后台产生一个webkit_server进程)永远不会被杀死)。因此,每次重新启动时,它都会继续生成一个新进程。 @Kenneth的答案可能有效但任何需要调用命令行的解决方案都是粗略的。一个更好的解决方案是在开始时声明一次会话并在最后从python中取消webkit_server进程:

import webkit_server
import dryscrape

server = webkit_server.Server()
server_conn = webkit_server.ServerConnection(server=server)
driver = dryscrape.driver.webkit.Driver(connection=server_conn)
sess = dryscrape.Session(driver=driver)
# set session settings as needed here

for url in urls:
    sess.visit(url)
    response = session.body()
    sess.reset()

server.kill() # the crucial line!

坦率地说,这是dryscrape库中的一个缺点。 kill命令应该可以从dryscrape Session访问。

答案 1 :(得分:3)

您好,

很抱歉挖掘这个旧帖子,但我解决问题的方法(谷歌搜索后只发现这篇文章)是在一个单独的过程中运行dryscrape,然后在每次运行后杀死Xvfb。

所以我的dryscrape脚本是:

dryscrape.start_xvfb()
session = dryscrape.Session()
session.set_attribute('auto_load_images', False)
session.visit(sys.argv[1])
print session.body().encode('utf-8')

并运行它:

p = subprocess.Popen(["python", "dryscrape.py", url],
                     stdout=subprocess.PIPE)
result = p.stdout.read()
print "Killing all Xvfb"
os.system("sudo killall Xvfb")

我知道这不是最好的方法,内存泄漏应该修复,但是这样可行。

答案 2 :(得分:3)

我遇到了与内存泄漏相同的问题。通过在每次页面查看后重置会话来解决它!

简化的工作流程看起来像这样。

设置服务器:

dryscrape.start_xvfb()
sess = dryscrape.Session()

然后遍历Url并在每个网址后重置会话

for url in urls:
    sess.set_header('user-agent', 'Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36')
    sess.set_attribute('auto_load_images', False)
    sess.set_timeout(30)
    sess.visit(url)
    response = sess.body()
    sess.reset()

<强>更新

我仍然遇到内存泄漏的问题,而@nico提供的答案更好。

我最终放弃了dryscrape,现在一直在使用Selenium和PhantomJS。仍有内存泄漏,但它们是可管理的。

答案 3 :(得分:0)

制作2个这样的脚本

call.py

import os
#read urls.txt make a list
urls = open('urls.txt').read().split('\n')
for url in urls:
  print(url)
  os.system("./recive_details.py %s" % url)

recive_details.py

import sys
url = sys.argv[1]
import dryscrape as d
d.start_xvfb()
br = d.Session()
br.visit(url)
#do something here
#print title
print br.xpath("//title")[0].text()

运行Always call.py就像这个“ python call.py”一样,它将自动执行第二个脚本并立即终止会话。我尝试了许多其他方法,但是这种方法像魔术一样对我有效,请尝试一次

注意 Haroon Amjad : The Python Expert

答案 4 :(得分:0)

省略 session.set_attribute('auto_load_images', False) 为我解决了问题,如 here 所述。好像没有加载图片时内存泄漏。