Парсим Google!Николай Байбородин (baiborodin@gmail.com) Хакер, номер #112, стр. 112-112-1
Автоматизация поиска низкочастотниковКлючевые слова, ключевики, кивордз, key words – это все вариации на тему одного из мощнейших инструментов поисковой оптимизации. Но «киворд киворду – рознь» и самыми желанными из них, а, следовательно, и самыми покупаемыми, являются низкочастотные запросы. Однако, если у тебя голова и руки на месте, то ты вполне сможешь разжиться дюжиной-другой НЧ самостоятельно. Я спросил у ясеня...Или у Яндекса. Да хоть у самого Google'а – полученный ответ на девяносто девять процентов будет зависеть от того, КАК именно ты спросишь. А, поскольку в качестве инструмента мы будем использовать поисковик номер один (да простит меня ТЫндекс), то и систему построения запросов будем рассматривать на примере Google. Хм... что-то ты не весел. Или ты не желаешь больше слушать о том, как использовать в запросах кавычки, элементы булевой логики и прочие увлекательные подробности из жизни поисковых движков? Таки расслабься – секса не будет, ибо в сотый раз перемалывать избитые и всем известные истины не в мазу не только тебе, но и автору. Мы спустимся на уровень ниже – туда, где живут протоколы межсервисного взаимодействия. Туда, где нас не ждут. Туда, где балом правит REST. Конечно, ты знаком с основными хитами от Google. Быть может, даже пользуешься не только поиском, но и другими веб сервисами. Вполне вероятно, даже знаешь, что практически все гугловские разработки имеют свой собственный, что важно, открытый API, позволяющий левым кодерам использовать возможности сервисов Google в своих приложениях. Но ничто не совершенно, и API одного из приложений скрыт за семью печатями. Да, да, да – это именно поисковый API. И это вполне объяснимо. Как ни крути, а основным источником дохода для гугловцев является реклама. А если пользователь будет напрямую обращаться к поисковому движку, получая чистый результат, то, как говорится: «Где деньги, Зин?» (© Владимир Высоцкий). А тут еще гнусные оптимизаторы норовят на халяву движком порулить, или того хуже, покуситься на самое святое – поисковые алгоритмы. Некоторое время назад все-таки можно было получить доступ к поисковому API, либо попав в круг избранных, либо заплатив небольшую мзду. Но мир катится в пропасть, кругом энтропия и энурез, и на поисковый API тихо повесили амбарный замок. Теперь максимум, на что можно рассчитывать, это на выдачу результатов в XML формате. Опять-таки, не забесплатно. Впрочем, наглухо закрывать поисковый движок – бессмысленно. Иначе, как, по-твоему, будет отправлять поисковые запросы безобидный веб браузер? А раз так, что нам мешает, натянув на себя шкуру овцы (то есть, осла), получить дополнительную степень свободы и использовать ее по своему усмотрению? На самом деле все не просто... а очень просто, так как отправка поисковых запросов осуществляется с использованием протокола REST (к сожалению, этот устоявшийся термин не совсем верен, ибо REST не является протоколом – это определенный набор технологий). Так же, как, скажем, и AJAX. И что из этого следует? А следует то, что все параметры поискового запроса передаются через URL и видны, как на ладони. Все, что необходимо сделать – разобраться в назначении каждого параметра. Более того, автор это уже сделал и готов поделиться с тобой результатами своего исследования. Типичный поисковый запрос выглядит следующим образом: http://www.google.com/search?hl=ru&as_qdr=all&q=viagra&lr=lang_en Из примера видно, что поисковый запрос отправляется по адресу http://www.google.com/search. Сам запрос строится согласно стандартной GET схемы, то есть отделяется от адреса знаком вопроса, а разделение параметров осуществляется с помощью знака амперсанд (&). Самый главный параметр запроса – это, конечно же, тот, которому передается искомая фраза (параметр q). Чтобы указать язык выборки, используется параметр lr, который в качестве своего значения принимает языковой индекс. В случае русского языка это будет lang_ru, а в случае английского – lang_en. Если вдруг нужно прикинуться каким-либо конкретным браузером – используем параметр client (например, client=firefox). Если необходимо ограничиться какой-то конкретной частью документа, выручит параметр as_occt. Например, для поиска по заголовкам страниц вбиваем as_occt=title, а для поиска в последовательности символов URL, соответственно, as_occt=URL. Для первого раза, пожалуй, хватит. Дополнительные параметры ты всегда можешь нарыть в Сети (смотри ссылки, которые я для тебя подобрал). Перечисленного выше минимума вполне достаточно, чтобы конструировать простые запросы. Например, если требуется найти англоязычные ресурсы, в которых упоминается полезный витамин Viagra, запрос примет следующий вид: http://www.google.com/search?q=viagra&lr=lang_en Что еще необходимо знать, так это ограничения, накладываемые на твой запрос. Имей в виду, что максимальная длина запроса не должна превышать 2048 байт. Длина искомой фразы – не более 128 символов (сюда не входят символы пробелов и знаки препинания). Количество параметров, используемых в запросе – не более пятидесяти. Ни шагу без плана (© Великий Джа)Прежде чем ринуться в бой, не мешало бы наметить план будущих действий. На самом деле, вариантов парсинга Google'а – вагон и маленькая тележка. Наиболее очевидный вариант выглядит следующим образом. Формируем поисковый запрос с интересующим нас словом. В ответ получаем набор страниц выборки. Дотошно парсим эти страницы в поисках заданного в запросе слова или фразы и при каждом его обнаружении выдираем из контекста соседние слова. Это – кандидаты на роль будущих HЧ-кеев. Аккуратно складываем их в список уникальных значений, подсчитывая при этом частоту вхождения. И в завершение определяем приемлемый для себя порог частоты, ниже которого и будут наши низкочастотники. Комбинируя их с первоначальным ключевым словом, получим низкочастотные запросы. Просто? Более чем. И некоторые платные SEO инструменты также работают в соответствии с этим алгоритмом. SERPом по...Прежде чем приступить к написанию программного кода, нужно выяснить все нюансы вывода SERP (Search Engine Result Pages) в окне браузера, а именно – содержание HTTP запроса к поисковому серверу. В Сети можно найти массу HTTP сниферов, как говорится, на любой вкус и цвет. Я остановился на Firefox плагине Live HTTP Headers. Теперь достаточно открыть окно снифера и вбить в адресную строку любой поисковый запрос. После вывода SERP в окне браузера смотрим, что удалось собрать Live HTTP. Включаем логику, удаляем лишнее и изменяем значения ряда параметров по своему усмотрению. GET /search?q=viagra HTTP/1.1 Host: www.google.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12 WebMoney Advisor Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Скорее всего, в полученных параметрах запроса ты решишь подправить данные о локализации браузера и выкинуть cookies. Это по минимуму. В строке GET ты можешь сконструировать любой запрос, соответствующий синтаксису Google (этот вопрос мы уже обсудили). И вот еще что, гринго. На страницах нашего журнала мы то и дело призываем тебя учить мат. часть. В данном случае – это RFC 2616, 2068 и 2965. Все они имеют отношение к HTTP запросам. Если ты до сих пор не знаешь, о чем там идет речь, держи подсказку, которая поможет тебе не наступить на грабли. После всех полей, которые ты будешь включать в HTTP запрос, ОБЯЗАТЕЛЬНО должны следовать два пустых перевода строки. В принципе, ты уже знаешь достаточно, чтобы начать шкодить свой парсер. Но не торопись. Предлагаю еще немного помучить поисковик. Дело в том, что намеченный ранее алгоритм слишком уж очевиден. А это, согласись, как-то не по-хакерски. Попробуем добавить к будущему парсеру щедрую горсть изюма. Очевидный минус пути, по которому идет большинство разработчиков парсеров поисковых систем (и платных парсеров, надо сказать, тоже!), состоит в том, что, собирая ключевые фразы и анализируя ближайшее окружение, мы оцениваем относительную частоту. То есть, пропарсив SERP запроса «Viagra», мы будем оценивать частоту фразы «buy viagra online» не по всему индексу поисковика, а только по полученной ранее выдаче. Другими словами, в большинстве парсеров поисковиков результат оказывается притянутым за уши. Поиск ключевиков — прибыльный бизнесА теперь открой свой любимый браузер, вбей в строку поискового запроса что-нибудь вроде «большие титьки» и обрати внимание на то, что произошло еще до того, как ты нажал на кнопку отправки запроса поисковику. Заметил? Открылось маленькое окошко выдачи поискового результата, в котором, как на блюдечке, представлены наиболее популярные запросы с введенной тобой фразой. И, что в самую мазу, для каждого из них уже посчитано количество вхождений в индекс поисковика! Удивлен? Вот так все просто. Действительно, для того, чтобы добраться до этой интересной функции, нужно отправить поисковый запрос по адресу www.google.com/complete/search. Большинство параметров запроса тебе уже известно. Отдельного упоминания заслуживает разве что такой параметр, как js. Это флаг, указывающий формат вывода: JavaScript или простой текст. Указав в запросе js = false, мы избавляем себя от ненужного нам мусора, получая только самую ценную информацию. Парсер как орудие пролетариатаРазобравшись с построением поисковых запросов, приступим к написанию пасера. Как обычно, для достижения поставленных целей мы будем использовать веб сервисы, написанные на Жабе в среде разработки NetBeans. Создавать веб сервисы ты уже умеешь. Если нет – бегом читать предыдущий номер своего любимого журнала (в этой статье мы лишний раз повторяться не будем). Как ты, наверное, уже догадался, простым методом URL.openStream() воспользоваться не получится. Это связано с тем, что необходимо указывать специфичные параметры HTTP запроса. А это значит – сокеты наше все. С ними и будем работать. Сам же запрос удобно загнать в строковую переменную. Или, если ты стремишься к универсальности, можно читать параметры запроса из файла. В последнем случае твой код будет выглядеть примерно так: byte buf[] = new byte[64*1024]; int r; FileInputStream in = new FileInputStream(fName); r = fis.read(buf); String header = new String(buf, 0, r); fis.close(); После получения строки с параметрами запроса, ее нужно разобрать на отдельные параметры и их значения. Позволю себе предположить, что, если ты читаешь наш журнал, парсинг строки для тебя не будет сложной задачей. Для создания сокета понадобятся два параметра – адрес узла и порт подключения. Для первого используй строковую переменную, а для второго – целочисленную. После того, как ты проинициализировал эти две переменные, можешь создавать сокет. Socket s = new Socket(host, port); Имея готовый сокет, можно приступить к самому главному. А именно, к отправке запроса и получению ответа от поисковика. Этот процесс включает в себя четыре основных этапа:
Поскольку язык программирования Java изначально затачивался под сетевую среду, все перечисленные выше этапы реализуются «как два байта переслать». s.getOutputStream().write(header.getBytes()); InputStream is = s.getInputStream(); FileOutputStream out = new FileOutputStream(outFile); int i = 1; while(i > 0) { i = is.read(buf); if(i > 0) out.write(buf, 0, i); } out.close(); s.close(); } Пока что у нас каша из служебной HTTP информации и выдачи поисковика на полученный им запрос. Чтобы отделить одно от другого, стандартом предусмотрены метки start и end. На них и ориентируйся. Лишнее — отрезать (© Мойша Либерман)Теперь у нас есть выдача поисковика, полученная в обход браузера. А это значит, что, грабя SERP в цикле с разными параметрами, можно серьезно заняться парсингом Google’а (учитывая подводные камни, упомянутые в одной из врезок). Следующий шаг – это извлечение кивордз из выдачи. Но для начала открой награбленную выдачу в текстовом редакторе или в браузере (если ты сливал все в файл), или сбрось значение переменной в консоль (если выдачу ты сохранял в переменной). Что, #?#$&! всякая? А ты кодировочку поменяй. Опять не получается? Ну, тогда смотри еще раз внимательно тот запрос, что мы отправляли через сокет. Там есть такая строка: Accept-Encoding: gzip,deflate Это означает, что мы запросили у сервера данные в сжатом виде. Следовательно, полученный ответ нужно еще и распаковать. Как альтернатива – можно просто удалить из запроса параметр gzip. Но я бы этого делать не советовал. В то, что у тебя халявный трафик, я еще могу поверить. Но, в то, что ты смог хакнуть время, и его теперь у тебя тоже анлим я не поверю никогда. Следовательно, придется получать сжатые данные, а затем их распаковывать. Благо, в Java для этого есть все необходимое в виде пакета java.util.zip. Как это добро работает – смотри ниже. Распаковываем GZip import iava.io.*; import java.util.zip.*; public class ReadGZIP{ public void unzip(String FILENAME){ FileInputStream fin = new FileInputStream(FILENAME); GZIPInputStream gzis = new GZIPInputStream(fin); InputStreamReader xover = new InputStreamReader(gzis); BufferedReader = new BufferedReader(xover); String line; while ((line = is.readLine()) != null) System.out.println(line); } Успешно распаковав HTTP ответ, неплохо было бы избавиться от HTML тегов, которые совершенно не нужны. Если ты кинулся писать свой кодировщик из HTML в TXT или скачивать уже готовый – расслабься и наслаждайся жизнью, задача решается с помощью простейшего регулярного выражения и нескольких строк кода: Pattern p = Pattern.compile("<(.*?)>"); Matcher m = p.matcher(Str); Str = m.replaceAll(""); Конец фильма (© Кто-то из продюсеров)Мы рассмотрели основные ключевые моменты создания парсера для поисковика номер один. За рамками статьи остались некоторые непринципиальные детали, которые достаются тебе в качестве домашнего задания. Напомню основные моменты. Парсим очищенную от мусора выдачу, собирая слова, окружающие наш ключевик. Затем группируем надерганные на предыдущем этапе слова с ключевиком, получая ключевые запросы. После чего проверяем выдачу по каждому запросу с помощью сервиса www.google.com/complete/search. Полученный результат сортируем по выдаче и делаем выводы. Если какие-то моменты непонятны или вызывают затруднение – мыль автору, постараюсь ответить. С удовольствием почитаю и твои идеи по поводу усовершенствования процесса парсинга Google'a! Статистика запросов – это информация об обращениях пользователей к поисковой системе по «ключевым словам». В большинстве случаев при работе с сервисом статистики есть возможность отсеивать результаты по географии или даже по отдельно взятому языку, а иногда и по месяцам. Обычно сервис показывает не только данные об искомом запросе, но также и о словосочетаниях, синонимах и близких темах («ищут также»). На данный момент Google занимает более 70% мирового рынка, а значит, семь из десяти находящихся в сети людей обращаются к его странице в поисках информации в интернете. Google регистрирует около 50 млн. поисковых запросов ежедневно и индексирует более 8 млрд. веб-страниц. Google состоит более чем из 130 тыс. машин, расположенных в разных точках планеты, и может находить информацию на 101-м языке. Этапы составления семантического ядра по Ашаманову
DVDХочешь во всех подробностях знать, как работает Google? Мы приготовили тебе щедрый подарок – подборку патентов поисковика номер один. Более ста документов, более двухсот мегабайт! WWWЭтот адрес должен знать каждый оптимизатор Google SOAP Search API Live HTTP Headers позволит тебе исследовать как GET-, так и POST-запросы Сервис по подбору ключевых слов от Google INFOПри автоматизации Google парсинга настоятельно рекомендуется использовать в алгоритмах тайм-ауты либо работать через несколько прокси серверов. В противном случае при аномальной активности есть риск заработать бан на целые сутки. |