2011-08-11 50 views
2

我想镜像一个网站的内容,不幸的是它的大块是基于JavaScript的,包括生成hrefs的代码。这消除了大多数标准的网页抓取工具(如httrack),因为他们尝试处理JavaScript,如果他们甚至尝试这样做,都非常不可靠。Python,GTK,Webkit和刮,大内存问题

所以我决定写我自己的python并获得webkit引擎来处理HTML。程序逻辑看起来非常直截了当,根据它是否已被处理,生成一个带有作为键发现的URL的字典,值为0或1。我设法使pyqt4的基本逻辑能够很好地工作,但它在随机时间继续进行分段,足以让我不信任它,然后我发现这一点:然后我发现这个:http://blog.motane.lu/2009/06/18/pywebkitgtk-execute-javascript-from-python/

整洁的脚本,它的工作,但我从来没有之前在python中处理过gtk。然而,我的逻辑围绕它的逻辑是相当直接的,然而它的证明是一个记忆猪。用meliae进行分析显示,即使蟒蛇达到2Gb,也没有任何内容占用太多内存。该网站有几页,并且脚本最终达到32位内存限制和段错误。我的假设是代码生成越来越多的webkit窗口。我不知道如何才能真正关闭或销毁这些窗口。我试过摧毁,那里有一个main_quit,没有任何东西似乎在关闭它。

这是什么应该是相关的部分(我希望),但目标网址更改。我正在使用url和foundurl的字典,但切换到anydbm的情况下,他们是为了一些奇怪的原因内存猪。我可能会在某个时候切换回类型的字典:

#!/usr/bin/env python 
import sys, thread 
import gtk 
import webkit 
import warnings 
from time import sleep 
from BeautifulSoup import BeautifulSoup 
import re 
import os 
import anydbm 
import copy 
from meliae import scanner 

warnings.filterwarnings('ignore') 

class WebView(webkit.WebView): 
    def get_html(self): 
     self.execute_script('oldtitle=document.title;document.title=document.documentElement.innerHTML;') 
     html = self.get_main_frame().get_title() 
     self.execute_script('document.title=oldtitle;') 
     self.destroy 
     return html 

class Crawler(gtk.Window): 
    def __init__(self, url, file): 
     gtk.gdk.threads_init() # suggested by Nicholas Herriot for Ubuntu Koala 
     gtk.Window.__init__(self) 
     self._url = url 
     self._file = file 
     self.connect("destroy",gtk.main_quit) 

    def crawl(self): 
     view = WebView() 
     view.open(self._url) 
     view.connect('load-finished', self._finished_loading) 
     self.add(view) 
     gtk.main() 
     return view.get_html() 

    def _finished_loading(self, view, frame): 
     with open(self._file, 'w') as f: 
      f.write(view.get_html()) 
     gtk.main_quit() 

..Various子程序,只是处理事情的BeautifulSoup结束,处理页面,拔出链接,整理起来等等

def main(): 
    urls=anydbm.open('./urls','n') 
    domain = "stackoverflow.com" 
    baseUrl = 'http://'+domain 
    urls['/']='0' 
    while (check_done(urls) == 0): 
     count = 0 
     foundurls=anydbm.open('./foundurls','n') 
     for url, done in urls.iteritems(): 
      if done == 1: continue 
      print "Processing",url 
      urls[str(url)] = '1' 
      if (re.search(".*\/$",url)): 
       outfile=domain+url+"index.html" 
      elif (os.path.isdir(os.path.dirname(os.path.abspath(outfile)))): 
       outfile=domain+url+"index.html" 
      else: 
       outfile=domain+url 
      if not os.path.exists(os.path.dirname(os.path.abspath(outfile))): 
       os.makedirs(os.path.dirname(os.path.abspath(outfile))) 
      crawler = Crawler(baseUrl+url, outfile) 
      html=crawler.crawl() 
      soup = BeautifulSoup(html.__str__()) 
      for link in hrefs(soup,baseUrl): 
       if not foundurls.has_key(str(link)): 
        foundurls[str(link)] = '0' 
      del(html) # this is an attempt to get the object to vanish, tried del(Crawler) to no avail 
      if count==5: 
       scanner.dump_all_objects('filename') 
       count = 0 
      else: 
       count=count+1 
     for url, done in foundurls.iteritems(): 
      if not urls.has_key(str(url)): 
       urls[str(url)]='0' 
     foundurls.close() 
     os.remove('./foundurls') 
    urls.close() 
    os.remove('./urls') 

if __name__ == '__main__': 
    main() 

回答

1

我没有实际使用过WebKit,但不应该将self.destroy改为self.destroy()?这可能会导致内存泄漏。

+0

真的..但不能解决问题不幸的是,它使python段错误。据推测,它正在从它下面杀掉webkit或gtk,它并不喜欢这么多! – Twirrim