我正在尝试镜像一个网站的内容,不幸的是它的大块是基于javascript的,包括生成hrefs的代码。这消除了大多数标准的网络抓取工具(如httrack),因为他们尝试处理javascript,如果他们甚至尝试过它,则非常不可靠。
所以我决定在python中编写自己的代码并获取webkit引擎来处理HTML。程序逻辑似乎非常简单,生成一个dict,其中url被发现为键,值为0或1,具体取决于它是否已被处理。我设法让基本逻辑与pyqt4合理地工作,但它随机时间保持segfaulting,足以让我不信任它,然后我发现了这个:http://blog.motane.lu/2009/06/18/pywebkitgtk-execute-javascript-from-python/
整洁的脚本,它可以工作,但我以前从未在python中处理过gtk。尽管如此,我对它的理解仍然相当简单,但事实证明它有点像记忆。使用meliae进行分析显示没有占用太多内存,即使python达到2Gb。该网站有几个页面,脚本最终达到32位内存限制和段错误。我的假设是代码正在产生越来越多的webkit窗口。我不知道如何让它实际关闭或摧毁那些窗户。我试过破坏,那里有一个main_quit,似乎没有什么东西可以关闭它。
这是相关部分(我希望),但目的地网址已更改。我正在使用dicts for url和foundurl但是切换到anydbm以防万一他们出于某种奇怪的原因记忆。我可能会在某个时候切换回dicts:
#!/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()
..各种子程序只处理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()
答案 0 :(得分:1)
我实际上没有使用过WebKit,但是self.destroy
不应该更改为self.destroy()
?这可能会导致内存泄漏。