Еще немного про Google Hack

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

1. Используем прокси

Прием с кукисами и tcpdump действительно позволяет обойти защиту от ботов, однако он имеет несколько существенных недостатков. Во-первых, этот прием неудобный — нужно запускать снифер, проходить капчу, прописывать кукис. Во-вторых, он не надежен — кто знает, как долго тема будет оставаться рабочей? И наконец, способ накладывает ограничение на частоту посылки запросов.

Если бы мы слали запросы через http/socks прокси, ни одной из названных проблем у нас не было. Да, названных проблем мы бы избежали, однако получили бы пару новых. Обычно паблик-прокси медленные и быстро умирают. Потому использовать их мы не будем.

Вместо них я решил использовать анонимайзеры. Кто не в курсе, анонимайзеры — это веб-скрипты, предназначенные для скрытия IP, а также вырезания рекламы из страниц и некоторых других вещей. Пожалуй, самым известным анонимайзером в рунете является Anonymizer.Ru. В сети существуют тысячи анонимайзеров, самый полный список которых можно найти на Proxy.org. Большинство из них работают на скриптах Glype и PHPProxy.

Есть много причин, зачем люди создают сайты-анонимайзеры. Например, можно показывать в начале каждой просматриваемой страницы контекстную рекламу. Или банально собирать пароли от GMail и ВКонтакте. Однако это для нас сейчас не так важно, как то, что анонимайзеры обычно намного быстрее socks-прокси и редко бывают оффлайн. Так от чего бы не слать запросы к Google через них?

Что интересно, искать анонимайзеры мы будем также с помощью Google. Какая ирония. Вот простой запрос, позволяющий собрать список сайтов, на которых работает PHPProxy:

"Rotate13" "Base64" "Strip" inurl:index.php?q=

Строки Rotate13, Base64 и Strip находятся в верхней части страницы, созданной с помощью PHPProxy.

Просмотр страницы через PHPProxy

Как видно на скриншоте (знаю, что он мелковат, но видно же!), URL просматриваемой страницы передается PHPProxy в аргументе q закодированный в Base64. Собрав пару десятков таких прокси, мы сможем слать все запросы к Google через них, без необходимости обходить капчу и делать задержки между запросами.

2. Генератор url запросов

Вместо того, чтобы при каждой новой задаче писать новый парсер Google, лучше написать универсальный парсер, принимающий на вход собственно запросы к ПС. А возьмем мы эти запросы откуда? Правильно, получим с помощью генератора запросов. Вот пример такого генератора:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/perl

use strict;

my $query = "\"Rotate13\" \"Base64\" \"Strip\" inurl:index.php?q=";

for my $p(0..9) {
  for my $zone(qw/.com .net .org .biz .info .de .ru/) {
    my $q = "$query site:$zone";
    $q =~ s/ /%20/g;
    print "http://www.google.ru/search?q=$q&num=100&start=${p}00&filter=0\n";
  }
}

Правда, написать такой скрипт проще, чем новый парсер? Кроме того, работая со списком запросов мы можем:

  • Перемешать его с помощью команды «cat list.txt | rl > rslt.txt». Посылая запросы вперемешку, мы вызовем у ПС меньше подозрений относительно их естественности;
  • Распараллелить парсинг. Просто запускаем несколько процессов-граберов, подав каждому на вход часть списка запросов. И никаких лишних скриптов для этого писать не надо;
  • Если грабер будет выводить номера выполненных запросов, мы сможем в любой момент приостановить его. Как только мы снова будем готовы к парсингу (ISP исправил неполадки в сети), удаляем из списка уже обработанные запросы, после чего возобновляем работу.

3. Универсальный грабер

А вот собственно и сам скрипт, посылающий запросы Google:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/perl

# Google Parser
# (c) Alexandr A Alexeev 2010 | http://eax.me/

use strict;
use MIME::Base64;

my @proxies = split /\n/, `cat proxies.txt`; # список PHPProxy

my $opt  = "--timeout=10 --no-check-certificate --user-agent='Mozilla/5.0 (X11; U; FreeBSD i386; ru-RU; rv:1.9.1.10) Gecko/20100625 Firefox/3.5.10'";
my $line = 0;
while(my $url = <>) {
  $line++;
  chomp $url;
  $url .= "&hl=en"; # язык выдачи - только английский
  print STDERR "url = $url\n";

NEW_ATTEMPT:
  my $proxy_url = $proxies[rand(@proxies)].encode_base64($url);
  $proxy_url =~ s/\n//g;
  print STDERR "proxy_url = $proxy_url\n";
  my $data = `wget $opt -q '$proxy_url' -O -`;

  my @sites = $data =~ /<h3 class="r"><a href="[^\?]+index\.php\?q=([^&"]+)"/g;
  my @sites = map {
    s/(\%3D)/=/g; s/(\%2B)/+/g; s/(\%2F)/\//g;
    $_ = decode_base64($_);
    s/(&amp;)/&/g;
    $_; } @sites;
  print STDERR "  >> line = $line, ".(scalar @sites)." sites found\n";
  if((scalar @sites == 0) && ($data !~ /Your search - <b>[^<]*<\/b> - did not match any documents/i)) {
    print STDERR "  >> ERROR, NEW ATTEMPT...\n";
    goto NEW_ATTEMPT;
  }
  print "$_\n" for(@sites);
}

Я думаю, вы без труда разберетесь в том, как работает этот скрипт (или нет — тогда читаем мои уроки Perl). Ключевая его часть — это строки с 25-ой по 30-ую. В них происходит поиск ссылок в ответе Google. Притом ссылки эти преобразованы используемыми нами анонимайзерами, список которых подгружается из файла proxies.txt. Потому прежде, чем выводить список ссылок пользователю, нужно их декодировать из Base64.

4. Валидатор прокси

Вот нашли мы пару рабочих анонимайзеров (пункт 1), сохранили в proxies.txt. Затем сгенерировали список запросов (2) и обработали его с помощью парсера (3). Что теперь делать с полученным списком ссылок?

Для начала нужно отфильтровать ссылки вида [сайт]/index.php?q=, поскольку именно так начинается url страниц, просматриваемых через PHPProxy, после чего удалить повторяющиеся строки:

cat google-proxies-serp.txt | grep -Eio '(https?://[^&]+/index\.php\?q=)' | sort -u > check-proxies.txt

Эта была, так сказать, предварительная обработка. После нее найденные прокси нужно проверить на работоспособность:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/perl

use strict;

my @proxies = split /\n/, `cat check-proxies.txt`;

for my $p(@proxies) {
  my $data = `wget --timeout=10 --user-agent='Mozilla/5.0 (X11; U; FreeBSD i386; ru-RU; rv:1.9.1.10) Gecko/20100625 Firefox/3.5.10' -q '${p}aHR0cDovL2dvb2dsZS5jb20v' -O -`;
  if($data =~ /<title>Google<\/title>/) {
    print "$p\n";
  } else {
    print STDERR "ERROR: $p\n";
  }
}

Алгоритм простой — пытаемся зайти на google.com (в base64 — aHR0cDovL2dvb2dsZS5jb20v), и если в ответе скрипта будет title, как на Google, значит анонимайзер рабочий.

В результате описанных в пунктах 1-4 действий, мне удалось получить список из 106 рабочих анонимайзеров. По-моему, этого более, чем достаточно для парсинга выдачи Google. К тому же, теперь у меня есть универсальный парсер, который уже несколько раз успел мне пригодиться. Надеюсь, и вы найдете ему применение!

Подпишитесь на блог с помощью RSS, E-Mail, Google+ или Twitter!
Также, пользуясь случаем, приглашаю вас посетить мой форум.

  • Ипполит Карамазов

    Спасибо за совет на счет анонимайзеров, а вот вопрос: как определить ворует он пасы или нет?

  • http://eax.me/ Безумный Программист

    Если не вы его устанавливали — то никак.

  • Ипполит Карамазов

    Это не есть гуд…
    Второй вопрос — постовыми не хочешь обменяться c seolondon.ru?

  • http://eax.me/ Безумный Программист

    Нет, я больше не практикую постовые в этом блоге :) А в твиттере Вас нет?

  • http://www.denaie.ru denaie

    :) вот за что я перл люблю, код на нем выглядит как сборище регулярных выражений.. слов то почти нет

  • http://eax.me/ Безумный Программист

    Хм… я так понимаю, это хорошо? :)

  • http://rogovsky.net/ Андрей

    А на практике что можно сделать?
    Допустим получить список удаленных ЖЖ аккаунтов?

  • http://rogovsky.net/ Андрей

    А на практике что можно сделать?
    Допустим получить список удаленных ЖЖ аккаунтов?

  • http://rogovsky.net/ Андрей

    А на практике что можно сделать?
    Допустим получить список удаленных ЖЖ аккаунтов?

  • No

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

  • http://eax.me/ Безумный Программист

    Ну я, к примеру, недавно собрал список dofollow форумов и отсортировал его по тИЦ.

  • http://eax.me/ Безумный Программист

    А гавносайты тут причем? Я писал несколько генераторов сайтов, но ни один не использовал Google.

  • No

    используя описанную технику говновебмастеры юзают гугл для проверки покупных ссылок для поднятия своих говносайтов, проверки индексированности страниц чужих говносайтов, на которых они купили ссылки, да много что можно сделать с этим. Только в основной своей массе говновебмастеры туповаты и к программированию (не осилили) не имеют никакого отношения, поэтому такие вот ресурсы для них очень ценны. Здесь же даются готовые решения.

  • http://eax.me/ Безумный Программист

    Все описанное биржи ссылок делают автоматически.

  • Omeh2003

    Чушь вы пишите. Рост массы говносайтов приводит к повышению качества поисковых алгоритмов. Что выгодно конечному пользователю. А вашей точки зрения придерживаются как раз те кто неспособны придумывать свои темы. А подглядев у других сидят и хомячат в тихоря. Вот от таких пользы обществу действительно ноль.

    А автору спасибо, пошел искать новые способы :)

  • http://bolverin.com/ BOLVERIN

    ничего особенного тут не описано. не исходите в гавно по поводу гавносайтов, они не портят выдачу совершенно

  • http://bolverin.com/ BOLVERIN

    а. ну в общем ты ужо так сделал как я в прошлом камменте написал)

  • daniel_1024

    хм, тогда лучше было бы парсить список анонимайзеров с http://proxy.org/cgi_proxies.shtml, сортировать по типам, проверять и использовать.
    кстати, я заметил, бывают случаи, что такие скрипты анонимайзеры еще и находятся на одном сервере и соответственно имеют одинаковый ip. плохо =(
    И использовать можно не только PHPProxy, но и Glype, ASProxy, Zelune и др.

  • http://eax.me/ Безумный Программист

    Спасибо за Ваш комментарий.

    Тут один скриптик работает у меня уже вторые сутки (решил запустить в один поток, тк не к спеху) безо всяких проблем, так что по поводу IP беспокоиться не стоит.

    proxy.org не стал парсить, потому что не знаю, как они составляли список, возможно он не полон. Один тип прокси выбрал для простоты, один тип — один интерфейс.

  • sugar

    какой кодер, такой и код. Автор явно заботился о функциональности, но никак не о читаемости кода. Кстати в этом коде действительно много регулярок, думаю он не лучше бы и на каком-нить пехепе выглядел.
    Автору:
    Если желаете улучшить качество кода (его читаемость, сопровождаемость и т.п.) есть классная книга Демиана Конвея «Perl Best Practice». На английском языке, содержит очень много ценных и практических советов. К ней, присутствует почти во дистрибутивах линукса, есть такая утилита — perlcritic. Она парсит прогу, и указывает на строки кода с рекомендациями из книги по его улучшению (прям со ссылкой на страницу книги, поэтому лучше качать pdf вариант).
    зы если нужно могу кинуть пдфку, пиши на почту.

  • http://eax.me/ Безумный Программист

    Спасибо за совет, книжку уже нашел.

  • sugar

    pdf? так быстро.. =) я ее минут сорок гуглил, только на 7 странице нашлась живая ссылка (O'Reilly по ходу выкашивает)
    С chm страницы не совпадают

  • daniel_1024

    а выдача яндекса Вас не интересует ? там с помощью их сервиса xml.yandex.ru можно спарсить сотни тысяч ссылок за несколько минут пример: я написал скрипт-парсер — за две минуты спарсилось 200к ссылок. *в шоке*
    вообще, хотел спросить, какая выдача, google или yandex наиболее предпочтительна ?

  • http://eax.me/ Безумный Программист

    Спасибо за информацию. Если интересует скорость, то Яндекс определенно лучше, судя по Вашим словам :) Однако Google в выдаче имеем больше страниц. Кроме того, я не знаю, поддерживает ли Яндекс.XML такие вещи, как поиск по новостям или по блогам.

  • Murz

    xml.yandex.ru даёт только 1000 запросов в сутки с одного IP плюс каждый IP-шник нужно привязывать к аккаунту, так что с Яндексом особо не разгуляешься.

  • TheAthlet

    > my @proxies = split /n/, `cat proxies.txt`; # список PHPProxy
    Для этого есть более лучший и кроссплатформенный вариант

    use File::Slurp;
    my @proxies = read_file(‘proxies’);