
Мне понадобилось для своих сайтов запускать еженедельную проверку битых и несуществующих ссылок. Потратив пол часа на интернет-серфинг, я нашел несколько достойных консольных приложений (так как сервера у меня на Windows, то хотел использовать для этой задачи TaskSheduler). Все они оказались платные. А так как я мог выделить себе немного свободного времени, и задача на первый взгляд показалась не сложной, решил написать свое.
Отталкиваться решил вот от этой реализации: WebSpider, но, как оно обычно бывает в конечном итоге, почти все переписал, как мне нравится.
Составил себе небольшой список, того, что мне требуется и понемногу вычеркиваю из него таски:
Задача | Описание | Статус |
Рекурсивно собрать все ссылки | Пробежаться по всем страницам в рамках одного сайта и собрать все ссылки | Сделано |
Проверить N ссылок | В основном для отладочных целей, остановиться после проверки N ссылок | Сделано |
Сохранить результат в файл | Сохранение в TXT | Сделано |
Сохранить результат используя html template | Для удобства чтения + прикрутить плагин jquery data table для фильтрации и сортировки | Сделано |
Показывать только ошибки | В файл репорте показывать только битые ссылки | Сделано |
Опция архивирования файла репорта | Добавить поддержку 7zip | Не сделано |
Посылать результат по почте | Добавить поддержку консольного мейлера | Не сделано |
Показывать в репорте редиректы | Правильно обрабатывать все редиректы и выводить информацию о них в репорте | Не сделано |
Добавить логирование | Добавить библиотек Log4Net | Не сделано |
Общая информация о процессе в html темплейте | Показывать когда начался процесс обработки, когда закончился, и другую общую информацию в html темплейте | Не сделано |
Проверить и настроить правильную обработку редиректов | Не сделано | |
app.config конфигурация по умолчанию | Так как стало слишком много параметров для утилиты, решил, что надо сделать конфигурацию по умолчанию из app.config | Не сделано |
Программа простая до безобразия:
1. На вход подается URI, для которого скачивается контент и в контенте ищутся ссылки при помощи регулярного выражения:
public const string UrlExtractor = @"(?: href\s*=)(?:[\s""']*)(?!#|mailto|location.|javascript|.*css|.*this\.)(?<url>.*?)(?:[\s>""'])";
2. Все найденные ссылки, если они относятся к данному сайту, помещаются в хештейбл, где ключ — это абсолютное URI, чтобы не было дублирования.
3. Для каждой ссылки из таблицы хешей мы создаем Request и пытаемся получить Response, и читаем возвращаемый статус:
public bool Process(WebPageState state)
{
state.ProcessSuccessfull = false;
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(state.Uri);
request.Method = "GET";
WebResponse response = null;
try
{
response = request.GetResponse();
if (response is HttpWebResponse)
state.StatusCode = ((HttpWebResponse) response).StatusCode;
else if (response is FileWebResponse)
state.StatusCode = HttpStatusCode.OK;
if (state.StatusCode.Equals(HttpStatusCode.OK))
{
var sr = new StreamReader(response.GetResponseStream());
state.Content = sr.ReadToEnd();
if (ContentHandler != null)
ContentHandler(state);
state.ProcessSuccessfull = true;
}
}
catch (Exception ex)
{
// обработка ошибок todo: сделать отдельные catch блоки
}
finally
{
if (response != null)
{
response.Close();
}
}
return state.ProcessSuccessfull;
}
Все остальное это красивости и энтропия.
Из интересного: использовал для удобного парсинга консольных параметров вот этот пакет https://nuget.org/packages/ManyConsole.
В итоге для обработки параметра, все что от меня требуется это создать вот такой вот класс:
public class GetTime : ConsoleCommand
{
public GetTime()
{
Command = "get-text";
OneLineDescription = "Returns the current system time.";
}
public override int Run()
{
Console.WriteLine(DateTime.UtcNow);
return 0;
}
}
P.S. И В заключении, так как проект пишу для себя и все еще в процессе, то добавил его на github https://github.com/alexsuslin/LinkInspector
Ах, да… кому все-таки интерсно визуально посмотреть что получается в итоге, вот это в консоле:
D:\WORK\Projects\Own\LinkInspector\LinkInspector\bin\Debug>LinkInspector.exe -u www.google.com -n=10 -ff=html -e
Executing -u (Specify the Url to inspect for broken links.):
======================================================================================================
Proccess URI: www.google.com
Start At : 2011-12-21 04:56:09
------------------------------------------------------------------------------------------------------
0/1 : [ 2.98s] [200] : www.google.com
1/7 : [ 0.47s] [200] : accounts.google.com/ServiceLogin?hl=be&continue=http://www.google.by/
2/6 : [ 0.22s] [200] : www.google.com/preferences?hl=be
3/5 : [ 0.27s] [200] : www.google.com/advanced_search?hl=be
4/7 : [ 0.55s] [200] : www.google.com/language_tools?hl=be
5/341 : [ 0.21s] [200] : www.google.by/setprefs?sig=0_OmYw86q6Bd9tjRx1su-C4ZbrJUU=&hl=ru
6/340 : [ 0.09s] [200] : www.google.com/intl/be/about.html
7/361 : [ 0.30s] [200] : www.google.com/ncr
8/361 : [ 0.21s] [200] : accounts.google.com/ServiceLogin?hl=be&continue=http://www.google.com/advanced_search?hl=be
9/360 : [ 0.13s] [200] : www.google.com/webhp?hl=be
------------------------------------------------------------------------------------------------------
Pages Processed: 10
Pages Pending : 0
End At : 2011-12-21 04:56:14
Elasped Time : 0h 0m 5s 456ms
======================================================================================================
или вот это вот скриншот репорта в html темплейте

P.P.S. Попросили скомпилированные бинарники, вот пожалуйста: скачать Link Inspector 0.1 alpha