Я пытаюсь зеркально отразить сайт на контенте, к сожалению, большая его часть основана на javascript, включая код, который генерирует hrefs.Это уничтожает большинство стандартных инструментов для очистки веб-страниц (таких как httrack), поскольку их попытки обработки javascript, даже если они и пытаются это сделать, крайне ненадежны.
Поэтому я решил написать свой собственный на python и получить движок webkitобрабатывать HTML.Процедурная логика кажется довольно простой: генерируйте dict с URL-адресами, найденными в качестве ключа, и значением, равным 0 или 1, в зависимости от того, было ли оно уже обработано.Мне удалось заставить базовую логику работать достаточно хорошо с pyqt4, но она продолжала работать с ошибками в случайное время, достаточно, чтобы заставить меня не доверять ей, и затем я нашел это: http://blog.motane.lu/2009/06/18/pywebkitgtk-execute-javascript-from-python/
Аккуратный скрипт, он работает, ноЯ никогда раньше не имел дело с gtk в python.Разобраться в моей логике было довольно просто, однако оказалось, что это что-то вроде памяти.Профилирование с помощью meliae показывает, что ничто не занимает столько памяти, даже когда python достигает 2 Гб.На сайте довольно много страниц, и сценарий в конечном итоге достигает 32-битного лимита памяти и сегментов.Я предполагаю, что код порождает все больше и больше окон WebKit.Я в недоумении, как заставить его закрыть или уничтожить эти окна.Я пытался уничтожить, там есть main_quit, кажется, ничто его не закрывает.
Вот то, что должно быть соответствующими частями (я надеюсь), но с измененным URL назначения.Я использовал dicts для 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()