Парсинг сайтов
0,0
рейтинг
5 марта 2012 в 14:27

Разработка → Документация по Grab — библиотеке для парсинга сайтов

Я ранее уже рассказывал на хабре о Grab — библиотеке для парсинга сайтов и о Spider — асинхронном модуле для парсинга. Рад сообщить, что я наконец-то дописал документацию по Grab. Я решил писать всё на русском языке т.к. на английском языке мне труднее выражать мысли. На деле писанины получилось гораздо больше, чем представлялось в начале, но я таки описал практически все функции библиотеки. Я решил просто вставить сюда, оглавление, кликайте на интересный раздел и читайте о возможностях Grab:



Кстати, HTML-код оглавления я подготовал скриптом с использованием Grab:

# coding: utf-8
from grab import Grab
from lxml.html import tostring

g = Grab()
g.go('http://grablib.org/docs/')
g.tree.make_links_absolute('http://grablib.org/docs')
elem = g.xpath(u'//h3[text()="Руководство пользователя"]/following-sibling::ul[1]')
toc = tostring(elem, encoding='utf-8')
print toc


Официальный сайт библиотеки grab: grablib.org
Вопросы по использованию grab писать лучше не мне в skype/jabber, а в майл-лист: groups.google.com/group/python-grab
Также напоминаю, что мы (grablab) занимаемся парсингом сайтов на заказ, если вам нужно собрать и обработать данные — обращайтесь.

Далее я планирую заняться документированием асинхронного spider модуля.
@itforge
карма
75,2
рейтинг 0,0
Парсинг сайтов
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (57)

  • 0
    хорошая библиотека ) уже достаточно давно с ней успешно работаю.
    на данный момент аналоги с подобным функционалом мне неизвестны.
  • –2
    Тоже на этом специализируюсь. Не знал, что специальные либы существуют. Мой инструмент — regexp =)
    • +22
      Примите мои соболезнования…
      • 0
        Ага, к тому же учитывая существование специализированных парсеров вроде pyparsing
      • +1
        Честно говоря, иногда подумываю написать обёртку для регекспов, какой-нить облегчённый xpath. Просто бывает, когда надо парсить миллионы страниц, xpath слишком медленный, вернее само построение DOM-дерева.
        • 0
          xpath подразумевает наличие дерева. Может быть, обертка нужна не для регекспов, а для SAX?
          • 0
            SAX непременим для разбора невалидных XML. Все сайты невалидные. Чтобы получить валидный XML из битого HTML, нужно затратить усилия, сравнимые с построением DOM-дерева. Поправьте, если я ошибаюсь.
            • 0
              А та же ситуация будет ведь и для регекспов и, тем более, для xpath? Честно говоря, вам должно быть виднее.

              В дотнете есть библиотека HtmlAgilityPack, там, например, незакрытые теги HTML4 (даже br) увеличивают степень вложенности следующих за ними. Это к вопросу о затрачиваемых усилиях.
              • 0
                А что регекспы? Регекспу /<div[^>]*>([^<]+) абсоюлтно пофиг, какой документ, валидный или нет, он просто ищет текст внутри div-тэга.

                Вся сложность с регекспами в том, что очень сложно описать вложенные тэги. Банальное xpath выражение "//div/div" с помощью регкспов описывается монстрообразным (не проверял):

                <div[^>]*>\s*<div[^>]*>(.(?!))+\s*
        • 0
          Написание своей обертки для xpath приведет к написанию… xpath! Причем скорее всего менее расширяемого и, возможно, более тормозного. Так зачем?

          Есть отличный инструмент в виде xpath, есть различные библиотеки реализующие работу с ним, смысла изобретать своё нет и в данном случае, имхо, разумнее масштабироваться горизонтально. И тогда не важно, что конкретный разбор идет долго (что делать, за гибкость xpath нужно платить), главное разбросать это на Х параллельных работ.
          • 0
            > Написание своей обертки для xpath приведет к написанию… xpath! Причем скорее всего менее расширяемого и, возможно, более тормозного. Так зачем?

            Регекспы работают очень быстро. Естественно не нужно заново изобретать xpath, достаточно очень простого синтаксиса, чтобы описать пару самых распространнённых случаев:
            1) найти тэг с заданным class/id
            2) найти тэг с заданным class/id, у родителя которого заданный class2/id2
            3) У тэга из 1 и 2 получить аттрибут какой-нибудь
            4) У тэга из 1 и 2 получить содержимое.

            Не нужна расширяемость, нужна быстрая реализация простых паттернов.

            Горизонтальное масштабирование хорошо, когда есть под рукой облако, желательно бесплатное :) В этом направлении я тоже копаю постепенно, например, щас в grab:spider можно разбить выполнение задачи по ядрам, но особого прироста это не даёт, двукратное ускорение на моём четырёхядерном-athlon. Да и ещё оказалось, что модуль multiprocessing не шибко удобная штука, распараллеливание по сети в нём вроде как вообще нету. Думаю посмотреть в сторону какого-нить pyro
            • 0
              celery, execnet
              • 0
                dispy, delegate, forkmap (original), forkmap (modified), ppmap, POSH, pp, pprocess, processing, PyCSP, remoteD, batchlib, Celery, Deap, disco, dispy, DistributedPython, exec_proxy, execnet, IPython, jug, mpi4py, NetWorkSpaces, PaPy, papyros, pp, PyLinda, pyMPI, pypar, pyPastSet, pypvm, pynpvm, Pyro, rthread, ScientificPython, seppo, Star-P for Python, superpy, Google App Engine, PiCloud, StarCluster, Ganga, Minimum intrusion Grid, PEG, pyGlobus

                :)
            • 0
              Приведенный примеры действительно хорошо партируются на регекспы и работают быстрее (у меня в среднем где-то в раз 8-10 работали). Тут не поспоришь. Только вот чаще всего на практике они полезны в очень небольшом спектре задач. А для парсинга чаще всего как раз нужен механизм хитрых вытаскиваний которых на регекспах 1) ужасны (в плане вида и сложности, как следствие сложность супорта такого кода); 2) содержат ошибки которые могут проявится не сразу.

              Под масштабированием я понимаю раскидку задачи по нескольким хостам. Не важно, как долго страница грузиться на отдельном хосте, важно, что таких хостов много и в сумме они могут достаточно быстро лить обработанные данные на агрегирующий сервер (который по сути выполнят роль менеджера задач + БД для сохранения результатов).

              Лично я для парсера выбрал PHP. Можно накупить дешевого харед хостинга. Загрузку и обработку данных можно делать на них, агрегирующий сервер может быть уже любым. В виде плюшек получаем: «скрытый» парсер (т.е. «снаружи» агрегирующий сервер не видно, а хосты шаред хостинга легко добавляются/удаляются, так что IP адрес самого парсера не палится и не может быть забанен), возможность быстрого горизонтального масштабирования.
              • 0
                Я думал, на php шаред-хостингах обычно обрубают взимодействие с сетью.
                • 0
                  Извиняюсь, но тогда нахрена такой хостинг нужен? С него же тогда даже банально курс валют не получить, RSS не прочесть и ни какой внешний API в духе вконтакте или твиттера не получить. Так что нет, ни чего не отрубают, curl (или другие механизмы достучаться из скрипта наружу) есть на многих. А у кого нет, это не хостинги.

                  А отрубают за спам, за большую нагрузку на БД ну и в целом по ситуации. Если не наглеть, то жить вполне себе в их условиях можно.
    • +3
      Ну, вообще, их не одна. Например, scrapy.org очень популярен.
    • +4
      Вам нужно ознакомиться с этим документом: stackoverflow.com/a/1732454/55209
      • +1
        Ну вот, сколько лет на регекспах парсил и даже не задумывался о чем-то другом, а тут вот оно как в мире.
        • 0
          Вполне возможно, что под парсингом вы подразумеваете какую-нибудь более узкую задачу.

          Универсальную библиотеку для парсинга HTML на регэкспах сделать впринципе невозможно. То есть, если у вас стоит задача в рамках одного проекта извлекать информацию из разнородных документов, то вам нужно что-то более для этого приспособленное.

          Если же нужно из пары страниц с известной структурой вытащить, например, все ссылки, то регекспами пользоваться можно и иногда даже нужно.
          • 0
            А если эта известная структура представляет из себя валидный XHTML, то обычно лучше с ней работать как с XML.
    • +1
      Я надеюсь, что вы пошутили. Если же нет, то вот ссылка на stackoverflow, которая сразу же вспомнилась в связи с вашим ответом.
      • 0
        Баян :) В смысле, эта ссылка на два коммента выше уже запощщена.
        • 0
          Упс :)
  • 0
    я конечно извиняюсь, но как ту получить например все iframe?
    мне выдает только первый
    • 0
      grablib.org/docs/grab/dom.html#xpath — используйте метод `xpath_list` или `css_list`
      • 0
        благодарю, как-то упустил
        • 0
          Просто намного чаще нужен один элемент, так что я решил более короткое имя зарезервировать для получения первого элемента из выборки.
  • 0
    Хорошая вещь!
    В результате её изучения Убунта теперь каждое включение приветствует меня свежим анекдотом с баша
    • +3
      Свежим? Анекдотом? С баша? Не смешите.
      • 0
        Ну для меня свежий. Хотя смысл скорее — свежедоставленный
      • 0
        А, по-моему, последняя цитата там очень даже:

        <DevXen:> Today I was at the store and saw a Darth Vader action figure that said «Choking Hazard.» It was great.

        bash.org/?latest
  • 0
    Принципиальные отличия от Scrapy имеются?
    • 0
      Cмотря, что называть принципиальным отличием. С высоты птичьего полёта — та же петрушка. А если смотреть оооочень детально, то в двух разных минорных версиях Scrapy можно найти принципиальные отличия :)
      • 0
        Абсолютно согласен.
        Проблема в том, что Скребок был первым что попалось под руку, и более того — я занимаюсь тем же, чем и вы ;)

        Вопрос вот в чем: насколько безболезненным будет переход от Scrapy к Grab?
        • 0
          Увы, не могу ничего вам обещать. Но есть пример: мы с товарищем по grablab вместе занимаемся парсингом, он сначала использовал scrapy, а потом как-то не могу побороть один баг, попробовал grab:spider, да так на нём и остался. Причём он его без всякой документации юзает т.к. по сути там апи не сильно сложный.

          Архитектура у обоих фреймворков одинаковая: пишем функции для обработки ответа от сервера, внутри функции можно порождать новые запросы. В данный момент в grab:spider нет никаких фишек для деплоя — я беру файл, называю его spider.py и фигачу туда всю логику, затем я запускаю его через команду python spider.py — вот и весь деплой :) В принципе, довольно удобно, в скрапи меня напрягала вся эта возня с проектами, с настройками, с пайплайнами. В спайдере нету пайплайнов, куда хотим — туда и пишем ручками… Я пишу в mongodb обычно.

          В spider есть одна фича — не знаю, есть ли она в scrapy. Эта фича сильно обгечает отладку парсинга и повторный парсинг. Все GET-запросы кэшируются в монгодб. Очень-очень удобно :)
          • 0
            без MongoDB заведется?
            • 0
              Да, монга опциональна. Вот без pycurl точно не заведётся.
              • 0
                dumpz.org/173587/ — я сейчас этой болванкой пользуюсь, когда новый проект начинаю
        • 0
          за день? ) пара примеров и все ясно, xpath и там и там один и тот же, общие принципы работы тоже. мне как-то пришлось несколько пауков переписывать (scrapy->grab), управился за пару часов.

          кстати есть конференция в жаббере, я думаю там с радостью ответят на возникающие вопросы =)
    • 0
      использовал scrapy достаточно продолжительное время, grab понравился больше.
      тому есть множество причин, например скорость парсинга в грабе у меня получается на порядок (!!!) выше. ну и он проще, больше контроля. если скрапи это как бы django в мире парсинга, то grab — это flask ) как-то так.

      на скрапи канешно много всего — всякие фишки для деплоя, получение информации о работе пауков. но мне это (да и обычному программисту) чаще всего не нужно.

      к плюсам граб можно отнести то что он на 100% проверен в деле т.е. бро itforge писал/дописывал зачастую параллельно с какими-то проектам которые на полную использовали функционал библиотеки, поэтому она получилас весьма удобной и продуманной до мелочей.
  • 0
    есть что-то подобное под .net?
    • 0
      Html Agility Pack для разбора, есть еще какие-то расширения к нему
  • 0
    Спасибо :)
  • 0
    Я так понял JavaScript в пролете? Если так, то очень жаль.
    Сейчас бывает порой, пол сайта генерит JavaScript. Сам пользуюсь Mechanize или Selenium там где много скриптов, но далеко на нем конечно не уедешь.
    • +1
      в любом случае для js нужен браузер (виртуальная машина которая будет обрабатывать js код). есть транспорт для Selenium grablib.org/docs/grab/transport.html#selenium

      сам селениум, если я не ошибаюсь позволяет поключать htmlunit.
    • +1
      Есть планы по подключению selenium, там на самом деле день-два посидеть и будет рабочее решение.
  • 0
    Вот всегда так, только задумываю заняться каким-то новеньким проектом, или технологией, так нужная мне статья выскакивает на хабре. Спасибо:)
  • 0
    вопрос, можно сделать так
    if 'text' in g.response.body:
    а можно так
    if g.seach('text'):

    что будет более рационально? или это для каких-то других целей сделано?
    • 0
      > или это для каких-то других целей сделано?
      `g.search`, по-умолчанию, работает с уникодом и ищет в unicode-представлении документа. То есть вам не нужно думать, в какой кодировке документ, вы можете всегда исползовать unicode-аргумент для поиска. Если же вы хотите искать таки байтовую строку, то нужно передать дополнительный аргумент `byte=True`, тогда поиск будет происходить в `g.response.body`.

      > что будет более рационально?
      docs.python.org/library/timeit.html
  • 0
    Насчет urllib с этой либой есть проблемы в транспортной части, она не может подключится к ряду сайтов. Например wikipedia.org Поэтому использую grab, с ним еще проблем не возникало.
    • 0
      С urllib всё в порядке. Просто для подключения к википедии надо указывать реальный User-Agent. Возможно что-то ещё, я давно не заморачиваюсь такими вещами т.к. в Grab все нужные заголовки генерируются.
      • 0
        Спасибо за наводку :)
  • 0
    Кто-нибудь grabил сайты на GWT?
  • 0
    Как это подключить к xmlrpclib, чтобы закачать жж с помощью программы ljdump?

    Ибо жж уже на 1000 записи пишет Fault 402: 'Client error: Your IP address is temporarily banned for exceeding the login failure rate.

    Или подскажите инструмент, с помощью которого можно выкачивать жжурналы с авторизацией, желательно в xml-виде, с комментариями.
    • –1
      Про инструмент ничо не подскажу. Чтобы не было бана по IP — используйте прокси. Например, эти datalab.io/proxy
  • 0
    Ссылки на документацию все умерли… А жаль.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.