Скачать PDF-файл из Википедии - PullRequest
6 голосов
/ 09 сентября 2011

Википедия предоставляет ссылку (слева на странице «Печать / экспорт») на каждую статью, чтобы загрузить статью в формате PDF. Я написал небольшой скрипт на Haskell, который сначала получает ссылку на Википедию и выводит ссылку на рендеринг. Когда я даю URL рендеринга в качестве входных данных, я получаю пустые теги, но тот же URL в браузере предоставляет ссылку для скачивания.

Может кто-нибудь сказать, пожалуйста, как решить эту проблему? Форматированный код на ideone .

import Network.HTTP
import Text.HTML.TagSoup
import Data.Maybe

parseHelp :: Tag String -> Maybe String 
parseHelp ( TagOpen _ y ) = if any ( \( a , b ) -> b == "Download a PDF version of this wiki page" ) y 
                      then Just $  "http://en.wikipedia.org" ++   snd (   y !!  0 )
                   else Nothing


parse :: [ Tag String ] -> Maybe String
parse [] = Nothing 
parse ( x : xs ) 
   | isTagOpen x = case parseHelp x of 
              Just s -> Just s 
              Nothing -> parse xs
   | otherwise = parse xs


main = do 
    x <- getLine 
    tags_1 <-  fmap parseTags $ getResponseBody =<< simpleHTTP ( getRequest x ) --open url
    let lst =  head . sections ( ~== "<div class=portal id=p-coll-print_export>" ) $ tags_1
        url =  fromJust . parse $ lst  --rendering url
    putStrLn url
    tags_2 <-  fmap parseTags $ getResponseBody =<< simpleHTTP ( getRequest url )
    print tags_2

1 Ответ

5 голосов
/ 10 сентября 2011

Если вы попытаетесь запросить URL с помощью какого-либо внешнего инструмента, например wget, вы увидите, что Википедия не обслуживает страницу результатов напрямую. На самом деле он возвращает 302 Moved Temporarily редирект.

При вводе этого URL в браузере все будет хорошо, так как браузер будет автоматически выполнять перенаправление. simpleHTTP, однако, не будет. simpleHTTP, как следует из названия, довольно просто. Он не обрабатывает такие вещи, как куки, SSL или перенаправления.

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

Вот быстрая и грязная функция для загрузки URL в String с поддержкой перенаправлений:

import Network.Browser

grabUrl :: String -> IO String
grabUrl url = fmap (rspBody . snd) . browse $ do
    -- Disable logging output
    setErrHandler $ const (return ())
    setOutHandler $ const (return ())

    setAllowRedirects True
    request $ getRequest url
...