Разработал сегодня полуавтоматический процесс сбора ссылок и заголовков страниц сайта для его дальнейшей SEO-оптимизации. Изначально при постановке задачи был предложен ручной метод:
- Заходим на сайт в браузере;
- Копируем URL и заголовок H1 страницы;
- Копируем в таблицу;
- Оформляем внешний вид ячеек к таблице;
- Переходим по любой ссылке;
- Возвращаемся к пункту 2.
И так по всем видимым ссылкам сайта. Представив, сколько времени такой процесс может занять, я решил процесс автоматизировать.
Инструментарий
Для работы с текстовыми файлами всегда рекомендую использовать Notepad++. Быстрая удобная программа с подсветкой кода (при необходимости), которая не испортит содержимое текстового файла независимо от использованной кодировки.
Для сбора заголовков нашел интересную программу, которая умеет парсить заголовки от H1 до H5. Называется «Парсер тайтлов», написал её Дмитрий Борисов, выложив на своем сайте в открытом доступе. У программы есть большой минус — она не умеет самостоятельно обходить сайт по страницам и просит предоставить список ссылок, от которых нужно получить данные.
Так я вышел веб-сервис www.xml-sitemaps.com, который позволяет получить все видимые ссылки сайта.
Получаем данные
Вставляем в поле Starting URL адрес сайта, выставляем значение всех остальных полей в None и жмем Start.
После завершения процесса обработки сайта ищем пункт Download Sitemap in Text Format и нажимаем на ссылку urllist.txt, чтобы скачать набор ссылок в текстовом виде.
Переходим в программу «Парсер тайтлов». Меню Файл — Загрузить URL’ы из файла и выбираем скаченный файл urllist.txt
. Список ссылок отобразится во вкладке URL’ы. Переключаемся на вкладку Настройки. Снимаем галочку Парсить title и ставим галочку Парсить заголовки H1. Жмем кнопку Начать парсинг.
После завершения процесса в меню Файл будет доступен пункт Сохранить в текстовый файл. Жмем на него, задаем имя файла, например, h1list.txt
, нажимаем Сохранить. Теперь у нас есть два файла, в которых соответственно есть списки ссылок и заголовков страниц.
Форматируем данные
Для формирование списка страниц и дальнейшей оптимизации я использую LibreOffice Calc. Я копирую список заголовков и вставляю их в первый столбец листа. Далее мне нужен список ULR’ов без домена.
Для удаления домена из ссылки я использую Notepad++. Копируем в буфер название домена без завершающего слеша, в данном примере это будет http://prof-montage.spb.ru
. Далее меню Поиск — Замена…, в поле Найти вставляем скопированный домен (Ctrl+V), а поле Заменить на оставляем пустым и нажимаем кнопку Заменить все. Полученный список ссылок без начального домена копируем (Ctrl+A, Ctrl+C) и вставляем во второй столбец листа таблицы.
У нас принято следующее оформление списка страниц для оптимизации:
- сначала идет заголовок страницы;
- на следующей строке расположена ссылка на страницу;
- эти две ячейки и две из второго столбца выделяются фоновым цветом.
Для того, чтобы не преобразовывать в ручную полученные два столбца заголовок-URL к принятому формату, я написал небольшой макрос и повесил его на пункт контекстного меню по правому клику мыши. В итоге двумя нажатиями мыши по каждому заголовку я получаю вот такой формат:
Теперь можно уже приступать к оптимизации. Для желающих публикую код макроса:
sub Main rem ---------------------------------------------------------------------- rem define variables dim document as object dim dispatcher as object rem ---------------------------------------------------------------------- rem get access to the document document = ThisComponent.CurrentController.Frame dispatcher = createUnoService("com.sun.star.frame.DispatchHelper") rem ---------------------------------------------------------------------- dispatcher.executeDispatch(document, ".uno:InsertRowsAfter", "", 0, Array()) dispatcher.executeDispatch(document, ".uno:InsertRowsAfter", "", 0, Array()) dispatcher.executeDispatch(document, ".uno:InsertRowsAfter", "", 0, Array()) dispatcher.executeDispatch(document, ".uno:InsertRowsAfter", "", 0, Array()) dispatcher.executeDispatch(document, ".uno:InsertRowsAfter", "", 0, Array()) dispatcher.executeDispatch(document, ".uno:InsertRowsAfter", "", 0, Array()) dispatcher.executeDispatch(document, ".uno:InsertRowsAfter", "", 0, Array()) dispatcher.executeDispatch(document, ".uno:InsertRowsAfter", "", 0, Array()) dispatcher.executeDispatch(document, ".uno:InsertRowsAfter", "", 0, Array()) rem ---------------------------------------------------------------------- dim args2(1) as new com.sun.star.beans.PropertyValue args2(0).Name = "By" args2(0).Value = 1 args2(1).Name = "Sel" args2(1).Value = false dispatcher.executeDispatch(document, ".uno:GoRight", "", 0, args2()) rem ---------------------------------------------------------------------- dispatcher.executeDispatch(document, ".uno:Cut", "", 0, Array()) rem ---------------------------------------------------------------------- dim args4(1) as new com.sun.star.beans.PropertyValue args4(0).Name = "By" args4(0).Value = 1 args4(1).Name = "Sel" args4(1).Value = false dispatcher.executeDispatch(document, ".uno:GoLeft", "", 0, args4()) rem ---------------------------------------------------------------------- dim args5(1) as new com.sun.star.beans.PropertyValue args5(0).Name = "By" args5(0).Value = 1 args5(1).Name = "Sel" args5(1).Value = false dispatcher.executeDispatch(document, ".uno:GoDown", "", 0, args5()) rem ---------------------------------------------------------------------- dispatcher.executeDispatch(document, ".uno:Paste", "", 0, Array()) rem ---------------------------------------------------------------------- dim args7(1) as new com.sun.star.beans.PropertyValue args7(0).Name = "By" args7(0).Value = 1 args7(1).Name = "Sel" args7(1).Value = false dispatcher.executeDispatch(document, ".uno:GoUp", "", 0, args7()) rem ---------------------------------------------------------------------- dim args8(0) as new com.sun.star.beans.PropertyValue args8(0).Name = "By" args8(0).Value = 1 dispatcher.executeDispatch(document, ".uno:GoRightSel", "", 0, args8()) rem ---------------------------------------------------------------------- dim args9(0) as new com.sun.star.beans.PropertyValue args9(0).Name = "By" args9(0).Value = 1 dispatcher.executeDispatch(document, ".uno:GoDownSel", "", 0, args9()) rem ---------------------------------------------------------------------- dim args11(0) as new com.sun.star.beans.PropertyValue args11(0).Name = "BackgroundColor" args11(0).Value = 26112 dispatcher.executeDispatch(document, ".uno:BackgroundColor", "", 0, args11()) rem ---------------------------------------------------------------------- dim args12(0) as new com.sun.star.beans.PropertyValue args12(0).Name = "Color" args12(0).Value = 16777215 dispatcher.executeDispatch(document, ".uno:Color", "", 0, args12()) end sub
Заключение
Я понимаю, что полученный метод далек от идеала, но уже в данном виде позволяет экономить массу времени по сбору подготовительной информации для оптимизации.
В дальнейшем я планирую написать свой веб-сервис, который по заданному адресу сайта будет выдавать набор пар заголовок-URL в табличном виде с опциональным форматированием под принятый у нас стандарт.