﻿# "Improve your\.\.\. Google?"

Занимаясь разработкой анализатора кода PVS\-Studio для поиска проблем в 64\-битных и параллельных программах, нам понадобилось собирать свежую информацию в сети интернет по некоторым темам\. Например, всегда полезно отвечать в форумах и блогах на вопросы программистов, которым может быть интересен наш инструмент\. В процессе сбора выяснилось, что информации в сети немало и вручную производить поиск весьма долго и утомительно, откуда появилась задача автоматизации поиска свежих данных\. В этой записи мы расскажем, как делаем это\.

Правда, наверняка вы сразу же скажете: "Ха\-ха\! Ребята придумывают велосипед и не знают про Google Alerts"\. Мы знаем про Google Alerts\. Это почти то, что нужно, только не то :\-\)\. За более чем полгода использования Google Alerts, нам так и не удалось добиться от него того, что нужно\. А нужно вот что:

* поиск на конкретных перечисленных сайтах;
* поиск только за последние сутки;
* возможность добавить стоп\-слова;
* Google Alerts как\-то дополнительно фильтрует результаты\. То есть обычный поиск Google дает больше, чем Google Alerts\.

Поэтому и было принято решение, попробовать сделать велосипед\.

В рамках этой задачи требуется искать на заданных сайтах новые материалы в количестве до 30 штук и созданные не дольше чем за 24 часа до начала работы автоматизированного поиска\. То есть, грубо говоря, кто чего написал в интернете за последний день\. Входные данные будут следующие:

* Список адресов сайтов \- url сайтов на которых следует произвести поиск\.
* Список поисковых фраз \- фразы на русском и/или английском языках, по которых следует искать\.
* Список нежелательных слов \- слова, которые должны отсутствовать в результатах поиска\.

## Идея

В сети существует много сервисов предлагающих услуги поиска, логично использовать их возможности для реализации задачи\. Выбран был поисковик google\.com как, на наш взгляд, наиболее подходящий\.

## Поиск в google

Принцип работы тот же, что и у любого другого поисковика: в Google посылается запрос, а он отдает ответ\. При этом поисковик имеет гибкие настройки для формирования запроса, таким образом можно сформировать нужный запрос\.

## Параметры поиска в google

Рассмотрим наиболее интересные \(в рамках задачи\) параметры поиска:

|http://www\\\.google\\\.com/search?|Собственно адрес|
|---|---|
|as\\\_q|Поисковая фраза \\\(именно фраза, а не набор слов\\\)|
|Num|Количество результатов, которые будут показаны на странице|
|as\\\_eq|Слова, которые должны отсутствовать в результатах поиска|
|as\\\_sitesearch|url сайта по которому производится поиск|

У поисковика имеются и другие параметры, но в рамках задачи они неинтересны\. Пример запроса к Google с параметрами поиска:

```cpp
http://www.google.com/search?as_q=64-bit+portability+&
hl=ru&newwindow=1&
num=30&btnG=%D0%9F%D0%BE%D0%
B8%D1%81%D0%BA+%D0%B2+Google&
as_epq=&as_oq=&
as_eq=%D0%BA%D1%83%D0%BF%D0%B8%D1%82%
D1%8C+%D1%81%D0%BA%D0%B0%D1%87%D0%
B0%D1%82%D1%8C+&
lr=lang_ru&cr=&as_ft=i&as_filetype=&
as_qdr=d&as_occt=any&
as_dt=i&as_sitesearch=http://www.codeguru.com/&
as_rights=&safe=images
```

## Как это можно использовать

Из выше написанного следует, что есть возможность автоматизации поиска с использованием поисковой системы Google\. Алгоритм будет следующий:

* На основе исходных данных формируется запрос к Google\.
* Запрос выполняется\.
* Обработка результата \(разбор html\-странички\)\.
* Предыдущие пункты повторить для каждого сайта и каждой поисковой фразы из входных данных\.

## Реализация

Скрипт написан на php\.

## Входные данные

Входных данных имеется три типа, это список url сайтов по которым надо произвести поиск, список поисковых фраз и список слов которые должны отсутствовать в результатах поиска\. Для представления этих данных используется xml файл следующего вида:

```cpp
<?xml version="1.0" encoding="utf-8"?>
<search_params lang="ru">
        <sites>
                <url>http://www.dreamincode.net</url>
                <url>http://forum.vingrad.ru/</url>
                <url>http://forum.sources.ru/</url>
                <url>http://groups.google.com/</url>
        </sites>
        <words>
                <white_list>
                        <phrase>"64-bit" c++</phrase>
                        <phrase>64-bit migration</phrase>
                        <phrase>viva64</phrase>
                </white_list>
                <black_list>
                        <phrase>купить</phrase>
                        <phrase>скачать</phrase>
                </black_list>
        </words>
</search_params>
```

## Разбор XML

XML файл имеет простую структуру и маленький размер, поэтому можно использовать скрипт [PHP Simple HTML DOM Parser](https://simplehtmldom.sourceforge.io/)\.

Применение скрипта описано в документации, но стоит заметить, что приемы использования с DOM очень похожи на то, как это делает JQuery, известная javascript библиотека\. Например, следующий код получает все ссылки с html страницы по адресу google\.com и выводит их на экран:

```cpp
include('../simple_html_dom.php');
// get DOM from URL or file
$html = file_get_html('http://www.google.com/');
// find all link
foreach($html->find('a') as $e)
    echo $e->href . '<br>';
```

Однако есть небольшая проблема с памятью при работе Simple HTML DOM Parser\. Заключается она в следующем: функция file\_get\_html при каждом вызове создает новый объект класса simple\_html\_dom и если эту функцию вызывать в цикле, то память заканчивается\. Освободить принудительно почему\-то не получается\. Решение \- просто не использовать эту функцию в цикле, а вызвать один раз и работать только с одним объектом класса simple\_html\_dom\.

## Создание скрипта

Собственно ничего интересного, обычный скрипт на php,написанный с применением паттерна MVC\. Исходный код также несложен\.

Интерфейс пользователя весьма аскетичен \- при обращении к странице появляется одна кнопка "Отправить запрос" \(в окне браузера\) а после ее нажатия, через некоторое время отображается результат\.

## Итог

После внедрения этого скрипта, теперь мы всегда узнаем, что в мире произошло в нашей предметной области \(64\-битное и параллельное программирование\) за последние сутки\.