Если вы задаёте `post` опцию, то писать `method=«post»` уже не обязательно, он таким будет автоматически. Да и disable_cache не нужно, post запросы не кэшируются:
Я уже ничо не соображаю. Сейчас спать пойду. Но могу сказать, чего есть в Task объектах: можно передавать сколько угодно именованных параметров и они потом будут доступны как аттрибуты task объекта, который передаётся в обработчик третьим параметром. Наверное это аналог meta из scrapy.
Гыгы, без понятия :) Можно сделать два спайдера и запускать второй после того как первый скачал все картинки. Ну или можно как-то извращаться и в task_images и определять что это последняя картинка и запускать нужный обработчик. Да, не помешала бы какая-то встроенная фича для такой задачи (генерация сигнала после обработки помеченных тасков), но пока ничего такого нет.
distributed mode — это мои эксперименты с выполнением task-обработчиков на нескольких ядрах процессора с помощью multiprocessing, но это всё нереально сырое, лучше эту опцию пока не трогать.
Ага, интересная идея. У меня там кстати щас есть хэндлер на SIGUSR1 — пишется статистика счётчиков в /tmp/spider.log или куда-то туда… Топорно конечно, но вот как бы думаю в этом направлении.
О, любитель ковычек, вы забыли слово лучше в кавычки заключить :)
Я использовал BeatifulSoup до тех пор, пока не созрел до lxml. Это библиотека написанная на C. Она полностью поддерживает поиск через xpath-выражения, а также понимает битый html. Grab использует lxml для парсинга, но вообще ничего не мешает вам в том же Grab:Spider работать с BeautifulSoup.
Плюсы BeautifulSoup:
* pure python
* умещается в одном файле
* допускаю, что новичку проще вникнуть в работу с BS, чем с lxml
Минусы BeautifulSoup
* отвратительно медленный
* возможно жрёт память, мне щас лень писать тесты для памяти
* меня лично напрягает писать два длинных camel case имени в строке импорта: «from BeautifulSoup import BeautifulSoup»
Для скорости мне тесты писать не лень. Запустите у себя на компьютере и ужаснитесь:
from lxml.html import fromstring
from BeautifulSoup import BeautifulSoup
import time
import urllib
data = urllib.urlopen('http://habrahabr.ru').read()
start = time.time()
for x in xrange(10):
tree = BeautifulSoup(data)
print tree.find('title').text
print 'BeautifulSoup: %.2f' % (time.time() - start)
start = time.time()
for x in xrange(10):
tree = fromstring(data)
print tree.xpath('//title')[0].text
print 'lxml: %.2f' % (time.time() - start)
Если вы ещё не используете lxml для парсинга, то мне вас жаль :)
Можно в принципе добависть фичку, чтобы вызывался callback какой-нить настраиваемый в таком случае. Можно будет в этом callback взять и опять запихать задание в очередь, чтобы ещё раз повторить цикл попыток.
> Потом в случае чего выдаю ошибку. Промежуточные структуры данных сохраняю в сериализованном виде на диск, чтобы потом если что можно было перезапуститься с ключиком --continue
Я обычно настраиваю парсер так, чтобы он работал без ошибок и потом запускаю главный парсинг.
Я сейчас эксперементирую с кэшем. Записываю в монго скачанные документы. Это поведение можно так включить: bot = SomeSpider(use_cache=True, cache_db='some-db-name') Кэшируются только GET-запросы. Столкнулся с проблемой, что не влезает всё на винчестер, ну нету у меня винчестера на 2 терабайта. Тогда я придумал на лету применять gzip-компрессию. Включается опцией use_cache_compression=True. Документы сжимаются в 10 раз — это очень круто. Но нужно время CPU на компрессию-декомпрессию — это не круто :( Я пытался через multiprocessing организовать обработку на множестве ядер, вроде как есть ускорение в два раза на 4-ядерном атлоне. Но это пока нихрена не оттестировано даже на эмпирическом уровне. Короче пока работа с кэшем довольно медленная, я вообще пока плохо понимаю что делаю — все эти асинхронности и mongodb — новые для меня области :) Как минимум, работа с кешем очень упрощает отладку парсера на начальном этапе.
Я объясню. Мне нужно было пробежаться по всем этим элементам, не просто достать первый такой элемент, а перебрать их все и у каждого взять несколько свойств. Если вы попробуете это сделать через lxml/xpath, то никаких тормозов не будет, а scrapy делает что-то больно хитрое, такое хитрое, что оно в 200 раз медленнее работает. Судя по всему он каждую ноду из результата заворачивает в какой-то свой класс — это и даёт феерическое замедление.
Там я немного про другую вещь писал, про Grab — это синхронный API к pycurl. А это статья про асинхронный spider, который как раз и является аналогом scrapy — решает абсолютно те же задачи.
Потому что я всегда любил велосипеды. Было интересно попробовать свой собственный асинхронный велосипед. Кроме всего прочего скрапи меня немного пугает свою монструозностью. В моём же модуле spider всего 700 строчек, которые я сам писал. Месяц назад сознательно попытался написать один парсер на скрапи, но его багафича отбила всякое желание делать что-то дальше: groups.google.com/group/scrapy-users/browse_thread/thread/5092eb5cc8695f2a/aa36618c58c539ec Но это всё мелочи жизни. Просто у меня есть время и желание писать свои решения, — я их пишу. А ну и ещё — синхронный интерфейс Grab я уже пишу/использую много лет, поэтому хотелось как-то заюзать эти наработки. Очень здорово получилось, что получилось натянуть старый интерфейс Grab на асинхронность.
А ещё scrapy не поддерживает socks-прокси. Впрочем grab:spider — тоже, в debian stable устаревшая версия curl-библиотеки, в которой есть баг — multicurl не работает с socks. В более новых версиях curl этот баг пофиксили.
Проверяйте, что ip действительно меняется. Провярйте, что cookie-действительно не передаются (смотрите grab.request_headers) Вопросы по грабу лучше в майл-лист писать, ссылка в конце статьи дана.
Весь трафик кстати можно логировать как с обычным Grab.
bot = SomeSpider(...)
bot.setup_grab(log_dir='/path/to/dir')
//div/strong[contains(text(), «Google»)]
* bitbucket.org/lorien/grab/src/7000b67ff7ad/grab/spider/base.py#cl-409
* bitbucket.org/lorien/grab/src/7000b67ff7ad/grab/spider/base.py#cl-519
Я использовал BeatifulSoup до тех пор, пока не созрел до lxml. Это библиотека написанная на C. Она полностью поддерживает поиск через xpath-выражения, а также понимает битый html. Grab использует lxml для парсинга, но вообще ничего не мешает вам в том же Grab:Spider работать с BeautifulSoup.
Плюсы BeautifulSoup:
* pure python
* умещается в одном файле
* допускаю, что новичку проще вникнуть в работу с BS, чем с lxml
Минусы BeautifulSoup
* отвратительно медленный
* возможно жрёт память, мне щас лень писать тесты для памяти
* меня лично напрягает писать два длинных camel case имени в строке импорта: «from BeautifulSoup import BeautifulSoup»
Для скорости мне тесты писать не лень. Запустите у себя на компьютере и ужаснитесь:
Если вы ещё не используете lxml для парсинга, то мне вас жаль :)
* bitbucket.org/lorien/grab/src/7000b67ff7ad/grab/spider/base.py#cl-520
Количество попыток можно настраивать. Когда количество попыток для задания истекает, то просто логируется ошибка:
* bitbucket.org/lorien/grab/src/7000b67ff7ad/grab/spider/base.py#cl-395
Можно в принципе добависть фичку, чтобы вызывался callback какой-нить настраиваемый в таком случае. Можно будет в этом callback взять и опять запихать задание в очередь, чтобы ещё раз повторить цикл попыток.
> Потом в случае чего выдаю ошибку. Промежуточные структуры данных сохраняю в сериализованном виде на диск, чтобы потом если что можно было перезапуститься с ключиком --continue
Я обычно настраиваю парсер так, чтобы он работал без ошибок и потом запускаю главный парсинг.
Я сейчас эксперементирую с кэшем. Записываю в монго скачанные документы. Это поведение можно так включить: bot = SomeSpider(use_cache=True, cache_db='some-db-name') Кэшируются только GET-запросы. Столкнулся с проблемой, что не влезает всё на винчестер, ну нету у меня винчестера на 2 терабайта. Тогда я придумал на лету применять gzip-компрессию. Включается опцией use_cache_compression=True. Документы сжимаются в 10 раз — это очень круто. Но нужно время CPU на компрессию-декомпрессию — это не круто :( Я пытался через multiprocessing организовать обработку на множестве ядер, вроде как есть ускорение в два раза на 4-ядерном атлоне. Но это пока нихрена не оттестировано даже на эмпирическом уровне. Короче пока работа с кэшем довольно медленная, я вообще пока плохо понимаю что делаю — все эти асинхронности и mongodb — новые для меня области :) Как минимум, работа с кешем очень упрощает отладку парсера на начальном этапе.
Конец brain dump'а :)
А ещё scrapy не поддерживает socks-прокси. Впрочем grab:spider — тоже, в debian stable устаревшая версия curl-библиотеки, в которой есть баг — multicurl не работает с socks. В более новых версиях curl этот баг пофиксили.
>>> int((549784 / 98.75) * 1.25 — (2 + 1 + 4 + 12))
6940
Что это значит?