Как стать автором
Обновить

Комментарии 49

Ну вот, а я только сегодня реализовывал всё на BS и urllib2 =)
Даешь еще статей по питоновским/джанговским либам на Хабре!

Спасибо за пост =)
Какая штука классная, моим велосипедам очень стыдно теперь.
Что делать если js на странице возвращает контент?
Наследуете паука от BaseSpider и пишете реквесты вручную
yield Request(url, callback=self.parse_page)
а веб-движок не проще прицепить?
НЛО прилетело и опубликовало эту надпись здесь
«офисный» ботнет решает :)
Есть, используем spynner. Тормоз, конечно, но работает.
Разбираешь что делает JS и реализуешь этот алгоритм в пауке. Вряд-ли там что-то сверхсложное будет.
Если там AJAX-запрос, возвращающий структурированные в JSON/XML/whatever данные — просто пишем Request на адрес хэндлера, входные параметры придётся упаковывать вручную, с результатом делаем что хотим. Если запрос возвращает кусок HTML, предназначенный для встраивания в разметку — можно использовать прямо XPathItemLoader (правда, если у этого куска несколько элементов верхнего уровня, придётся обернуть в фиктивный элемент, иначе парсер расстроится).
С частичными постбэками ASP.NET, возможно, будет сложнее.
списибо, было интересно почитать. раньше для этих целей ковырял mechanize и Beautiful Soup, хотел еще посмотреть lxml/leaf чтобы выбрать что будет удобней, но руки так и не дошли.
Так же для этих целей можно использовать nodejs. правда он работает под GNU Linux но если напильником поработать то и на винде запустится. Очень удобно пауков на нём писать! Большой плюс, то что он может превращать html код в DOM модель и работать с ним через jquery. Тоесть вытащить любую часть страницы не занимает много труда! Так же к нему написано много дополнений, с помощью них можно работать через прокси и сохранять сессии с куками! Вообщем советую глянуть и в этом направлении тоже! С удовольствием выслушаю конструктивную критику или поддержку!
А еше гвозди микроскопом забивать удобно.
Из конструктивной критики — насколько мне известно, NodeJS это больше все-таки для создания веб-приложений. А тут описывается готовый специальный очень мощный, работающий в продакшне фреймворк конкретно для скачивания страниц и их разбора.
Могли-бы хоть список библиотек дать с которыми можно так просто в NodeJS странички качать, обрабатывать, сохранять данные. Превращать html в DOM и выполнять xpath/CSS запросы все умеют. Куки и прокси Scrapy из коробки поддерживает.
NodeJS это в первую очередь надстройка надо V8, а уж что вы с ним будете делать это зависит от вашей фантазии и знания JS. Г-н kurokikaze несколько раз демонстрировал примеры своих «игр» с хабром и во всех случаях в качестве движка для пауков выступало что-то на базе nodeю

Лично мне понравилась связка: node-htmlparser + node-soupselect. Во всяком случае вменяемый парсинг аукционов с vworker.com, без regexp и прочих «не тру» методов (для интереса рекомендую взглянуть на исходный код их аукционов и проникнуться даже не индийским, а каким-то нечеловеческим кодом), удалось написать только на ней. Под питоном честно пытался сделать это с помощью BeautifulSoup, pyquery и недавно рекламировавшегося на хабре leaf. Все потерпели неудачу. Возможно, стоило написать собственную обертку над lxml, где учесть все недостатки целевого сайта, но мне показалось, что возни будет больше, чем просто написать под node.
Не, ну если знаете Node лучше, чем Twisted/Scrapy то пишите на нем. Хотя XPath запросы везде должны быть одинаковые, не вижу здесь проблемы)))
Просто Sсrapy это не «еще одна библиотека для ПАРСИНГА страничек». Это фреймворк для написания веб-пауков. В Scrapy при желании можно использовать любую библиотеку для парсинга. Я использую lxml, хотя по-умолчанию там libxml2.

Фишка Scrapy в том, что он не говорит, что «Twisted это в первую очередь надстройка над Python. А то, какого вы паука на нем напишете зависит от вашей фантазии и знания Python». Он говорит — скачиванием страничек я занимаюсь сам, диспетчеризацией данных, очередью запросов, приоритетами, обработкой исключений, поиском ссылок, защитой от зацикливания, защитой от того, что странички "/catalog.php?p1=1&p2=2" и "/catalog.php?p2=2&p1=1" это одно и то же, удаленная консоль, отладка памяти, REST интерфейс для управления, логгирование, генератор кода, отличная документация и куча других штуковин. Причем все это можно легко отключить или доработать. Есть готовая инфраструктура, вам остается только написать стартовую страницу, XPath запросы и (опционально) механизм для сохранения результатов (только если нужно что-то сложнее CSV/XML — для этих есть уже готовые экспортирующие конвейеры).
Очень интересно хотелось бы больше информации

По вот этой части:
>>выполнение POST запросов, поддержка куков и сессий, аутентификации

Раньше я для этого использовал mechanize — конкретно авторизация, заполнение и отправка форм, получение данных из форм редактирования.

Scrapy позволяет это?
да, вконтакте им ок парсится, делал бота раньше
Да, все это можно. Делается так:
FormRequest.from_response(response,
                    formdata={'username': 'john', 'password': 'secret'},
                    callback=self.after_login)


Scrapy также следует редиректам, хранит куки, устанавливаемые с сервера (иногда нужно отключать).
JavaScript код не выполняет, поэтому если сайт на Ajax, запросы необходимо прописывать вручную.
И все это из коробки.
По сравнению с Mechanize есть одно очень важное преимущество — производительность. Scrapy работает поверх Twisted — асинхронного фреймворка. Поэтому держать по тысячи соединений одновременно вполне реально.
Памяти дофига нужно.
Ну, гораздо меньше, чем понадобилось бы при использовании потоков.
Мне понравилось, как раз искал подобные темы
Эта штука умеет запускать паука и парсер многопоточно? Это true-многопоточность (noGIL)?
Там Twisted внутри.
НЛО прилетело и опубликовало эту надпись здесь
Оно НЕ умеет многопоточность. Оно на асинхронных сокетах. (На всякий случай уточню — это плюс). Я им парсил 20 форумов разных, на каждый форум по 4 одновременных соединения. Полет нормальный.
А в чем плюс? Помимо самого скачивания есть же еще и парсинг кода для поиска ссылок с целью их обхода, отномающий не мало процессорного времени. В итоге вы упретесь в процессор, вместо того чтобы упереться в пропускную способность сети.
Ну так при одинаковом количестве страничек в секунду расход процессора будет один и тот же на многопоточном и асинхронном спайдере. Но первый будет жрать заметно больше памяти (плюс оверхед на переключения контекста потоков) ну и усложнение кода из-за необходимости всяких блокировок, очередей и пр.
Упирался в процессор только когда на одном из форумов напарывался на 10Мб страничку. При ее разборе блокировался весь паук и ядро процессора нагружалось на 100%. Но я сомневаюсь что использование многопоточного паука решило бы эту проблему. Он так-же уперся бы в процессор.

Хотя идеальный паук в моем видении должен использовать асинхронные сокеты для скачивания и пул потоков (еще лучше — пул процессов) для парсинга. Scrapy такой подход не реализует к сожалению и я не смог найти способа просто реализовать это на базе Scrapy. Это конечно жаль.
Поиграл в IE9 — тормозов не заметил.
Блин, думаю, что минусуют, я не в ту тему коммент оставил, извиняюсь.
Хорошая статья, сам похожую хотел давно написать.

От себя добавлю что использую его на работе, очень доволен. Высокая производительность, легко расширять и подстраивать под свои нужды, отличная документация.

Тем кто работал с Django особенно понравится, т.к. по структуре они очень похожи.

Ну и по поводу написания пауков — я их пишу совсем по другому. У меня пауки наследуются не от CrawlSpider а от BaseSpider. Т.е. я сам формирую Request-ы а не доверяю это SgmlLinkExtractor-у. Немного больше кода, но гораздо больше контроля. И XPathItemLoader-ы я не использую, заполняю Item ручками из XPath, не знаю почему, может они недавно появились…
По мне, лучше использовать CrawlSpider, когда это возможно. Если сайт сделан нормально, не вижу смысла не доверять. А про BaseSpider думаю написать отдельную статью.

О XPathItemLoader написано еще в 0.7 версии. Я решил показать, что они есть. Хоть они иногда ограничивают возможности, мне нравятся тем что они отделяют парсинг и валидацию. Еще extract() возвращает список, в котором обычно нужен только первый элемент. Это удобно сделать с помощью TakeFirst, прописав как дефолтный процессор.
Тема интересна, прошу продолжения)
Если есть возможность — киньте ссылки на статьи\туториалы по Scrapy, кроме родного сайта, которые считаете интересными\полезными.
Спасибо за статью!
Возник один вопрос.
Не могу разобраться, как настроить краулинг через прокси… Кто-нибудь сталкивался?
В доке поиск есть. А вопрос есть в FAQ.
HttpProxyMiddleware.
Знаю, что HttpProxyMiddleware.
Только по тому, что написано в доке — не разберусь как его применить. Как указать список прокси?
Список? Вы хотите ротацию? Мидлварь это не умеет. Впрочем, косвенно из её доки, а прямо из её кода и кода scrapy.core.downloader.webclient.ScrapyHTTPClientFactory._set_connection_attributes() следует, что достаточно выставить request.meta['proxy'] в URL прокси.
Да, хотелось ротацию. Но пока не могу задать даже один прокси )
Где я могу получить доступ к request.meta['proxy'], если я использую rules и реквесты формирует SgmlLinkExtractor?
> Но пока не могу задать даже один прокси )
Переменную окружения выставляли?

> Где я могу получить доступ к request.meta['proxy'], если я использую rules и реквесты формирует SgmlLinkExtractor?
Тогда видимо придётся писать свою мидлварь (это и универсальнее) на основе кусков HttpProxyMiddleware.
Спасибо за советы =)
Написать свой мидлварь — это хорошая идея!
Кстати, возможно, я нашел место где можно задать request.meta['proxy']. С помощью process_request (параметр конструктора класса Rule)
Подскажите, пожалуйста, где задать request.meta['proxy'] при использовании CrawlSpider?
Не совсем понял, что делать, если какая-то страница содержит и блок данных и ссылки на другие данные,
причом блок данных на текущей надо связать с данными на страницах по ссылкам.

Например, на странице учебного курса есть его описание, а по ссылкам — отдельные лекции.
Каждую лекцию надо связать с описанием курса, ну хотябы название курса всобачить.
(из предположения, что на странице самой лекции даже название курса не указано)
Или например, так:
example.edu/classes/:
Лекции по физике


example.edu/classes/phys/1
Вводные



И надо собрать все заголовки либо в разные свойства айтемов лекций, либо в одно списочное.

Как быть?
1. Как в примере выше, написать Pipeline, который будет писать в 2 csv-файла: по ссылкам с лекциями и по ссылкам с вводными. Вместо csv можно использовать любое хранилище, сводить данные там же или отдельно.
2. Передавать собранные данные на странице с лекциями в request на страницу с вводными.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации