Итак, в начале коротко о последних событиях в блоге.
Первое событие — у блога появился новый автор — SeregaAltmer, так что теперь я не одинок :). Первый пост нового автора Вы можете прочитать уже сейчас.
Таким образом, вдвоем мы постараемся освещать более широкий круг вопросов программирования в Delphi.
Второе событие, которое я, признаться не ожидал, заключается в том, что в ближайшее время будет разработана новая версия «Хронометра» с учетом всех предложений, пожеланий и баг-репортов. Так что, если у Вас есть что предложить по поводу программы — милости прошу в тему или пишите на email — vlad383@mail.ru. Вообще программа создавалась «под себя» и отчасти ради интереса «смогу или нет», но раз есть интерес к продукту — будем развивать дальше. Ну, а теперь по теме топика. Сегодня рассмотрим новый компонент для Delphi 2010 — SearchCatalogs, который предназначен для определения нахождения сайта в каталогах: Яндекс.Каталог, DMOZ и Yahoo Directory — трех крупнейших каталогах сайтов в Интернет. Думаю, что подобный компонент будет очень кстати разработчикам программ по аудиту сайтов.
1. Пара слов о поиске в каталогах.
В начале рассмотрим простой вопрос — как вообще проводится поиск в каталогах. Провести поиск вручную проблем не составит ни для кого — ввел URL в поле поиска, нажал кнопку — получил результат. А программно? Естественно при программном поиске сайта в каталогах не обойдется без применения RegExp и регулярных выражений. Можно было бы, конечно, поковыряться в DOMе, по-вытаскивать необходимые теги, по-разбирать содержимое и т.д., но на мой взгляд, это лишнее и можно обойтись более простыми способами. Достаточно знать URL страницы с результатами поиска каталога и применить RegExp и дело в шляпе. Рассмотрим как это можно сделать на примере выбранных каталогов.
Яндекс.Каталог
Заходим в каталог и записываем в поле поиска любой сайт, например webdelphi.ru, жмем поиск и получаем следующий результат:
Как видите блог отсутствует в каталоге. Какую информацию мы можем вытащить с этой странички? Я думаю, что если функция поиска будет работать «от противного», т.е. определять отсутствие сайта в каталоге, то здесь можно воспользоваться titl’ом странички, который кстати сказать довольно просто вытаскивается со страницы хоть через TWebBrowser, хоть напрямую из DOM, хоть с помощью RegExp:
<title>Яндекс.Каталог:webdelphi.ru (0)</title>
То есть вытаскиваем титл, читаем число скобках и, если число отлично от нуля, то сайт находится в каталоге. Можно воспользоваться и другими способами, например искать не число в скобках, а подстроку, которая выдается на странице поиска в том случае, если сайт обнаружен в Яндекс.Каталог. Регулярное выражение для этого случая может быть таким:
'.*(?:сайт).*?(d+)'
SearchCatalogs работает с Яндекс.Каталогом именно с помощью этого регулярного выражения. Какой из способов будет удобно использовать Вам, в случае самостоятельной работы с этим каталогам решать Вам, мне остается только сказать, что URL необходимой для работы странички Яндекс.Каталога выглядит вот так (для использования в Delphi):
'http://search.yaca.yandex.ru/yandsearch?text=%s&&rpt=rs2';
Вместо %s подставляете домен и можете качать страничку результатов поиска.
DMOZ
Строка URL страницы результатов поиска для DMOZ выглядит следующим образом:
'http://search.dmoz.org/cgi-bin/search?search=%s
В случае, если сайт не найден в каталоге, страничка будет снаружи выглядеть вот так:
На рисунке также отмечена подстрока, которую можно искать для определения нахождения сайта в каталоге.
Единственное, что немного осложняет поиск — наличие гиперссылки в подстроке. Но мы же знаем (или делаем вид, что знаем), что такое RegExp! Составляем простенькое регулярное выражение:
'.*?No.*?results.*?found'
То есть ищем подстроку в которой встречаются подстроки No, Results, found, разделенные любыми другими символами. В нашем случае этими «любыми» символами будет как раз html-код ссылки. Нашли подстроку — значит сайта в каталоге нет.
Yahoo Directory
Целевой URL:
'http://search.yahoo.com/search/dir?p=%s'
При работе с Yahoo Directory, также как и с DMOZ наиболее целесообразно парсить страничку на предмет отсутствия сайта в каталоге.
Смотрите как красиво и просто выглядит целевая подстрока:
Здесь даже RegExp не нужен — поискали соответствие в тексте тем же pos() и все становится предельно ясно.
С поиском разобрались. А теперь переходим непосредственно к компоненту.
2. Свойства, методы и события компонента SearchCatalogs
У компонента SearchCatalogs определены следующие свойства:
Domain: string — домен для проверки наличия в каталогах.
Options — группа из трех свойств:
- Yandex: boolean — определять наличие сайта в Яндекс.Каталог
- YahooDir: boolean — определять наличие сайта в Yahoo Directory
- DMOZ: boolean — определять наличие сайта в DMOZ
Active: boolean — свойство «только для чтения» определяет выполняются ли в текущий момент какие либо операции в компоненте.
А также три свойства для чтения:
InYandex: boolean — если true, то сайт находится в Яндекс.Каталоге
InDMOZ: boolean — то же самое, но для DMOZ
InYahoo: boolean — то же самое для Yahoo Directory.
После того, как необходимые значения свойств установлены, запустить в работу компонент можно, использовав метод Activate.
Соответственно, для прерывания работы используется второй метод — Deactivate.
После выполнения метода Activate запускаются в работу 3 параллельных потока, каждый из которых выполняет работу с одним из каталогов.
Для того, чтобы отслеживать ход выполнения всех операций в SearchCatalogs реализованы следующие события:
OnStartYandex — был запущен поток для Яндекса
OnStartDMOZ — был запущен поток для DMOZ
OnStartYahooDir — был запущен поток для Yahoo Directory
OnGiveYandex — успешно получены данные о сайте в Яндекс.Каталоге
OnGiveDMOZ — успешно получены данные о сайте в DMOZ
OnGiveYahoo — успешно получены данные о сайте в Yahoo Directory
OnStopYandex — работа потока Яндекса прервана
OnStopDMOZ — работа потока DMOZ прервана
OnStopYahooDir — работа потока Yahoo прервана
OnAcceptData — были успешно получены данные от одного или нескольких потоков. Событие удобно использовать для вывода информации «на лету».
Конечно, подобное количество копипаста может быть лишним. Например все эти события можно было ужать всего в три-четыре штуки, но вот такой вот я разгильдяй, люблю копипастить собственный код :) Да и по-моему, так проще отследить каждый поток в отдельности.
Так как про установку компонентов для Delphi 2010 я уже писал не один раз, то не буду повторяться и переходим сразу к реализации тестового приложения с использованием компонента.
3. Пример работы компонента SearchCatalogs
Заготовка для будущего приложения у меня получилась следующая:
Всё предельно просто (тем более, что это просто пример, а не продукт для реализации за деньги через интернет) — одно поле ввода для домена, две кнопки одна из которых запускает компонент в работу, а вторая прерывает потоки и куча label’ов для вывода информации. Для включения/выключения опций предусмотрены три чекбокса.
Работать приложение будет следующим образом — записываем в поле адрес домена, выбираем необходимые каталоги, жмем кнопку и покорно ждем результат или прерываем потоки, если терпение лопнуло или возникли проблемы с Интернет-соединением.
Листинг всей программы также прост как и интерфейс (привожу только обработчики событий):
procedure TForm1.Button1Click(Sender: TObject); begin SearchCatalogs1.Domain:=Edit1.Text; Edit1.Text:=SearchCatalogs1.Domain; SearchCatalogs1.Options.Yandex:=CheckBox1.Checked; SearchCatalogs1.Options.DMOZ:=CheckBox2.Checked; SearchCatalogs1.Options.YahooDir:=CheckBox3.Checked; SearchCatalogs1.Activate; end; procedure TForm1.Button2Click(Sender: TObject); begin SearchCatalogs1.Deactivate; end; procedure TForm1.SearchCatalogs1AcceptData(InYandex, InDMOZ, InYahooDir: Boolean); begin SearchCatalogs1GiveDMOZ(InDMOZ); SearchCatalogs1GiveYahoo(InYahooDir); SearchCatalogs1GiveYandex(InYandex); end; procedure TForm1.SearchCatalogs1GiveDMOZ(InDMOZ: Boolean); begin if InDMOZ then label8.Caption:='есть' else label8.Caption:='нет'; label5.Caption:='отработал'; end; procedure TForm1.SearchCatalogs1GiveYahoo(InYahooDir: Boolean); begin if InYahooDir then label9.Caption:='есть' else label9.Caption:='нет'; label6.Caption:='отработал'; end; procedure TForm1.SearchCatalogs1GiveYandex(InYandex: Boolean); begin if InYandex then label7.Caption:='есть' else label7.Caption:='нет'; label4.Caption:='отработал'; end; procedure TForm1.SearchCatalogs1StartDMOZ; begin label5.Caption:='запущен' end; procedure TForm1.SearchCatalogs1StartYahooDir; begin label6.Caption:='запущен' end; procedure TForm1.SearchCatalogs1StartYandex; begin label4.Caption:='запущен' end; procedure TForm1.SearchCatalogs1StopDMOZ; begin label5.Caption:='остановлен' end; procedure TForm1.SearchCatalogs1StopYahooDir; begin label6.Caption:='остановлен' end; procedure TForm1.SearchCatalogs1StopYandex; begin label4.Caption:='остановлен' end;
Теперь собираем приложение, запускаем и любуемся результатом. Три потока шустро скачут по трем каталогам и выдают результат.
Привет, если в дельфи ставить с твоим компонентом поисковая статистика то ставиться только один а второй глохнет, используется похоже одинаковые файлы, как бы иправить это?
Скажи какую версию Delphi используешь и какие компоненты вместе не работают? В ближайшее время сделаю один пакет для установки
Запускаю все на Embarcadero RAD Studio 2010
Мне требуются в одном проекте чтобы работало:
SearchCatalogs
searchstats
DomainAge
Получается работает только один из компонентов, второй и третий не ставяться, одновременно с первым, по отдельности все ок.
П.С в searchstats не работает парсер рамблера, еще читал где то что ты писал как получить PR сайта от гугла, но так и не получилось сделать как в твоей заметке, не мог бы ты добавить это в компонент yatic
Пакет компонентов соберу к выходным..странно, но у меня все три компонента работают на Delphi 2010. Проверю,что там не так.
Парсер Рамблера не работает в смысле не парсит вообще или парсит, но не то? :)
С Гуглом было два варианта — через Java Script и напрямую через тулбар, но почему-то сейчас оба варианта корректно отображают PR только для сайтов с PR=10. Если смогу эту проблему побороть, то в обновленный пакет всё и уложу
Я так подумал что из за того что во всех пакетах есть одинаковый файл, на него и ругается, что уже используется: InetThread
про рамблер не парсит если страниц в нем больше 1000, скорее всего из за пробела который там, например в индексе 1 500 страниц и ошибка строковая.
Спасибо, жду решений =)
Понятно. Не учел я пробелы…зря :) К выходным, думаю, управлюсь
Отлично буду ждать, что получилось…
Вроде бы всё готово. Пакет состоит из 4х компонентов: YaTIC, DomainAge, SearchStat, SearchCatalogs. Ставится без проблем. На всякий случай в архиве есть bpl и dcp файлы + все исходники (если потребуется что-то исправить «под себя»). У рамблера добавлена функция удаления пробелов. Скачать архив можно со страницы с исходниками
Спасибо, все встало, единственно не работает рамблер, если страниц до 1000 то все ок, если больше он определяет 4 страницы вместо 4000 или 1 вместо 1500
С рамблером надо, блин разбираться…Попробую ещё раз все внимательно просмотреть и исправить
За массовую проверку параметров по идее бана быть не должно, т.к. в потоках по умолчанию стоят достаточно большие задержки перед запросами. Я бы сделал так — сделал цикл на проверку, например 3-4 сайтов и отследил в браузере банят меня или нет. Если банят, то просто увеличил бы задержку между запросами или научился бы юзать прокси — с ними точняком всё пройдет
Можешь еще подсказать, каким образом лучше всего организовать массовую проверку параметров? в цикле получается, но параметров не один, не могу разобраться? Не будет ли бана за такое?