Битые ссылки являются нежелательными для любого сайта, мы рассмотрим процесс написания скрипта для поиска внешних битых ссылок с помощью языка VBScript и создадим для него форму с помощью объекта WindowSystemObject. Материал данной публикации будет полезен как для оптимизаторов (смогут самостоятельно создать собственный скрипт, а может и несколько, который поможет найти на их блоге, или блогах, исходящие битые ссылки), так и для любителей скриптинга (смогут узнать, как и с помощью каких компонентов сделать обход заданного сайта и найти на нем битые ссылки, или вообще проанализировать интернет ресурс).
Хорошо, а теперь давайте поподробней, что именно будет рассмотрено в данной статье:
- Вкратце рассмотрим определение битых ссылок.
- Определимся с компонентами Chilkat.Spider и WinHttp.WinHttpRequest, WindowSystemObject
- Протестируем наш сценарий, после чего, сделаем форму с нужными полями и кнопками.
- Рассмотрим некоторые нюансы при поиске битых ссылок и обходе страниц сайта.
И так, вступление готово, теперь можно переходить к практической теории, начнем.
Битые ссылки
Любая ссылка, как в глазах поисковой системы, так и в глазах пользователя – это указатель на то, что сюда можно или стоит перейти, и в теории, произойдет попадание на новую страницу сайта или другой сайт. Если же поисковая система или пользователь перейдет по указателю, а в результате “Ресурс не найден”, то произойдет банальный обмана, а ведь никто не любит быть обманутым. Это собственно и есть битая ссылка – линк, который ведет в никуда. Как вы поняли, битыми могут быть как внутренние, так и внешние ссылки, первые — вы удалили статью или документ, а указатель на них остался, вторые – в основном это линки в комментариях или постовых на ресурсы, которые давным-давно канули в небытие.
Пакуем сумку с компонентами для поиска битых ссылок
Давайте освежим немного память, компоненты системы (ActiveX, COM и так далее) – это своеобразные файлы-библиотеки, в которых прописаны функции и переменные, любое приложение или язык программирования (если они это умеют) может создать в памяти копию нужного компонента и использовать его функционал по своему усмотрению, так, например, работает пакет Microsoft Office. Компонентов много, одни позволяют работать с файловой системой, вторые с оболочкой Windows, а третьи с сетевыми ресурсами, одно слово – их много. Сервер сценариев Windows Script Host хорош тем, что предоставляет не только собственные объекты, но и может подключать чужие. ЭТО ВАЖНО!!!! СТОРОННИЙ ОБЪЕКТ БУДЕТ ДОСТУЕН ТОЛЬКО ПОСЛЕ ТОГО, КАК БУДЕТ ЗАРЕГИСТРИРОВАН В РЕЕСТРЕ. Нам понадобятся только три компонента:
Chilkat.Spider – позволит создать собственного “паука” для обхода сайта, является сторонним и требует предварительной установки – регистрации в системе.
WinHttp.WinHttpRequest – позволят отправлять HTTP запрос по найденной внешней ссылки, если в ответ мы получим ошибку 404 (ресурс недоступен), то указатель примет статус битой ссылки. Данный объект (как правило) уже присутствует в системе и не нуждается в дополнительной установке.
Scripting.FileSystemObject – встроенные объект сервера Windows Script Host, нужен для создания текстового файла, куда будут записываться битые ссылки.
Scripting.WindowSystemObject — позволит создать форму с нужными полями и кнопками.
Для регистрации компонента у вас должны быть права администратора (в добавок, для успешного написания сценариев, должен быть установлен сервер сценариев Windows Script Host), далее прописываем в командной строке, или в меню Пуск/Выполнить: REGSVR32 “Путь к компоненту”. ЭТО ВАЖНО!!! ПЕРЕМЕЩЕНИЕ КОМПОНЕНТА СДЕЛАЕТ ЕГО НЕДОСТУПНЫМ ДЛЯ ВЫЗОВА ИЗ ТЕЛА СКРИПТА.
Делаем разминку с VBScript
Прежде чем рассматривать наш пример, давайте определимся с алгоритмом его работы. Сначала с помощью цикла for мы будем пробегаться по внутренним ссылкам заданного сайта, в процессе, уже встроенный цикл for будет пробегаться по внешним ссылкам, если ссылка недоступна – код ответа 404, то присваиваем ей статус БИТАЯ ССЫЛКА. Заданная переменная будет хранить список битых ссылок и адрес страницы, на которой они находятся, в самом конце произойдет запись отчета в текстовый документ.
И так, открываем Notepad++ и прописываем в нем следующий код, дадим скрипту название bad_links.vbs. Смотрим на пример:
' *********************************************************** ' bad_links.vbs ' Поиск внешних битых ссылок - разминка ' Сайт автора scriptcoding.ru ' *********************************************************** Option Explicit Dim fso, outFile, spd, objWINHTTP, pages, success, url, links, a, bad_list, bad_links_list, i, objXSHTTP 'Подключаем объекты Set fso = CreateObject("Scripting.FileSystemObject") Set outFile = fso.CreateTextFile("bad_links.txt", True) set spd = CreateObject("Chilkat.Spider") Set objWINHTTP = CreateObject("WinHttp.WinHttpRequest.5.1") 'Задаем начальный домен spd.Initialize "scriptcoding.ru" 'Добавляем URL адрес для исследования spd.AddUnspidered "https://scriptcoding.ru/" 'Исключаем заданные адреса из проверки spd.AddAvoidPattern "feeds.feedburner.com*" spd.AddAvoidPattern "www.liveinternet.ru*" spd.AddAvoidPattern "twitter.com*" spd.AddAvoidPattern "www.facebook.com*" 'Задаем количество страниц pages=5 'Считываем внутренние ссылки сайта For i = 0 To pages 'Включаем обработку ошибок On Error Resume Next 'Переходим к следующей странице success = spd.CrawlNext() If (success = 1) Then 'Считываем внешние ссылки сайта For a = 0 To spd.NumOutboundLinks - 1 'Присваиваем переменной url адрес текущей ссылки url = spd.GetOutboundLink(a) 'Инициализируем HTTP-запрос, тут false - синхронный запрос (ждем ответа) objWINHTTP.open "GET", url, false 'добавление HTTP-заголовка objWINHTTP.SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MyApp 1.0; Windows NT 5.1)" 'Отправляем запрос objWINHTTP.send 'Проверяем код ответа If (objWINHTTP.status = 404) Then 'Записываем в переменную адреса битых ссылок bad_links_list=bad_links_list & url & VBCrLf end if Next 'Если список не пустой - заносим битые ссылки в список if bad_links_list <> "" then bad_list=bad_list & "Адрес: " & spd.LastUrl & VBCrLf & "Битые ссылки " & VBCrLf & bad_links_list & VBCrLf end if 'Обнуляем найденные линки spd.ClearOutboundLinks() bad_links_list="" Else ' Условие возникновения ошибки, или закончился обход If (spd.NumUnspidered = 0) Then MsgBox "Адрес отсутствует" Else ' Информацию об ошибке MsgBox spd.LastErrorText End If End If 'Ожидание в 1 секунду до перехода к следующему URL spd.SleepMs 1000 Next 'Не пустой ли список if bad_list <> "" then 'Записываем в файл наш список битых ссылок outFile.WriteLine(bad_list) end if ' Закрываем открытый файл outFile.Close MsgBox "Обход адресов закончен" |
Если посмотреть на наш пример, то мы видим, что пользователю надо вручную задать количество страниц и сам адрес исследуемого сайта. Плюс, тут стоит обратить внимание на строку spd.AddAvoidPattern, с ее помощью мы можем добавить те адреса, которые не хотим проверять на статус битой ссылки. Дело в том, что на многих ресурсах есть различные значки социальных сетей (Вконтакте, Одноклассники и так далее), тратить на них время нет смысла, тут URL исключается с помощью постановочных знаков (* — любое количество символов и ? – один любой символ).
У скрипта есть один изъян, дело в том, что в зависимости от исследуемого сайта, надо исключить и внутренние ссылки (указатель в комментариях – Ответить, архивы или рубрики статей, собственно, все то, что мы прописываем в Robots.txt для запрета на индексацию поисковыми системами).
Создаем форму для сценария
Если мы запустим наш скрипт, то визуально ничего не произойдет, и о том, работает или нет наше творение, мы сможем узнать, лишь если заглянем в диспетчер задач и увидим процесс wscript.exe. Что бы придать форму нашему творению, я прибегну к помощи объекта WindowSystemObject. Давайте посмотрим на синтаксис сценария в целом, а потом разберем, что в нем изменилось, файл сохраним под новым именем bad_links_full.vbs:
' *********************************************************** ' bad_links_full.vbs ' Поиск внешних битых ссылок ' Сайт автора scriptcoding.ru ' *********************************************************** 'Создаем экземпляр объекта set wso = CreateObject("Scripting.WindowSystemObject") 'Задаем начальные размеры и отступы set f = wso.CreateForm(0,0,0,0) 'Задаем через свойства ширину и высоту f.ClientWidth = 500 f.ClientHeight = 500 'Центрируем форму f.CenterControl() 'Заголовок окна f.Text = "Поиск битых ссылок" 'нельзя менять размеры f.SizeGrip = false 'нельзя развернуть форму f.MaximizeBox = false MSG="Автор:Владимир Баталий" & vbCrLf &_ "Поиск внешних битых ссылок для заданого сайта" set t = f.CreateHyperLink(10,10,250,20,"scriptcoding.ru") f.TextOut 10,30,MSG f.TextOut 350,65,"имя домена" set my_site =f.CreateEdit(350,85,125,20,wso.Translate("ES_MULTILINE")) my_site.Text = "scriptcoding.ru" f.TextOut 350,125,"число страниц" set pages = f.CreateEdit(350,145,124,20,wso.Translate("ES_MULTILINE")) 'Задаем тип вводимых данных pages.DataType=wso.Translate("DT_INTEGER") pages.Text="100" set Button = f.CreateButton(350,180,125,25,"Поиск") 'Компонент список set list_links = f.CreateEdit(5,70,300,400,wso.Translate("ES_MULTILINE")) list_links.ScrollBars = wso.Translate("SS_BOTH") list_links.ReadOnly = true list_links.WordWrap = true 'Вызов функции Bad_Links после нажатия на кнопку Button.OnClick = GetRef("Bad_Links") 'метод делает форму видимой f.Show() 'Запуск встроенного цикла обработки сообщений, он будет продолжаться до тех пор, пока видна какая либо форма или до вызова метода Stop. wso.Run() Sub Bad_Links On Error Resume Next Set fso = CreateObject("Scripting.FileSystemObject") Set outFile = fso.CreateTextFile("badlinks.txt", True) set spd = CreateObject("Chilkat.Spider") Set objWINHTTP = CreateObject("WinHttp.WinHttpRequest.5.1") spd.Initialize my_site.Text spd.AddUnspidered "http://" & my_site.Text & "/" spd.AddAvoidPattern "*" & my_site.Text & "/*/*reply*" spd.AddAvoidPattern "feeds.feedburner.com*" spd.AddAvoidPattern "www.liveinternet.ru*" spd.AddAvoidPattern "twitter.com*" spd.AddAvoidPattern "www.facebook.com*" list_links.Text="Идет поиск битых ссылок. ЖДИТЕ..." MsgBox "Идет поиск битых ссылок. ЖДИТЕ..." For i = 0 To CStr(pages.text) success = spd.CrawlNext() If (success = 1) Then 'Считываем внешние ссылки сайта For a = 0 To spd.NumOutboundLinks - 1 url = spd.GetOutboundLink(a) objWINHTTP.open "GET", url, false objWINHTTP.SetRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MyApp 1.0; Windows NT 5.1)" objWINHTTP.send 'Проверяем код ответа If (objWINHTTP.status = 404) Then ' анализ ответа сервера bad_links_list=bad_links_list & url & VBCrLf end if Next if (bad_links_list <> "") then bad_list=bad_list & "Адрес: " & spd.LastUrl & VBCrLf & "Битые ссылки " & VBCrLf & bad_links_list & VBCrLf end if spd.ClearOutboundLinks() bad_links_list="" Else ' Условие возникновения ошибки, или закончился обход If (spd.NumUnspidered = 0) Then 'Количество страниц сканируемых страниц закончелось MsgBox "Конец списка" 'Выходим из цикла Exit for Else ' Информацию об ошибке MsgBox spd.LastErrorText End If End If ' Ожидание в 1 секунду до перехода к следующему URL spd.SleepMs 1000 Next if (bad_list="") then bad_list="Поздравляю, битых ссылок нет" if (bad_list<>"") then list_links.text = bad_list outFile.WriteLine(bad_list) outFile.Close MsgBox "Сканирование завершено!!!" End Sub |
Тут мы можем заметить, что в списке исключенных появилась строчка
spd.AddAvoidPattern «*» & my_site.Text & «/*/*reply*»
тут my_site.Text информация, которую мы прописываем в текстовом поле (адрес сайта), а *reply* — текст, по которому будет определяться внутренний URL, который надо игнорировать, при желании, можно добавить и адреса категорий и архивов. Вся загвоздка в том, что если этого не сделать, то сценарий просто будет тратить лишнее время на поиск битых внешних ссылок.
Цель данной публикации – пробудить у вас интерес к созданию собственных скриптов и развитию идей. Поиск битых ссылок – лишь один из возможных вариантов для реализации возможностей сервера Windows Script Host. И, честно говоря, сам пример нуждается в доработке, так как, если ресурс существует, но долго грузится, то программа посчитает его за битую ссылку. На этом всё, подписывайтесь на новые статьи, и жду ваших отзывов о статье.
Владимир хотелось бы подробнее как-то. Где взять WinHttp.WinHttpRequest ? И как запустить файл с расширением .mf не понятно. У меня на компе такие файлы ни с чем не ассоциируются.
Александр, что бы запустить файл с расширением .mf надо установить приложение LangMF.exe (оно позволяет создавать форму для нашего скрипта, хотя, компонент WindowsSystemObject для этого тоже подходит) Относительно WinHttp.WinHttpRequest — операционная система сама его предоставляет, но, я решил на всякий случай написать статью «Компоненты для создания HTTP запроса» в ней есть описание основных методов и свойств и сам архив с компонентами, но, для надежности вот прямая ссылка на архив. Вы так же можете самостоятельно проверить, зарегистрирован ли компонент в системе, для этого запустите реестр Windows (Пуск/Выполнить regedit) и просто вбейте в поиск имя компонента. Если компонент отсутствует, то его придется зарегистрировать, для этого запускаем Пуск/Выполнить REGSVR32 «Путь к компоненту». Также не забудьте, что для поиска битых ссылок вам придется установить компонент Chilkat.Spider.
Спасибо! Уже лучше. Все скачал зарегистрировал. Буду экспериментировать. Есть еще вопрос. Где взять начальные шаблоны указанные в example_1.mf? Может я еще не все прочитал? В Нотпаде я что-то не нашел как создать первичный шаблон для таких типов файлов.
Если честно, то я просто храню заготовки с примерами, и если надо написать новый скрипт, просто открываю заготовку и добавляю нужный код. Насчет Notepad++ как то не вникал в возможность добавления начального шаблона, обязательно разберу этот момент, и напишу по этому поводу статью, спасибо за идею.
P.S Насчет предыдущего. Имеется ввиду есть ли в Нотпаде или в других программах начальные шаблоны как для php в Дримвивере и т.п. Пишете интересные статьи. Благодарю.
Я переделал пример, вместо приложения LangMF применил компонент WindowSystemObject, так практичней