Приветствую всех читателей!
Я начал заниматься SEO недавно, и сразу же столкнулся с задачей определения позиций продвигаемых сайтов по ключевым словам в поисковиках. Задача тривиальная и решается на ура различным ПО, которое у всех SEO-специалистов на устах: Semonitor, AllSubmitter, etc. Помимо проприетарности, которой попахивает от всех подобного рода программ, в них есть, как это не парадоксально, ряд технических моментов, из-за которых хочется выбросить компьютер в окно.
Я бы не прочь купить Semonitor, но попользовав демо-версию, решил от этой идеи отказаться — на оф.сайте программы доступная для скачивания версия у меня глючила, требовала обновить себя, а после выпрошенного у меня обновления и вовсе отказывалась заниматься анализом позиций. Самому настроить, как Вы понимаете, нельзя.
AllSubmitter в этом плане получше, позволяет даже кастомизировать регулярные выражения для поисковиков, что вроде как делает этот софт устойчивым к смене формата выдачи, однако и с ним не все слава богу — когда 18.08.2008г. Яндекс вдруг изменил формат выдачи результатов поиска, вместе с тем поменяв и URL ссылок (возможно, эксперименты с вводом учета переходов, подробнее об этом писалось здесь), то и AllSub оказался бессилен. Правда, на следующий день Яндекс снова вернулся к старому формату выдачи, но прецедент, тем не менее, произошел.
Я тогда ради интереса изобретал велосипед: решил написать анализатор позиций, причем на PHP. У меня не было цели дойти до production'а, просто хотелось прочувствовать, как работают всякие там Semonitor'ы и Allsubmitter'ы. А потому, написав классы для парсинга Яши, Гугла и Рамблера, потестив и убедившись, что все пашет, удовлетворенно забыл, поскольку был AllSubmitter, и огород городить было незачем, было предостаточно и других задач.
Когда на Хабре написали про PHP-класс для работы с Яндекс.XML и я обильно прокомментировался по этому поводу, то по наличию плюсов в карму понял, что тема неплоха для оформления в статью, тем более что возможность появилась — я вылез из минусов. И хотя речь там шла немного о другом — об организации поиска по сайту, используя Yandex.XML, задача анализа позиций сайта по ключевым словам и фразам пересекается с первой. Итак, моя задача:
создать анализатор позиций сайтов в выдаче поисковых систем (пока Яндекса)
Тут нету ничего сложного.
все необходимое для получения результатов поиска передается через GET-параметры, а именно:
Шаблон строки запроса:
Выдача Яндекса подвергается разбору на нужные нам составляющие, путем прогона через регулярное выражение вида:
Вот таким путем:
В результате чего получается массив (в нем numdoc элементов) массивов (3 элемента в подмассиве: html с одним результатом выдачи, url найденной страницы выдачи, ее заголовок).
Вот по какой схеме я работаю, чтобы найти сайт в Яндексе по определенному запросу (поиск до первого вхождения):
В качестве параметров к процессу анализа у меня имеется:
это посредством иерархии классов (чтобы при надобности легко расширять функциональность анализатора на другие поисковики).
Хочу обратить Ваше внимание на один момент: не знаю, что это было 18 числа этого месяца сего года, но у Яндекса поменялся формат выдачи, пришлось менять регулярки и дописывать классы, однако уже 19 числа все с изумлением наблюдали то, как яндексоиды возвратили все как было. И, почему бы и нет, это может повториться, потому привожу список изменений и дополнений в класс YandexAnalyzer, которые нужно будет сделать, если вдруг формат выдачи станет как 18.08.2008г.:
Вот небольшой код для тестирования:
и результат тестирования:
4-я позиция сайта vinzavod.ru по фразе «винзавод»
13-я позиция сайта vinzavod.ru по фразе «алкоголь производство»
158-я позиция сайта vinzavod.ru по фразе «производство алкоголя»
45-я позиция сайта vinzavod.ru по фразе «продажа алкоголя»
vinzavod.ru не найден в первых 300 результатах по фразе «производители алкоголя»
181-я позиция сайта vinzavod.ru по фразе «вино»
255-я позиция сайта vinzavod.ru по фразе «вина»
4-я позиция сайта vinzavod.ru по фразе «производство вина»
56-я позиция сайта vinzavod.ru по фразе «продажа вина»
94-я позиция сайта vinzavod.ru по фразе «коньяк»
56-я позиция сайта vinzavod.ru по фразе «коньяки»
7-я позиция сайта vinzavod.ru по фразе «производство коньяка»
5-я позиция сайта vinzavod.ru по фразе «продажа коньяков»
7-я позиция сайта vinzavod.ru по фразе «продажа коньяка»
5-я позиция сайта vinzavod.ru по фразе «продажа коньяк»
11-я позиция сайта vinzavod.ru по фразе «настойка»
17-я позиция сайта vinzavod.ru по фразе «настойки»
3-я позиция сайта vinzavod.ru по фразе «производство настоек»
1-я позиция сайта vinzavod.ru по фразе «продажа настоек»
30-я позиция сайта vinzavod.ru по фразе «вермут»
25-я позиция сайта vinzavod.ru по фразе «вермуты»
32-я позиция сайта vinzavod.ru по фразе «производство вермута»
32-я позиция сайта vinzavod.ru по фразе «портвейн»
15-я позиция сайта vinzavod.ru по фразе «портвейны»
93-я позиция сайта vinzavod.ru по фразе «портвейн 777»
4-я позиция сайта vinzavod.ru по фразе «продажа портвейнов»
Статья готовилась в течении недели, поэтому на момент ее написания уже реализованы анализаторы для Яндекса, Гугла, Рабмлера, и пишется потихоньку приложение. Но это — тема уже следующих постов))
P.S.: Мой первый пост на Хабре, прошу больно не пинать, а конструктивно комментировать))
Я начал заниматься SEO недавно, и сразу же столкнулся с задачей определения позиций продвигаемых сайтов по ключевым словам в поисковиках. Задача тривиальная и решается на ура различным ПО, которое у всех SEO-специалистов на устах: Semonitor, AllSubmitter, etc. Помимо проприетарности, которой попахивает от всех подобного рода программ, в них есть, как это не парадоксально, ряд технических моментов, из-за которых хочется выбросить компьютер в окно.
Я бы не прочь купить Semonitor, но попользовав демо-версию, решил от этой идеи отказаться — на оф.сайте программы доступная для скачивания версия у меня глючила, требовала обновить себя, а после выпрошенного у меня обновления и вовсе отказывалась заниматься анализом позиций. Самому настроить, как Вы понимаете, нельзя.
AllSubmitter в этом плане получше, позволяет даже кастомизировать регулярные выражения для поисковиков, что вроде как делает этот софт устойчивым к смене формата выдачи, однако и с ним не все слава богу — когда 18.08.2008г. Яндекс вдруг изменил формат выдачи результатов поиска, вместе с тем поменяв и URL ссылок (возможно, эксперименты с вводом учета переходов, подробнее об этом писалось здесь), то и AllSub оказался бессилен. Правда, на следующий день Яндекс снова вернулся к старому формату выдачи, но прецедент, тем не менее, произошел.
Я тогда ради интереса изобретал велосипед: решил написать анализатор позиций, причем на PHP. У меня не было цели дойти до production'а, просто хотелось прочувствовать, как работают всякие там Semonitor'ы и Allsubmitter'ы. А потому, написав классы для парсинга Яши, Гугла и Рамблера, потестив и убедившись, что все пашет, удовлетворенно забыл, поскольку был AllSubmitter, и огород городить было незачем, было предостаточно и других задач.
Постановка задачи
Когда на Хабре написали про PHP-класс для работы с Яндекс.XML и я обильно прокомментировался по этому поводу, то по наличию плюсов в карму понял, что тема неплоха для оформления в статью, тем более что возможность появилась — я вылез из минусов. И хотя речь там шла немного о другом — об организации поиска по сайту, используя Yandex.XML, задача анализа позиций сайта по ключевым словам и фразам пересекается с первой. Итак, моя задача:
создать анализатор позиций сайтов в выдаче поисковых систем (пока Яндекса)
Решение
Тут нету ничего сложного.
Во-первых,
все необходимое для получения результатов поиска передается через GET-параметры, а именно:
- text — текст поискового запроса. URL-кодированный.
- p — номер страницы выдачи (p=0, 1, 2...). Without comments
- numdoc — число выдаваемых результатов на страницу(numdoc=10, 20, 30, 50; допустимы только эти значения и никакие более). Для анализа позиций сайта по ключевым словам лучше всего юзать наибольшее значение, т.к. явное уменьшение нагрузки на сервер и, как следствие — меньше подозрений, что «Я, робот»
Шаблон строки запроса:
yandex.ru/yandsearch?text=[KEYWORD]&p=[PAGE_NUMBER]&numdoc=[RESULTS_ON_PAGE]
Во-вторых,
Выдача Яндекса подвергается разбору на нужные нам составляющие, путем прогона через регулярное выражение вида:
#<li>.*<a[^>]*tabindex[^>]*onclick[^>]*=[^>]*"[^>]*"[^>]*href="([^<>"]+)"[^>]*>(.+)</a>.*</li>#Ui
Вот таким путем:
* This source code was highlighted with Source Code Highlighter.
- preg_match_all(РЕГВЫР, HTML_ВЫДАЧИ, МАССИВ_РЕЗУЛЬТАТОВ, PREG_SET_ORDER);
В результате чего получается массив (в нем numdoc элементов) массивов (3 элемента в подмассиве: html с одним результатом выдачи, url найденной страницы выдачи, ее заголовок).
В итоге,
Вот по какой схеме я работаю, чтобы найти сайт в Яндексе по определенному запросу (поиск до первого вхождения):
- получаю первую страницу с выдачей
- если это не «страница недоверия» Яндекса с капчей — прогоняю через регвыр, перебираю результаты в поиске нужного.
- если нахожу, возвращаю результат — номер позиции страницы в выдаче, не нахожу — получаю следующую страницу и возвращаюсь к п.2, подождав секунды 3-5
В качестве параметров к процессу анализа у меня имеется:
- resultsLimit — ограничение по глубине поиска, по умолчанию
люблю ставить 200 - url — имя хоста, который ищем в выдаче. Учитывается любая страница с этого хоста
- keyword — запрос к поисковику.
Реализовано
это посредством иерархии классов (чтобы при надобности легко расширять функциональность анализатора на другие поисковики).
Абстрактный класс — SomeAnalyzer:
* This source code was highlighted with Source Code Highlighter.
- abstract class SomeAnalyzer{
- //// ИНТЕРФЕЙС
- // функция анализа
- public abstract function analyzeThis($url);
- // получение имени хоста из url (parse_url с дополнительным функционалом, поскольку убедился что просто parse_url не всегда почему-то работает, когда url слишком неудобочитаемый)
- public function getHost($url){
- $url=@parse_url($url);
- if($url['path'] && !$url['host'])
- $url['host']=$url['path'];
- $url['host']=ereg_replace("/.*$", "", $url['host']);
- $url['host']=ereg_replace("^www\.", "", $url['host']);
- return $url['host'];
- }
- //// РЕАЛИЗАЦИЯ
- // функция сравнения 2-х url на предмет принадлежности к одному хосту
- protected function compareURL($url1, $url2){
- $url1=$this->getHost($url1);
- $url2=$this->getHost($url2);
- return(strtoupper($url1['host'])==strtoupper($url2['host'])? true: false);
- }
- }
Класс анализатора выдачи Яндекса:
* This source code was highlighted with Source Code Highlighter.
- class YandexAnalyzer extends SomeAnalyzer{
- //// ИНТЕРФЕЙС
- // настройки
- public $resultsLimit=200; // лимит результатов выдачи
- public $url;
- public $keyword;
- public $resultsOnPage=50; // можно только 10, 20, 30, 50
- // функция анализа
- public function analyzeThis($url, $keyword=''){
- $this->url=$url;
- $this->keyword=$keyword;
- $x=0;
- while($x*$this->resultsOnPage<=$this->resultsLimit-1){
- if($results=$this->analyzePage(str_replace(array("\r", "\n", "\t"), '', $this->downloadPage($x)))){
- $results[0]=$x*$this->resultsOnPage+$results[0];
- return $results;
- }
- $x++;
- sleep(rand(3, 5));
- }
- return false;
- }
- //// РЕАЛИЗАЦИЯ
- protected $regexpParseResults='#<li>.*<a[^>]*tabindex[^>]*onclick[^>]*=[^>]*"[^>]*"[^>]*href="([^<>"]+)"[^>]*>(.+)</a>.*</li>#Ui';
- protected $urlMask='http://yandex.ru/yandsearch?text=[KEYWORD]&p=[PAGE_NUMBER]&numdoc=[RESULTS_ON_PAGE]';
- protected function downloadPage($pageNumber){
- $mask=str_replace('[KEYWORD]', urlencode($this->keyword), $this->urlMask);
- $mask=str_replace('[PAGE_NUMBER]', $pageNumber, $mask);
- $mask=str_replace('[RESULTS_ON_PAGE]', $this->resultsOnPage, $mask);
- return file_get_contents($mask);
- }
- protected function analyzePage($content){
- if(preg_match_all($this->regexpParseResults, $content, $matches, PREG_SET_ORDER)!==false){
- if(count($matches)<=0)
- deb('<br /><span style=«color: red;»>Не найдено вхождений или ошибка парсера: возможно гугл подозревает, что Вы робот!</span>');
- else
- foreach($matches as $num=>$match){
- if($this->compareURL($match[1], $this->url))
- return array($num+1, $match[1], $match[2]);
- }
- }
- else deb('<span style=«color: red;»>Не найдено вхождений или ошибка парсера: возможно йандекс подозревает, что Вы робот!</span>');
- return false;
- }
- }
Хочу обратить Ваше внимание на один момент: не знаю, что это было 18 числа этого месяца сего года, но у Яндекса поменялся формат выдачи, пришлось менять регулярки и дописывать классы, однако уже 19 числа все с изумлением наблюдали то, как яндексоиды возвратили все как было. И, почему бы и нет, это может повториться, потому привожу список изменений и дополнений в класс YandexAnalyzer, которые нужно будет сделать, если вдруг формат выдачи станет как 18.08.2008г.:
- строка №30 теперь имеет вид:
- protected $regexpParseResults='#<li>.*<a[^>]*tabindex[^>]*href="([^<>"]+)"[^>]*>(.+)</a>.*</li>#Ui';
- строка №48 также поменялась:
- if($this->compareURL($this->getUrlFromYa($match[1]), $this->url))
- Вы наверно заметили, что в строке №48 используется теперь функция getUrlFromYa? Мало того что поменялся формат выдачи, ссылки стали не прямые, посему понадобилась дополнительная операция извлечение адреса хоста из огромного урла яндекса. Вот код функции, добавьте его в конец класса YandexAnalyzer:
- protected function getUrlFromYa($yaUrl){
- if(preg_match_all('/[\*](http:.*)$/Ui', $yaUrl, $matches, PREG_SET_ORDER)!==false)
- return $matches[0][1];
- return false;
- }
Результат
Вот небольшой код для тестирования:
* This source code was highlighted with Source Code Highlighter.
- $url=«vinzavod.ru»;
- $keywords=array(
- 'винзавод',
- 'алкоголь производство',
- 'производство алкоголя',
- 'продажа алкоголя',
- 'производители алкоголя',
- 'вино',
- 'вина',
- 'производство вина',
- 'продажа вина',
- 'коньяк',
- 'коньяки',
- 'производство коньяка',
- 'продажа коньяков',
- 'продажа коньяка',
- 'продажа коньяк',
- 'настойка',
- 'настойки',
- 'производство настоек',
- 'продажа настоек',
- 'вермут',
- 'вермуты',
- 'производство вермута',
- 'портвейн',
- 'портвейны',
- 'портвейн 777',
- 'продажа портвейнов',
- 'алкоголь',
- 'алкогольная продукция',
- 'фирменный алкоголь',
- 'алкогольные напитки',
- 'классические алкогольные напитки'
- );
- $g=new YandexAnalyzer();
- foreach($keywords as $keyword){
- if($res=$g->analyzeThis($url, $keyword)){
- deb('<span style=«color: green;»>'.$res[0].'-я позиция сайта '.$url.' по фразе <a href="'.$url.'"'.$keyword.'</a>"</span>');
- }
- else
- deb($url.' не найден в первых '.$g->resultsLimit.' результатах по фразе "'.$keyword.'"');
- sleep(rand(3, 5));
- }
и результат тестирования:
4-я позиция сайта vinzavod.ru по фразе «винзавод»
13-я позиция сайта vinzavod.ru по фразе «алкоголь производство»
158-я позиция сайта vinzavod.ru по фразе «производство алкоголя»
45-я позиция сайта vinzavod.ru по фразе «продажа алкоголя»
vinzavod.ru не найден в первых 300 результатах по фразе «производители алкоголя»
181-я позиция сайта vinzavod.ru по фразе «вино»
255-я позиция сайта vinzavod.ru по фразе «вина»
4-я позиция сайта vinzavod.ru по фразе «производство вина»
56-я позиция сайта vinzavod.ru по фразе «продажа вина»
94-я позиция сайта vinzavod.ru по фразе «коньяк»
56-я позиция сайта vinzavod.ru по фразе «коньяки»
7-я позиция сайта vinzavod.ru по фразе «производство коньяка»
5-я позиция сайта vinzavod.ru по фразе «продажа коньяков»
7-я позиция сайта vinzavod.ru по фразе «продажа коньяка»
5-я позиция сайта vinzavod.ru по фразе «продажа коньяк»
11-я позиция сайта vinzavod.ru по фразе «настойка»
17-я позиция сайта vinzavod.ru по фразе «настойки»
3-я позиция сайта vinzavod.ru по фразе «производство настоек»
1-я позиция сайта vinzavod.ru по фразе «продажа настоек»
30-я позиция сайта vinzavod.ru по фразе «вермут»
25-я позиция сайта vinzavod.ru по фразе «вермуты»
32-я позиция сайта vinzavod.ru по фразе «производство вермута»
32-я позиция сайта vinzavod.ru по фразе «портвейн»
15-я позиция сайта vinzavod.ru по фразе «портвейны»
93-я позиция сайта vinzavod.ru по фразе «портвейн 777»
4-я позиция сайта vinzavod.ru по фразе «продажа портвейнов»
Перспективы и планы на будущее
- обуздать как минимум тройку Яндекс, Гугл, Рабмлер.
- сделать человеческую оболочку для пользования, лучший вариант — ajax-приложение, с поддержкой проектов и сохранением на сервере результатов анализов
Статья готовилась в течении недели, поэтому на момент ее написания уже реализованы анализаторы для Яндекса, Гугла, Рабмлера, и пишется потихоньку приложение. Но это — тема уже следующих постов))
P.S.: Мой первый пост на Хабре, прошу больно не пинать, а конструктивно комментировать))