суббота, 23 июля 2011 г.

Shpider. Простые примеры


Многие, кто только начал изучать Haskell сразу лезут в Web. Причем лезут с двух сторон, с одной стороны это web-пауки, а с другой сайты и порталы.

При наличии великолепных web-фреймворков вроде Snap или Yesod, написание CMS для сайта не является подвигом.


А вот с web-crawler'ами новичку будет сложнее. Наиболее удобной библиотекой является Shpider.

Установить её можно с помощью cabal:
cabal install shpider
Итак, приступим.

Сперва взглянем на тип Shpider, с ним нам придется все время работать:
type Shpider = StateT ShpiderState IO
Мы имеем state transformer monad с состоянием ShpiderState и используемой "внутри" IO монадой. ShpiderState мы разберем чуть позже.
Т.к. мы работаем со state transformer monad, то любые действия надо будет выполнять через подобие runState - runShpider.

Главный модуль называется Network.Shpider, его мы и импортируем:
import Network.Shpider
Начнем с простых примеров:
a1 = runShpider $ download "http://kreed131.blogspot.com/"
Функция download возвращает tuple из ShpiderCode и Page. ShpiderCode, как написано в документации, описывает различные непредвиденные ситуации, которые могут случиться во время краулинга. Грубо говоря, это "return code", который оповещает нас о том, все ли хорошо прошло.

Тип Page содержит в себе исходный код страницы, все формы со страницы, все гиперссылки со страницы, адрес страницы и "Tag Soup". С "Tag Soup" вы скорее всего и продолжите работать, для этого вам понадобится модуль Text.HTML.TagSoup.
Библиотека tagsoup позволяет удобно работать с валидными и невалидными html/xml документами.

С runShpider мы можем использовать do-нотацию:
-- | Получим html-код страницы
a2 = runShpider $ do
         s <- download "http://kreed131.blogspot.com/"
         return (source $ snd s)
-- | Или гипперссылки
a2 = runShpider $ do
         s <- download "http://kreed131.blogspot.com/"
         return (links $ snd s)
-- | Заполним форму a3 = runShpider $ do          f <- fmap (head . forms . snd) $ download "http://www.yandex.ru/"          sendForm $ fillOutForm f $ pairs $ do                       "login" =: "helloworld"                       "password" =: "superpassword"
Все вроде понятно. Но вот незадача: некоторые сайты шлют нас лесом, им видите-ли, наш пустой user-agent не нравится. А еще cookies нет. Что же делать?

Тут нам и приходит на помощь ShpiderState.
ss = SS { startPage = ""
              , htmlOnlyDownloads = False
              , dontLeaveDomain = False
              , curlOpts = [ CurlCookieFile "cookies"
                           , CurlCookieJar "cookies"
                           , CurlUserAgent 
                             "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.27 \
                             \(KHTML, like Gecko) Chrome/12.0.718.0 Safari/534.27 
                           ]
              , currentPage = emptyPage
              , visited = Nothing
        }
Теперь мы определили наш user-agent и cookies будут сохраняться в файле "cookies". Shpider "под капотом" имеет всем знакомый curl, поэтому о параметрах curlOpts подробнее можно посмотреть тут.

Теперь настало время включить наш ShpiderState. Сделать это очень просто:
a2 = runShpider $ do
         put ss -- вводим наш state
         s <- download "http://kreed131.blogspot.com/"
         return (links $ snd s)
Вот и все! Web-crawling на Haskell доступен всем! ;)

Комментариев нет:

Отправить комментарий