2016-03-29 2 views
3

Я использую dryscrape/webkit_server для очистки веб-сайтов с поддержкой javascript.Утечка памяти Dryscrape/webkit_server

Использование памяти процесса webkit_server увеличивается с каждым вызовом session.visit(). Это происходит со мной, используя следующий сценарий:

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 URL-адресов и после 70-80 URL-адресов webkit_server занимает около 3 ГБ памяти. Однако на самом деле это не проблема для меня, но кажется, что dryscrape/webkit_server становится все медленнее с каждой итерацией. После упомянутых 70-80 итераций dryscrape так медленно, что он вызывает ошибку таймаута (установить тайм-аут = 10 секунд), и мне нужно прервать скрипт python. Перезапуск webkit_server (например, после каждых 30 итераций) может помочь и освободит память, однако я не уверен, что «утечка памяти» действительно ответственна за сухую царапину, которая замедляется и замедляется.

Кто-нибудь знает, как перезапустить webkit_server, чтобы я мог проверить это?

Я не нашел приемлемого обходного пути для этой проблемы, однако я также не хочу переключаться на другое решение (selenium/phantomjs, ghost.py), поскольку я просто люблю dryscrape для его простоты. Dryscrape работает отлично. если вы не повторяете слишком много URL-адресов за один сеанс.

Этот вопрос также обсуждается здесь

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?

+0

до тех пор, пока у dryscrape есть код python, вы можете бросить декораторы '@ profile' и запустить [mprof] (https://pypi.python.org/pypi/memory_profiler/0.33) или [kernprof] (https://github.com/rkern/line_profiler). Вы можете запустить его по своему собственному коду, но, вероятно, это будет не так полезно. –

+0

Спасибо, Уэйн! – Baili

ответ

3

У меня была такая же проблема с утечкой памяти. Решил его, сбросив сеанс после каждого просмотра страницы!

Упрощенный рабочий процесс будет выглядеть следующим образом.

Настройка сервера:

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

Затем перебираем URL, и сброс сессии после каждого 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() 

Update

я до сих пор встречаются проблемы с утечкой памяти и лучше ответ - тот, который предоставлен @nico.

Я закончил тем, что оставил сухую резинову вместе и теперь использовал Selenium и PhantomJS. Есть еще утечки памяти, но они управляемы.

2

Привет,

К сожалению для выкапывания этого старого поста, но что я сделал, чтобы решить проблема (после поиска в Интернете и только нахождение этого сообщения) заключалась в том, чтобы запустить 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") 

Я знаю, что это не самый лучший способ, и утечка памяти должна быть исправлена, но это работает.

+1

В идеале, dryscrape должен был предоставить что-то вроде dryscape.stop_xvfb(), но даже без него, ваше решение, похоже, в порядке. Я собираюсь попробовать и посмотреть, работает ли это для моего использования! –

5

Утечка памяти, которую вы имеете, также может быть связана с тем фактом, что webkit_process никогда фактически не убит (и что вы создаете новую сухую чипсет.Сессия каждой итерации, которая порождает процесс webkit_server в фоновом режиме, который никогда не получает убит). Таким образом, он будет просто создавать новый процесс каждый раз, когда он перезагружается. Ответ @Kenneth может работать, но любое решение, требующее вызова командной строки, является отрывочным. Лучшее решение было бы объявить сессию один раз в начале и убить процесс 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 должна быть доступна из сеанса сушки.

+3

Это должен быть принятый ответ. Спасибо чувак – eusid

Смежные вопросы