Wed, 27 Oct 2004

Google Wrapper

Снощи се заплеснах в писането на wrapper на web-интерфейса на Google. Исках да мога програмно да разпитвам Google и да правя разни неща с резултатите. Започнах с официалното Web Services API, което дори идва с работещи примери на Java и .NET. За съжаление, официалното API има следните недостатъци:

-- Изисква предварителна регистрация

-- Допуска само 1000 заявки на ден

-- Връща максимум 10 резултата за всяка заявка

Особено последното прави този програмен интерфейс съвсем осакатен и подходящ само за тривиални експерименти.

Въоръжен с мерак за скриптиране, драснах един прототип на Питон, който използва стандартния web-интерфейс, но програмно изглежда като итератор (хич не съм го изчистил концептуално, но това ми беше последната грижа). Дори се преструва на потребител и се прави че щрака на бутона "Следваща" по време на итерацията.

Какво бе учудването ми, когато открих, че Google се правят на ощипани при използването на невизуален web-клиент. Когато се опиташ да изпълниш заявка към търсещата машина с Python urllib2 като User-Agent, Google връща любезно съобщение за грешка:

Your client does not have permission to get URL /search?q=blah from this server.

Айде, ве, не на мене тия. Бях твърдо решен ако се наложи да имитирам пълнокръвна HTTP-сесия. Наподобих повечето хедъри от моя Firefox и убедих Google, че всъщност търсещата машина се ползва от потребител на Firefox, който е изключил функцията cookies. Не че е проблем да се реализират и cookies, но защо да се престараваме след като Google работи и без тях. :-)

Така успях да подкарам прототипа и да изпълня няколко много интригуващи заявки. Вероятно знаете за заявките от тип site:domain.com, където ограничавате Google да търси само върху адресите попадащи в определен домейн и неговите поддомейни. По-слабо известна обаче е възможността [inurl:blah] където думата blah трябва да се среща в адреса на ресурса, който търсим. Така например със заявката [inurl:pdf] site:microsoft.com лесно можем да извлечем всички PDF-файлове, които се намират на сайтовете на Microsoft. Примерно.

Другата изненада беше, че през web-интерфейса си Google може да връща само първите 1000 резултата от изпълнената заявката. За да избегна това ограничение, пусках по няколко заявки, специфициращи подмножество на голямата. Например, искаме да извлечем "всички", но вместо това първо извличаме "всички, които започват с А", след това "всички, които започват с Б" и т.н. Накрая обобщаваме резултата.

Обаче като натрупаме доста такива заявки и Google по някое време баялдисва и казва: Error 503 Service Unavailable. Затуй скриптът в такива случаи трябва да се направи на пушач и да излезе на терасата в почивка няколко минути (с постъпателно нарастване на пуш-паузата при последователни откази) докато успее да продължи. Последното решение го измислихме заедно с Тревата, докато чатвахме в ShakeIT IRC.

Така мина нощта, без да я усетя.

А, да, и Ани се обади в потайна доба, беше се нашморцала здраво по случай раждането на племенника на Момчил. Тя се събуди в ранния следобед и не си спомняше почти нищо от снощния ни разговор. :-)

Така е, Ани, като не си индексираш спомените с Google. ;-)