Немного теории SEO Давай для начала отбросим всю шелуху и заглянем в самую суть поисковой оптимизации. Ее основная цель – сделать веб-сайт видимым для поисковой системы и вывести на верхние позиции в результатах поиска по тем или иным запросам. Оставим на некоторое время алгоритмы работы поисковых систем в стороне и посмотрим на задачу более широко. Представь, что по пути из пивного ларька домой к тебе подбежал какой-то баклан в зеленом жилете и вручил бумажный листок странного вида. Бегло пробежав его глазами, ты понимаешь, что это очередная рекламная замануха от расположенного в соседнем квартале магазина «Колорадо». Внимание, вопрос: на основании чего ты квалифицировал этот текст именно таким образом? Правильный ответ: на основании определенных слов и словосочетаний, встреченных тобой в тексте. Допустим, это будут слова «скидки», «china», «лох», «кредит», «лучшая цена». Теперь возьмем этот же набор слов и в случайном порядке вставим их в произвольно выбранные места моей любимой книги «Война и мир». Легким движением руки мы превратили бессмертное произведение в рекламу магазина, продающего всякий трэш. Но не так-то просто вымарать классиков! После эксперимента по скрещиванию «Войны и мира» с рекламным мусором Наташа Ростова не стала кассиром-операционистом №6. Мы по-прежнему имеем легко узнаваемое произведение, в котором иногда встречаются странные баги в виде слов «скидки», «колорадо» и т.д. Что произошло со словесной диареей маркетологов? Почему мы теперь не воспринимаем ее как таковую? Ответ очевиден – она просто растворилась в огромном объеме другой информации. Исходя их этого, можно сделать ценные выводы. Во-первых, в любом осмысленном тексте есть определенные ключевые слова, по которым можно определить его контекстное поле (то есть его основную тематику). Во-вторых, для того чтобы это контекстное поле было определено верно, необходимо, чтобы частота появления этих ключевых слов в тексте была не меньше определенного уровня. Для определения тематики текста поисковыми системами используются специальные математические алгоритмы, которые держатся в строжайшем секрете, однако все они основаны на частотном анализе с теми или иными дополнениями. Таким образом, если веб-мастер желает срубить бабок на адалт-партнерке, переправляя туда трафик пользователей сети, интересующихся размножением сусликов в неволе, он должен таким образом организовать контекст своего сайта, чтобы последний однозначно идентифицировался поисковиками как сусликовый вертеп. Для этого ему придется определить ключевые слова, проанализировать, с какой частотой они встречаются на страницах сайта, и в случае недостаточно высокого показателя частоты внести соответствующие коррективы (при этом важно не перестараться, так как за поисковый спам легко заработать бан на веки вечные). Постепенно переходим от скучной теории к практике. Как считать частоту ключевых слов (или их плотность, в терминологии SEO)? Этот показатель рассчитывается как отношение количества повторов ключевого слова в текстовом фрагменте определенного объема к общему количеству слов в этом фрагменте. Чаще всего плотность ключевых слов (keyword weight) рассчитывается для всей страницы или для всего сайта. В данном случае говорят уже не о плотности, а о частоте (keyword frequency). Задача ясна. Требуется, получив от пользователя кейворд, посчитать, сколько раз он встречается на странице, и разделить это число на общее количество слов на странице. Все просто. Но не спеши бежать за пивом – мозги тебе сегодня еще понадобятся, так как в этом незамысловатом алгоритме есть важные нюансы, которые мы обкурим по ходу дела. Let's my people go (© Кто-то из древних евреев) Приступим к написанию нашего первого SEO-инструмента. Для начала определимся с платформой. Из двух возможных альтернатив – традиционное оконное приложение и веб-приложение - предлагаю остановиться на последнем варианте. А для большей его гибкости и универсальности оформим все это в виде веб-сервиса. В качестве инструмента предлагаю использовать язык программирования Java и IDE NetBeans (хотя последнее, как говорится, на любителя, кто-то предпочитает Eclipse). Пораскинув мозгами, ты можешь прийти к выводу, что приложение должно включать в себя следующие функциональные модули: веб-сервис, механизм получения содержимого гипертекстового документа и парсер, выполняющий основную работу по расчету плотности заданного ключевого слова. Начнем с наименее ответственной части работы – создадим каркас приложения в виде веб-сервиса. Запускай среду разработки и открывай диалог создания нового проекта. В списке категорий выбирай web-проект и необходимый шаблон в правой части окна. В данном случае это будет Web Application. На описании шагов мастера останавливаться я не буду - там ничего сложного нет. Отмечу только, что на последнем этапе тебе будет любезно предложено выбрать фреймворк для создания пользовательского интерфейса. Но поскольку нас сейчас интересует только логика приложения, здесь можно ничего не выбирать, тем самым избавившись от ненужного балласта в виде неиспользуемого программного кода. После того как шаблон будет успешно загружен в редактор, создадим пакет, в котором будут храниться все наши основные классы. Назовем его org.kwf.core. Теперь в только что созданном пакете нужно разместить основной класс приложения. Что он должен уметь делать? Во-первых, соединяться с указанным в качестве параметра веб-узлом и забирать с него необходимый HTML-документ. Во-вторых, получив еще один параметр (кейворд), рассчитывать его частоту или плотность. Забирать документ с указанного ресурса мы будем в конструкторе класса, а парсить его – в отдельном методе. Назовем этот метод parse. Кстати, он должен возвращать в качестве значения уже рассчитанный для заданного ключевого слова показатель его частоты. Если перевести все вышесказанное на нормальный человеческий язык, то получится следующее: package org.kwf.core; class Parser{ private String text; private int freq; Parser(String val){} public int parse(String val){ return 0; } } Класс готов. Создаем сервис, который будет предоставлять к нему доступ веб-пользователей. Для этого в контекстном меню корневого узла проекта выбираем «New -< Web Service». В окне мастера нужно указать имя, которое будет присвоено сервису (например, KwfWs), и пакет, в котором будет находиться его основной класс (например, org.kwf.ws). После того как сервис создан, не мешало бы придать ему смысла (пока что он пуст, как твои пивные бутылки). Для этого можно воспользоваться как традиционным редактором кода, так и архитектором веб-сервисов, появившимся в шестой версии NetBeans и позволяющим визуально представить структуру и программную логику проектируемого веб-сервиса. Чтобы объяснить веб-сервису, что от него требуется, жми кнопку Add Operation. В окне свойств операции нужно будет ввести ее имя (у меня это count), а также указать передаваемые функции параметры. В качестве параметров будущий сервис будет принимать URL анализируемой страницы и ключевое слово, частота которого будет анализироваться. Для этого создадим две строковые переменные – url и word. Что дальше? А дальше мы будем ручками править программный код, созданный средой разработки. Зачем? А затем, чтобы подружить его с созданным ранее классом – надеюсь, ты про него еще не забыл. Переключайся на редактор программного кода веб-сервиса и ищи модуль, начинающийся со строки «@WebMethod(operationName = "count")». Именно здесь вместо строки «//TODO write your implementation code here» мы создадим экземпляр класса Parser, передадим ему необходимые параметры и получим ответ, возвращаемый методом класса. Подробности смотри во врезке. package org.kwf.ws; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebService; import org.kwf.core.Parser; @WebService() public class KwfWs { @WebMethod(operationName = "count") public String count(@WebParam(name = "url") String url, @WebParam(name = "word") String word) { Parser psr = new Parser(url); int count = psr.parse(word); String countStr = "Frequence of " + word + " is " + count; return countStr; } } По идее, это уже готовое веб-приложение с сервисно-ориентированной архитектурой (вау! клево-то как!). И хотя оно по-прежнему еще ни на что не способно, его уже можно (и нужно) тестировать, чтобы, как говорит мой знакомый боцман, оставив якоря, долги и плачущих женщин, отправиться вперед за горизонт, то есть приступить к разработке функционального ядра приложения. Для того чтобы проверить работоспособность веб-сервиса, найди его в древовидном списке проводника проектов и через контекстное меню выбери опцию Test Web Service. Да, не забудь предварительно стартануть сервер приложений и развернуть на нем свой проект (проще всего это сделать непосредственно из IDE с помощью команды Run). Перед тобой любезно распахнется окно веб-браузера, содержащее форму для ввода параметров, передаваемых веб-сервису, и ссылку на WSDL-файл. После отправки сервису любых двух строковых параметров он должен дать адекватный ответ, проигнорировав параметр, отвечающий за указание URL и сообщающий, что частота искомого ключевого слова равна нулю. Грабим HTML Для того чтобы произвести вычисление частоты использования определенного ключевого слова на той или иной странице, эту страницу для начала нужно получить и прочитать. Этим мы сейчас и займемся, мой бледнолицый друг! Создавая класс Parser, мы, как ты помнишь, предусмотрели в нем конструктор, который должен получать веб-страницу с указанным URL. Пока он пуст, следовательно, пора над ним серьезно поработать. Средствами Java загрузка веб-страницы реализуется не просто, а очень просто. Буквально, на счет два. Следи за руками. Делаем раз - преобразовываем строковый параметр, содержащий адрес страницы, в объект URL: URL resUrl = new URL(String) Делаем два – получаем HTML-документ: String doc = downloadPage(resUrl) Здесь downloadPage() - простейшая функция, на написание которой у меня ушло не более минуты: private String downloadPage(URL val){ try{ BufferedReader reader = new BufferedReader(new InputStreamReader(val.openStream())); String line; StringBuffer pageBuffer = new StringBuffer(); while((line = reader.readLine()) != null){ pageBuffer.append(line); } return pageBuffer.toString(); } catch (Exception e){} return null; } Думаю, идею ты уловил. Если так, то при создании реального приложения я бы тебе еще посоветовал организовать проверку корректности обрабатываемой строки при инициализации объекта URL на предмет соответствия стандарту веб-адресации. И на всякий случай (для тех, кто в танке) поясню, что этот код мы вставляем в конструктор класса Parser. Нелишним будет еще раз проверить работоспособность веб-сервиса. Для этого, запустив тест, вбивай в соответствующее поле реально существующий и доступный в данный момент с твоей машины URL. Сервис должен молча проглотить запрос. Если же он выплюнул страницу с громадным списком ошибок, значит ты где-то лопухнулся (читай еще раз или смотри пример на нашем диске). Раз словечко, два словечко, или парсинг HTML Наш пациент успешно помещен на операционный стол (читай: удаленный документ преобразован в локальную строковую переменную), и можно приступать к вскрытию, то есть к парсингу. Другими словами, пишем код для метода parse. С этой задачей справится даже true emogirl. Суть работы состоит в разборе имеющейся строки на отдельные лексемы (или, по-нашему, слова). Для этого в арсенале Java имеется такой замечательный класс, как StringTokenizer. Его конструктор выглядит следующим образом: StringTokenizer st = new StringTokenizer(string, templ) Здесь string – строка, подлежащая разбору, а templ – набор символов, используемых для отделения одного слова от другого. То есть этот набор должен представлять собой что-то вроде «,!\"\n;:|.?-()#@$%1234567890“”…©`\r\t–—<+={}_:&». Для того чтобы создать наиболее эффективный шаблон, можно организовать тестовый вывод массива токенов на консоль и отслеживать появление нежелательных символов с последующим их добавлением к шаблону. Для извлечения токенов из объекта StringTokenizer используется цикл: while(st.hasMoreElements()) st.nextToken(); } Итак, разбираем строку на отдельные токены и в цикле сравниваем каждый токен с нашим кейвордом, попутно подсчитывая количество токенов. По окончанию цикла делим первое значение на второе и делаем ретурн юзеру. while(st.hasMoreElements()){ countAll++; if(text.val.equalsIgnoreCase(st.nextToken())) count++; } float freq = count/countAll; Думаю, самое время поговорить о некоторых подводных камнях, о которых ты просто обязан знать, иначе весь твой частотный анализ не будет стоить и «стакана семочек». Начнем с того, что парсер в том виде, в котором он представлен, не осуществляет фильтрацию HTML-тэгов, наряду с основным текстом учитывающихся при подсчете токенов. Следовательно, перед разбором строки неплохо было бы вырезать из нее все последовательности <*<, более того, не забывай, что некоторые фрагменты документа, заключенные в парный тэг, тебе тоже совершенно не нужны (например, веб-формы). Но и это еще не все. Если слить все токены в консоль и внимательно их проанализировать, для большей убедительности подсчитав частоту появления каждого токена, то легко заметить, что в любом тексте чаще всего встречается такой хлам, как разнообразные предлоги, местоимения и прочая ерунда, которую, как подсказывает здравый смысл, не надо учитывать при подсчетах. Такого рода, с позволения сказать, слова имеют специальное название - «стоп-слова». И если уж ты собрался писать серьезные SEO-приложения, то этот факт обязательно надо учитывать. Например, включить в приложение словарик стоп-слов и на его основании организовать еще один уровень фильтрации. Нет предела совершенству, камрад. И наш простой анализатор плотности кейвордов можно совершенствовать до бесконечности. Вот тебе еще одна идейка (сегодня я добрый). Смысл ее в следующем. Любой язык обладает так называемым семантическим ядром, то есть набором слов, используемых в абсолютном большинстве текстов самой разнообразной тематической направленности. Еще один характерный признак слов, входящих в семантическое ядро, – это их нейтральная (иногда говорят «нулевая») информативность. Большинство поисковых систем при определении релевантности документа учитывает семантическое ядро основного для документа языка. Следовательно, ты тоже можешь взять на вооружение эту технологию и, самостоятельно составив семантическое ядро, автоматически пропарсив и проанализировав большой объем текстов или взяв уже готовое ядро (Google тебе в помощь), добавить еще один уровень фильтрации, исключающий слова, входящие в семантическое ядро. Клиент всегда прав До этого момента мы занимались созданием веб-сервиса. Однако, для того чтобы воспользоваться его возможностями, необходимо наличие соответствующего клиента. Вот тут-то ты можешь в полной мере прочувствовать своей задн... то есть головой, всю прелесть веб-сервисов. Я имею в виду абсолютную свободу в реализации клиента для веб-сервиса. Это может быть и оконное, и веб-приложение, созданные с использованием самых разнообразных технологий и языков программирования. Единственное условие – наличие сетевых средств и способность обрабатывать XML-сообщения. Как в окне конструктора веб-сервиса, так и в момент отладки ты не мог не заметить отображаемые на экране XML-сообщения – запрос клиента и ответ сервиса. Все, что тебе теперь нужно сделать, - это написать клиентское приложение, способное формировать соответствующий запрос и разбирать полученный ответ. Если же для создания клиента (неважно, оконного или с веб-интерфейсом) ты остановишься на том же языке Java и будешь создавать его в той же IDE NetBeans, то весь процесс потребует от тебя буквально несколько кликов мышкой. Автоматизация, брат. На всякий случай в качестве примера на диске мы выложили не только исходный код веб-сервиса, но и исходный код клиента. Собственно, это все, что я собирался тебе сегодня рассказать. Мораль сей басни такова: если руки растут из правильного места и есть желание, то всегда можно обойтись своими силами, а сэкономленные на покупке софта деньги потратить на женщин и карты. Adios! Релевантность (англ. relevant) применительно к результатам работы поисковой системы - степень соответствия запроса и найденного ответа, уместность результата. Основным методом оценки релевантности является TF-IDF–метод, который используется в большинстве поисковых систем (как в интернет-поисковиках, так и в справочных системах (MSDN)). Его смысл сводится к следующему: чем больше локальная частота термина (запроса) в документе (TF) и «редкость» термина (то есть чем реже он встречается в других документах) в коллекции (IDF), тем выше вес этого документа по отношению к термину, то есть документ в результатах поиска по этому термину будет выдаваться раньше. Автором метода является Gerard Salton (в дальнейшем он был доработан Karen Sparck Jones). Структура XML-запроса Структура XML-ответа sample text
|