Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Урок 3 из 25 ~16 мин +50 XP

HTML для скрапера: DOM, теги, атрибуты

HTML для парсинга — это не вёрстка, а карта местности: скраперу достаточно уметь читать дерево документа, различать классы, id и атрибуты, чтобы находить данные по селекторам. В этом уроке доберём этот минимум: разберём DOM на разметке quotes.toscrape, научимся работать с вкладкой Elements и поговорим о разметке, которая переживает чужие релизы.

Содержание урока · 11 разделов

Вы открываете вкладку Elements в браузере, и на вас вываливается четыре тысячи строк разметки: вложенные div, классы-абракадабра, скрипты, мета-теги. Хочется закрыть и попросить кого-то другого. Хорошая новость: скраперу вёрстка нужна ровно в объёме, которого хватает, чтобы найти данные и не потерять их завтра. Вы не собираетесь править CSS и ловить баги отступов — вы ищете контейнеры, тексты и атрибуты, и на это уходит процентов двадцать языка. Уверенно читать дерево документа, понимать, чем класс отличается от идентификатора и зачем нужны data-атрибуты, — этого достаточно, чтобы писать селекторы для девяти задач из десяти. Остальная глубина — для верстальщиков, и она нам не пригодится. Всё, что ниже, разбирается на живой разметке песочницы quotes.toscrape.com: откройте её в соседней вкладке и проверяйте каждое утверждение глазами. Программных примеров в этом уроке почти нет — зато весь материал сразу ложится в скрапер из второго урока, когда вы запустите его локально с новым селектором.

DOM: дерево страницы, по которому ходит скрапер#

Браузер, получив HTML, строит из него DOM — объектную модель документа, и dom дерево страницы — это иерархия узлов: элемент внутри элемента внутри элемента. У каждой ветки есть родитель, у элементов — дети, у текста внутри тегов — текстовые узлы. Корень дерева — html, под ним head и body, и дальше разметка разветвляется по вложенности. Скраперу это дерево важно по одной причине: селекторы в colly ищут не строки в тексте, а узлы в дереве, и результат поиска зависит от того, где именно лежит узел и кто его предки. Один и тот же span на верхнем уровне и span внутри карточки товара — разные цели для селектора. Вложенность читается по отступам в исходнике: всё, что открыто между открывающим и закрывающим тегом контейнера, — его потомки. Ошибка новичка — судить о структуре по визуальному расположению на экране: браузер растягивает и переносит элементы так, что визуально рядом могут лежать узлы из разных веток дерева. Смотрите на вложенность, а не на картинку.

Разметка одной цитаты из quotes.toscrape

GO
<div class="quote" itemscope itemtype="http://schema.org/CreativeWork">
  <span class="text" itemprop="text">
    "The world as we have created it is a process of our thinking."
  </span>
  <span>by <small class="author" itemprop="author">Albert Einstein</small></span>
  <div class="tags">
    Tags:
    <meta class="keywords" itemprop="keywords" content="change,deep-thoughts">
    <a class="tag" href="/tag/change/page/1/">change</a>
    <a class="tag" href="/tag/deep-thoughts/page/1/">deep-thoughts</a>
  </div>
</div>

Типовой контейнер: div.quote обнимает всё, что относится к одной цитате; span.text несёт текст, small.author — автора, ссылки a.tag — теги. itemscope и itemprop — микроразметка schema.org: сайт помогает поисковикам, а заодно и нам. На странице таких контейнеров десять, по одному на цитату.

Теги и атрибуты: на что смотрит скрапер#

Тег задаёт тип узла — div, span, a, img, small, — а атрибуты приписаны тегу парами имя-значение. Для парсера значимы четыре вида: class и id, на которых держатся селекторы; href у ссылок и src у картинок — адреса, по которым ходит и качает скрапер; title и alt — человеческие подписи, в которых сайты любят прятать полные названия товаров; и data-атрибуты вида data-url, data-id — куда фронтенд складывает машиночитаемые значения. Текст узла — то, что лежит между открывающим и закрывающим тегом, — достаётся через e.Text, а атрибуты — через e.Attr; это два разных выхода из одного узла, и выбирать надо по тому, где данные надёжнее. Классический пример: у карточки товара в каталоге books.toscrape.com название обрезано в тексте ссылки до пары слов, а полный вариант лежит в атрибуте title той же ссылки — берут именно атрибут. Разметка обычно щедрее, чем кажется: у большинства узлов найдётся второй путь к данным.

Класс против id: сколько элементов выбирает селектор#

Класс описывает тип или роль элемента, и один класс может носить сколько угодно узлов на странице — десять карточек каталога делят один класс product_pod. Идентификатор id по стандарту должен быть уникален в документе: один узел — один id, чаще всего это главный контейнер страницы вроде id="content" или навигация. Отсюда правило выбора для скрапера: повторяющиеся данные — цитаты, товары, строки таблицы — ищут по классам, потому что их много; привязку к конкретному месту страницы делают по id, если он есть и стабильный. Жизнь вносит поправки: современные фронтенд-фреймворки генерируют id автоматически, и они меняются от сборки к сборке, а на некоторых сайтах один id тихо повторяется пять раз, потому что верстальщику было удобно. Поэтому и класс, и id стоит проверять взглядом: откройте Elements, посчитайте совпадения, пройдитесь на вторую страницу каталога и убедитесь, что селектор ловит то же самое. Проверка занимает минуту и экономит вечер отладки.

Инлайн и внешний контент: что видит скрапер#

Здесь спрятана ловушка, о которую спотыкаются все, кто привык к вкладке Elements. Скрапер получает исходный HTML-ответ сервера — то, что отдал сайт по сети, до всяких скриптов. Вкладка Elements показывает текущий DOM: после того как JavaScript успел дорисовать, переставить и удалить узлы. Для серверных страниц, как наши песочницы, разница почти нулевая. Но на сайтах с рендерингом в браузере Elements показывает данные, которых в исходном ответе нет: скрапер по селектору из Elements получит пустоту. Способ проверки без кода: правый клик по странице — «Просмотреть исходный код страницы» и поиск по тексту, который вы ищете. Нашли фрагмент в исходнике — colly до него доберётся; не нашли — данные приходят скриптом, и это уже разговор про браузерные движки из урока про пределы colly. Вторая половина той же мысли: текст, который вы видите на экране, может собираться из нескольких узлов и псевдоэлементов CSS, а e.Text берёт только то, что реально лежит в дереве.

Data-атрибуты и семантические теги: надёжные зацепки#

Хорошие сайты оставляют для машин явные зацепки, и ими стоит пользоваться в первую очередь. Data-атрибуты — всё, что начинается с data-, — придуманы для того, чтобы JavaScript носил данные прямо в разметке: data-id="42", data-url="/product/42", data-price="1490". Они почти не участвуют в оформлении, поэтому живут дольше классов; для скрапера это часто лучший источник значений. Семантические теги — article, main, nav, table, header — описывают смысл блока, а не его вид: карточка товара почти всегда article, список статей — внутри main. Селектор article.product_pod переживает редизайн чаще, чем div.row > div:nth-child(3), потому что смысл карточки не меняется вместе с сеткой раскладки. Микроразметка itemprop, как в разметке цитаты выше, — ещё один слой стабильности: сайты несут её для поисковиков и редко ломают. Приоритет простой: data-атрибуты и семантика, потом осмысленные классы, и только потом геометрия страницы.

Elements в devtools: от клика до селектора#

Рабочий цикл скрапера начинается в браузере. Правый клик по нужному элементу на странице — «Просмотреть код» — и вкладка Elements разворачивается на том самом узле. Дальше три вопроса: что это за тег, какие у него классы и атрибуты, и что вокруг — в каком контейнере он лежит. Контейнер важнее всего: селектор, построенный от контейнера цитаты, точнее, чем селектор, построенный от самого текста. В контекстном меню узла есть Copy selector — и им стоит пользоваться с оговоркой: devtools часто выдаёт абсолютный путь вида body > div.container > div.row > div.col-md-8 > div.quote:nth-child(4) > span.text — с номерами детей, которые переломаются, как только на странице станет на одну цитату больше или меньше. Такой вариант берут как сырьё: сокращают до повторяющейся части div.quote span.text и проверяют поиском по документу, сколько узлов ловится. Самая эффективная привычка — искать по классу в поиске devtools: Ctrl+F внутри Elements показывает все совпадения и сразу даёт понять, уникален ли селектор.

Что где лежит: карта атрибутов скрапера#

АтрибутЧто в нёмКак использовать
classроль элемента, обычно не уникальнаосновной материал селекторов для повторяющихся данных
idуникальный идентификатор узлапривязка к конкретному блоку страницы, если id стабильный
href, srcадреса ссылок и картинокисточник для обхода и для выкачивания файлов
title, altполные подписи элементовполные названия, обрезанные в тексте, и описания картинок
data-имямашиночитаемые значения фронтендачасто самый стабильный путь к id, url и ценам
itemprop, contentмикроразметка schema.orgструктурированные данные, которые сайты держат для поисковиков

Проверка: класс и id

На странице десять карточек товара. Какой селектор их соберёт?

Проверка: Elements против исходника

Во вкладке Elements карточка товара видна, но скрапер по селектору получает ноль элементов. Первое действие?

Что выберет селектор в этой ветке

Прочитайте код и выберите, что он выведет:

<div class="quote">
  <span class="text">"Be yourself; everyone else is already taken."</span>
  <span>by <small class="author">Oscar Wilde</small></span>
</div>

// Селектор: .quote .author
// Вопрос: какой текст достанет e.Text на этом элементе?

Соберите разметку цитаты

Допишите фрагмент разметки: класс контейнера цитаты, класс текста и класс автора — ровно как в quotes.toscrape.

<div class=""> <span class="">"Текст цитаты"</span> <small class="">Albert Einstein</small> </div>

Соберите вложенность разметки

Расставьте строки так, чтобы получилась корректная ветка дерева: контейнер, его дети, закрытия тегов в обратном порядке.

Строки

Ваша программа

Нажимайте на строки слева, чтобы собрать программу

Карточки: HTML глазами скрапера

Термин

DOM

нажмите, чтобы перевернуть
Определение

Объектная модель документа: дерево узлов, которое браузер строит из HTML. Селекторы colly ищут узлы именно в нём.

1 / 6

Что дальше#

Разметка прочитана, зацепки найдены — пора превращать их в запросы. Следующий урок — CSS-селекторы в colly: от простых тегов и классов до комбинаций, атрибутных условий и псевдоклассов. А после него — пятый, про механику колбэков OnHTML: что именно colly делает с найденными узлами и как не намолотить дубликатов. Если захочется освежить, зачем всё это нужно и где границы темы, — вернитесь к знакомству с Colly.

Песочница урока

Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.

Вывод

Запустите код, чтобы увидеть вывод.

Коротко: что запомнить

  • Скраперу хватает минимума HTML: дерево документа, теги, атрибуты, текст узлов — вёрстка на этом объёме заканчивается.
  • DOM — дерево вложенных узлов; селектор ловит узлы по месту в дереве, а не по внешнему виду на экране.
  • Классы носят много элементов — ими собирают повторяющиеся данные; id уникален и подходит для привязки к блоку, если он стабильный.
  • Важные атрибуты: href и src — адреса, title и alt — полные подписи, data-* — машиночитаемые значения, itemprop — микроразметка.
  • Elements показывает DOM после скриптов, скрапер видит исходный HTML-ответ; расхождение проверяют через просмотр исходного кода.
  • Хэшированные классы вроде css-1x2abc переламываются при деплое — зацепки выбирают по убыванию стабильности: data-атрибуты, семантика, осмысленные классы.
  • Copy selector из devtools — сырьё, а не готовое решение: абсолютные пути с nth-child сокращают и проверяют на второй странице.

Домашнее задание

Откройте quotes.toscrape.com и books.toscrape.com в двух вкладках devtools. Для каждой песочницы выпишите: класс контейнера повторяющегося блока, селектор текста, селектор атрибута со ссылкой и один data-атрибут или itemprop, если найдёте. Потом возьмите Copy selector на карточке товара в books и сократите его до самого короткого варианта, который ловит все карточки на странице — проверьте поиском по документу.

Личные заметкиПусто
Хранятся только в вашем браузере (Colly · HTML для скрапера: DOM, теги, атрибуты)

Вопросы и ответы по уроку

Насколько глубоко нужно знать HTML для парсинга?

Хватит дерева документа, тегов, атрибутов и классов: контейнер, текст, ссылка, картинка. Флексбоксы, сетки и обработчики событий — территория верстальщика; скраперу важнее уметь читать вложенность и выбирать стабильные зацепки.

Почему Copy selector из devtools не работает в скрапере?

Работает, но недолго: devtools выдаёт абсолютный путь с номерами детей (nth-child), который переламывается при любом изменении количества блоков. Сократите путь до повторяющейся части — контейнер плюс цель — и проверьте на нескольких страницах.

Скрапер видит страницу так же, как браузер?

Нет: он получает исходный HTML-ответ, до исполнения JavaScript. Вкладка Elements показывает уже обработанный DOM. Если данные есть только в Elements, их рисуют скрипты, и colly по ним пройдёт с пустыми руками.

Термины урока

Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.

Следующая ступень учебного пути

Testify25 уроков~9 чпрактика25 уроков уже доступны

Testify: тестирование Go с assert и require

Интерактивный курс Testify для Go: assert и require, табличные тесты, suite, mock-объекты, Eventually, HTTP-тесты. 25 уроков с примерами и практикой в браузере.

  • Писать читаемые проверки через assert и require, а не лестницы if
  • Проверять ошибки, паники и краевые случаи без ручного кода
  • Сравнивать структуры, слайсы, карты и числа с плавающей точкой
  • Строить табличные тесты и сьюты с хуками подготовки