Компания
599,94
рейтинг
14 января 2013 в 14:27

Разработка → Как и для чего мы сделали свой валидатор микроразметки

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

Реакция роботов на ошибки в микроразметке

Медленно, но верно семантическая разметка набирает популярность. Чуть больше десяти лет назад (в мае 2001 года) впервые был введен термин «семантическая паутина». В 2004 году появилось первое упоминание формата RDFa, примерно тогда же начали развиваться микроформаты. В июне 2011 года был запущен стандарт schema.org. Сейчас семантическую микроразметку поддерживают и Яндекс, и другие ведущие мировые поисковые системы.

Однако вебмастера часто сталкиваются с тем, что валидаторы HTML выдают массу ошибок. Дело в том, что большинство из них не поддерживают микроразметку. Например, validator.w3.org поддерживает HTML5 в тестовом режиме и воспринимает микроданные как ошибку:



Существует много инструментов для проверки семантической разметки. Некоторые из них универсальны (например, http://validator.nu/), другие – проверяют конкретный тип разметки. Есть валидаторы RDFa (checkrdfa, w3.org/RDF/Validator/, rdfabout.com и другие), валидатор OpenGraph у Facebook, валидаторы микроформатов (например, валидатор hCard). Поисковые системы, использующие разметку, предлагают свои валидаторы.

Когда Яндекс стал использовать микроформаты и schema.org в своих сервисах, выяснилось, что у каждого потребителя разметки есть свои особенности её использования и свой набор расширений. Поэтому валидатор делает жизнь вебмастера намного проще. К тому же мы предупреждаем не только об ошибках в стандарте, но и о том, что нужно изменить в разметке, чтобы мы смогли использовать данные в своих сервисах.

Разработка универсального валидатора семантической разметки


Сейчас валидатор обрабатывает все популярные виды семантической микроразметки (микроформаты, микроданные, RDFa) и популярные словари (schema.org, OpenGraph). Эти форматы отличаются между собой логикой встраивания на страницу и внутренней структурой.

Сложнее всего разбирать микроформаты. Видимо, при их разработке больше внимания уделяли удобству встраивания на страницу, а не простоте извлечения данных.

Микроформаты встраиваются как классы CSS, и, чтобы найти их на странице, надо понимать их структуру. При этом они могут быть вложены друг в друга. Или один микроформат может быть полем другого. Некоторые микроформаты в одних случаях могут быть самостоятельными, а в других – полями других форматов. Например, hCard может использоваться и сам по себе, и в качестве поля. Другие сами по себе никогда не встречаются (например, поле adr в hCard).

В нашем валидаторе микроразметки есть небольшой фреймворк, который понимает логику разбора разных форматов микроразметки. Благодаря ему мы можем отдельно добавлять новые поля или даже целые типы разметки.
Рассмотрим на примере фрагмента кода, который парсит и валидирует микроформат hRecipe:

 public class HRecipe extends Microformat {
    final private static HRecipe instance = new HRecipe("hrecipe", true);

    protected HRecipe(@NotNull final String name, final boolean root) {
        super(name, root);
    }

 /**
   * Указываем список полей данного микроформата. 
   * Есть несколько видов свойств: 
   * MFPropertySingular – не более одного значения у поля,
   * MFPropertyPlural – множественные значения, MFPropertyConcatenated – множественные 
   * значения, объединяемые в одно.
   * Для каждого поля задается его имя и типы данных, которые могут в нем встретиться.
   */
    static {
      instance.addProperty(new MFPropertySingular("fn", TextProperty.getInstance()));
      instance.addProperty(
              new MFPropertyPlural("ingredient", Ingredient.getInstance(), TextProperty.getInstance()));
      instance.addProperty(new MFPropertySingular("yield", TextProperty.getInstance()));
      instance.addProperty(
              new MFPropertySingular("instructions", Instructions.getInstance(), TextProperty.getInstance()));
      ...
      instance.addProperty(new MFPropertySingular("result-photo", URIProperty.getInstance()));
      instance.addProperty(new MFPropertySingular("summary", TextProperty.getInstance()));
    }

 ...
}

При разборе микроформатов в дереве выделяются точки, которые могут быть корневыми. Затем находятся все элементы, которые могут быть использованы в качестве полей (adr, fn и т.д.). После этого формат очищается от вложенных карточек. Затем начинается разбор формата. Если обнаруживаются поля, которые тоже являются микроформатами, они разбираются рекурсивно. Увидеть, как это работает, можно на примере микроформата hCard:

<div class="vcard">
<!-- поля fn org url относятся к корневому микроформатному объекту -->
	<a class="fn org url" href=" http://www.commerce.net/"> CommerceNet </a>
<!-- поле adr является комплексным (то есть само по себе является микроформатным объектом) и содержит в себе другие поля: street-address, locality и пр. -->
	<div class="adr">
	    <span class="type">Work</span>:

	    <div class="street-address">169 University Avenue</div>
	        <span class="locality">Palo Alto</span>, <abbr class="region" title="California">CA</abbr>  
	        <span class="postal-code">94301</span>
	        <div class="country-name">USA</div>
	    </div>
<!-- поле tel так же комплексно и содержит поле type -->
	    <div class="tel">
	        <span class="type">Work</span> +1-650-289-4040
	    </div>

	    <div class="tel">
	        <span class="type">Fax</span> +1-650-289-4041
	    </div>

	    <div>Email:
	        <span class="email">info@commerce.net</span>
	    </div>
            
<!-- так же комплексные поля могут содержать тот же микроформат, что и основной объект. Например поле agent содержит объект микроформата hCard--> 
	    <div class="agent vcard">Contact person:
	        <a class="fn n email" href=" mailto:johndow@commerce.net">John Dow</a>
	    </div>
<!-- а этот объект hCard просто вложен внутрь корневого, но никак не влияет на его разбор -->
	    <div class="vcard">See also:
	        <a class="fn org url" href=" http://www.yellowpages.com/ATT">AT&T</a>
	    </div>
</div>


Все микроформаты различаются по своей внутренней структуре и по составу полей. Интересен, например, формат hResume (вернее, драфт этого формата – у него, как и у многих других, пока нет завершенной версии). В этом формате поле experience (опыт работы) одновременно задается как hCalendar (для указания временного промежутка) и hCard (для описания организации, в которой человек работал). Таким образом, есть поля, которые относятся к двум карточкам одновременно. При разборе других микроформатов мы каждое поле относили к одной карточке. Это помогало нам разделять произвольно вложенные друг в друга микроформаты. Чтобы научиться разбирать резюме, не ломая логику работы парсера, мы добавили в фреймворк свой искусственный тип данных – расширенный hCalendar, в который складываем все поля, относящиеся к опыту работы. Таким образом, мы разбираем этот микроформат не совсем по спецификации, зато правильно.

<div class="hresume">
    <div class=" position first experience vevent vcard summary-current" style="display:block">
        <span class="n fn" id="name">
            <span class="full-name"><span class="given-name">Peter</span> <span class="family-name">Savelyev</span></span>
        </span>
    <div class="postitle">
        <h4><strong>
            <a class="company-profile" href="/company/10718?trk=pro_other_cmpy"><span class="org summary">Yandex</span></a>      
            </strong>
        </h4>
    </div>
    <p class="period">
        <abbr class="dtstart" title="2011-07-01">июль 2011 г.</abbr>
        <abbr class="dtstamp" title="2012-12-11">настоящее время</abbr>
            <span class="duration"><span class="value-title" title="P1Y6M"> </span>(1 год 6 месяцев)</span>
    </p>
    <p class="description current-position">structured information extraction using semantic technologies</p>
    </div>
</div>

Парсер обработает этот пример так:

    hresume
        experience
            vevent
                vcard
                    fn = Peter Savelyev
                    n
                        family-name = Savelyev
                        given-name = Peter
                    org = Yandex
                dtstamp = 2012-12-11
                dtstart = 2011-07-01
                duration = P1Y6M
                summary = Yandex
                description = structured information extraction using semantic technologies

Многие микроформаты не имеют готовых спецификаций, хотя уже активно используются. Сейчас окончательно определены только hCalendar, hCard и несколько rel. Остальные – это черновые версии спецификаций разной степени готовности: некоторые почти готовы (например, hRecipe), другие далеки от совершенства и имеют ряд неопределенностей (например, hListing). Многие из микроформатов определяются только примерами, поэтому в спорных ситуациях бывает сложно принять обоснованное решение.

hListing – это микроформат для описания товаров и услуг. Для него пока не существует формального описания поля listing action, характеризующего вид услуги (продажа, покупка), поэтому вебмастера здесь поступают на свое усмотрение. Например, так:

<div class="hlisting">
    ...
    <span class="offer rent">Аренда</span>
    ...
</div>
или так
<div class='hlisting offer-rent'>
...
</div>

Поддержку этого формата мы отложили до выхода более полной версии спецификации.

Со словарем schema.org тоже не всегда удобно работать. В реальном мире микроразметка работает иначе, чем она могла бы работать в идеальных условиях.

Например, для ссылок можно разметить только url. Однако в самом тексте ссылки может содержаться полезная информация. Поэтому наш парсер сейчас сохраняет не только ссылку – как нужно было бы делать по спецификации – но и текст:

<a onclick="(new Image()).src='/rg/title-overview/director-1/images/b.gif?link=%2Fname%2Fnm0000487%2F';" href="/name/nm0000487/"   itemprop="director">Ang Lee</a></div> 

Если разбирать этот пример по правилам, то в поле «режиссер» будет расположена только ссылка "/name/nm0000487/", однако в большинстве случаев такой информации недостаточно. Поэтому наш парсер извлечет данные следующим образом:

director
    href = /name/nm0000487/
    text = Ang Lee 

Самая частая проблема при валидации и использовании любой микроразметки — ошибки вебмастеров. Страницы не всегда содержат верную разметку, иногда она неправильно встроена на страницу и т. д. Валидатор всегда предупреждает об ошибке (или просто о том, что данных недостаточно для использования в сервисах Яндекса). Мы стараемся сделать предупреждения об ошибках максимально понятными и конкретными.

При этом мы стремимся максимально использовать данные, даже если они содержат ошибки. Поэтому иногда мы предупреждаем об ошибке, но наш парсер успешно извлекает даже некорректно размеченные данные.

А вот с форматом RDFa проблем не возникло. Хотя и здесь есть нюанс. Дело в том, что RDFa позволяет сущностям ссылаться друг на друга, то есть дает возможность для создания циклов. Однако если в значении одной сущности есть ссылка на другую, мы воспринимаем ее как ссылку, а не подставляем описание сущности. Такое решение не противоречит официальной спецификации и предотвращает возможные проблемы.

Благодаря разным словарям с помощью RDFa можно разметить самые разные данные. Некоторые из словарей наш валидатор уже умеет понимать, другие только в планах. Сейчас один из самых популярных словарей – OpenGraph. Для него в результатах проверки у нас даже есть отдельный префикс –«og».

Результаты


Сейчас наш валидатор поддерживает все популярные типы микроразметки. Даже те, которые пока не используются в сервисах Яндекса. Нам хочется облегчить жизнь вебмастерам, которые интересуются семантическим вебом, и помочь им разобраться с ошибками. Для этого мы, в частности, написали раздел помощи по валидатору, введение в schema.org и справку по использованию микроформатов.

Немного статистики


Больше половины запросов к валидатору содержат разметку Schema.org. При этом примерно в 9% валидатор находит ошибки.

Запросы, содержащие микроформат hCard, составляют примерно 20%, и ошибки обнаруживаются примерно в 10% случаев.

Около 4% запросов – это RDFa, и около 10% примеров содержат ошибки.

OpenGraph составляет всего около 1,5% запросов, но и ошибок в этом формате практически нет. Всего в 1% случаев валидатор сообщает о некорректной разметке. Однако не удивляйтесь, если при проверке кода, содержащего OpenGraph, увидите предупреждения. Дело в том, что Яндекс пока принимает только og:video, о чем и сообщает валидатор, – при этом проверять он может и другие виды этой разметки.

А порядка 2% запросов – это проверка примеров, расположенных на главной странице валидатора.

Мы не собираемся останавливаться на достигнутом и планируем сделать интерфейс валидатора еще более наглядным и простым. Например, визуально отделить ошибки и предупреждения, относящиеся к стандарту, от ошибок и предупреждений сервисов Яндекса. И, разумеется, как можно активнее использовать в наших сервисах данные, полученные с помощью микроразметки. В ближайшем будущем мы продолжим рассказывать вам полезную информацию о микроразметке, о том, как удобнее ее встраивать и где лучше использовать. А если вы хотите узнать что-то конкретное – пишите об этом в комментариях, и мы постараемся ответить на ваши вопросы в следующих постах.
Автор: @Rasifiel
Яндекс
рейтинг 599,94

Комментарии (15)

  • 0
    А как быть если микроразметку внедрили, а Яндекс её не индексирует и саппорт не может ничего сделать :)?
    • 0
      А сама страница индексируется? На то, индексируется страница или нет, микроразметка не влияет.
      • 0
        Страницы индексируются, но в поиске отображались как обычные странице а не как рецепты (мы используем hRecipe). В вебмастере сниппеты были подключены.

        Сейчас сделали отдельный xml фид для Яндекса и ждем модерации.
    • +2
      Проблема была в детектировании страниц с микроформатами из потока индексируемых документов. Вот прямо сейчас документы индексируются и используются. К сожалению это заняло несколько больше времени чем хотелось бы.
      • +2
        Спасибо!

        Сделал для себя вывод, что с ПриватБанком нужно общаться в твиттере, а с Яндексом на хабре :)
  • 0
    Скажите пожалуйста, есть ли в планах поддержка микроразметки отзывов / рейтинга? (http://www.data-vocabulary.org/Review-aggregate/), так как это делает Google?
    • +3
      www.data-vocabulary.org/Review-aggregate/ менее выразительный, чем Review, Rating и AggregateRating из schema.org, ну и распространенность его меньше. К тому же сам Google всю новую разметку предлагает делать на базе schema.org.
      А отзывы на базе schema.org мы используем в наших партнерских программах: help.yandex.ru/webmaster/?id=1126788 и help.yandex.ru/webmaster/?id=1127405. Советую обратить внимание на них.
  • 0
    Было бы чудесно, если бы можно было просмотреть результат, который я получу в случае внедрения микроразметки.

    Также, не понятно, если есть предупреждения, то будет ли формироваться сниппет?
    К примеру, для кулинарного сайта формируется рецепт с использованием schema.org/Recipe, но также, в коде присутствует data-vocabulary.org/breadcrumb для формирования крошек, на которые валидатор ругается.

    Также, в справке картинка примера отличается от тектового примера, что приводит иногда в замешательство.

    В общем, было бы чудесно получить возможность увидеть результат и понимать, влияют ли на него ошибки или нет. Спасибо!
    • 0
      Предпросмотр сниппета в планах есть. Так же планируем улучшить читаемость ошибок и понятность их влияния на использование данных в сервисах Яндекса. Спасибо за обратную связь.
      • 0
        Спасибо и Вам за быстрый ответ. Я просто как раз сейчас борюсь (пытаюсь подогнать код) за то, чтобы Яндекс начал выдавать красивые картинки под нашими рецептами и при этом не разрушить внешний вид сниппетов, которые сейчас есть в гугле.
  • 0
    Возник вопрос, который, думаю, будет интересен многим вебмастерам.

    Скорость загрузки сайта сейчас очень актуальна и многие вебмастера прибегают к определенным ухищрениям. Одним из таких ухищрений является lazy load, подгрузка картинок по мере прокрутки страницы.

    Скажите, пожалуйста, как быть с микроразметкой, когда на сайте используется такой метод ускорения?

    Валидатор после парсинга выдает следующую картину:
    image
    href = http://delo-vcusa.ru/wp-content/plugins/bj-lazy-load/img/placeholder.gif
    text = Пицца Цезарь: Готовим тесто
    image
    href = http://img.delo-vcusa.ru/2012/10/DSC_2125-300x194.jpg
    text = Пицца Цезарь: Готовим тесто</code>
    

    То есть, в одном теге он делает разделение на placeholder и саму картинку.

    Вот мне интересно, как в итоге будет выглядеть выдача и будут ли учтены эти заглушки?
    • 0
      В данном случае самым простым вариантом будет разметить только noscript часть
      • 0
        Сначала не понял, а теперь идея ясна стала… убрать плейсхолдеры. Нужно будет покопаться в плагине, который использую и посмотреть механику работы. Просто сейчас смотрю выдачу и вижу, что некоторые рецепты так и добавились — картинка — белая картинка — картинка.

        Спасибо за идею!
  • 0
    Не как не подружиться с вашим валидатором, то поле не определено в спецификации, когда оно чётко определено в schema.org, то ошибка из-за отсутствия обязательного поля – когда оно вписано. При этом валидатор Гугла пишет, что всё замечательно.
    • 0
      Покажите, пожалуйста, пример, который у вас не работает, посмотрим, в чем проблема

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка