Скрипт для поиска внешних битых ссылок

Скрипт для поиска внешних битых ссылок Примеры скриптов и макросов для Word и WSH

Битые ссылки являются нежелательными для любого сайта, мы рассмотрим процесс написания скрипта для поиска внешних битых ссылок с помощью языка 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 исключается с помощью постановочных знаков (* — любое количество символов и ? – один любой символ).

Поиск битых ссылок с помощью LangMF

У скрипта есть один изъян, дело в том, что в зависимости от исследуемого сайта, надо исключить и внутренние ссылки (указатель в комментариях – Ответить, архивы или рубрики статей, собственно, все то, что мы прописываем в 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. И, честно говоря, сам пример нуждается в доработке, так как, если ресурс существует, но долго грузится, то программа посчитает его за битую ссылку. На этом всё, подписывайтесь на новые статьи, и жду ваших отзывов о статье.

Оцените статью
Технологии программирования и ведение блога
Добавить комментарий для Coding Отменить ответ

  1. Александр

    Владимир хотелось бы подробнее как-то. Где взять WinHttp.WinHttpRequest ? И как запустить файл с расширением .mf не понятно. У меня на компе такие файлы ни с чем не ассоциируются.

    Ответить
    1. Coding автор

      Александр, что бы запустить файл с расширением .mf надо установить приложение LangMF.exe (оно позволяет создавать форму для нашего скрипта, хотя, компонент WindowsSystemObject для этого тоже подходит) Относительно WinHttp.WinHttpRequest — операционная система сама его предоставляет, но, я решил на всякий случай написать статью «Компоненты для создания HTTP запроса» в ней есть описание основных методов и свойств и сам архив с компонентами, но, для надежности вот прямая ссылка на архив. Вы так же можете самостоятельно проверить, зарегистрирован ли компонент в системе, для этого запустите реестр Windows (Пуск/Выполнить regedit) и просто вбейте в поиск имя компонента. Если компонент отсутствует, то его придется зарегистрировать, для этого запускаем Пуск/Выполнить REGSVR32 «Путь к компоненту». Также не забудьте, что для поиска битых ссылок вам придется установить компонент Chilkat.Spider.

      Ответить
      1. Александр

        Спасибо! Уже лучше. Все скачал зарегистрировал. Буду экспериментировать. Есть еще вопрос. Где взять начальные шаблоны указанные в example_1.mf? Может я еще не все прочитал? В Нотпаде я что-то не нашел как создать первичный шаблон для таких типов файлов.

        Ответить
        1. Coding автор

          Если честно, то я просто храню заготовки с примерами, и если надо написать новый скрипт, просто открываю заготовку и добавляю нужный код. Насчет Notepad++ как то не вникал в возможность добавления начального шаблона, обязательно разберу этот момент, и напишу по этому поводу статью, спасибо за идею.

          Ответить
  2. Александр

    P.S Насчет предыдущего. Имеется ввиду есть ли в Нотпаде или в других программах начальные шаблоны как для php в Дримвивере и т.п. Пишете интересные статьи. Благодарю.

    Ответить
    1. Coding автор

      Я переделал пример, вместо приложения LangMF применил компонент WindowSystemObject, так практичней

      Ответить