В этой статье представлен инструмент для извлечения данных JSON из HTML и показано, как использовать этот инструмент на примере Douban Movie. В этой статье используется много селекторов CSS, селекторы CSS могут относиться кMDN.
В последние месяцы было написано больше сканеров Node, а инструменты, используемые для анализа HTML-документов,cheerio(cheerio можно рассматривать как серверную версию jQuery). cheerio довольно многофункционален и предоставляет множество API для запроса/изменения/удаления/добавления узлов или текста. Однако по мере увеличения количества просканированных страниц постоянное использование cheerio по-прежнему становится немного громоздким. сканеры для обработки Шаблоны HTML относительно фиксированы, но обработка определенных шаблонов в Cheerio недостаточно лаконична.Следующие три пункта являются одними из наиболее распространенных ситуаций:
В следующих трех пунктах предположим, что мы хотим просканировать изображение выше с домашней страницы Douban Movies."Появление"список. Обратите внимание, что список обновляется в режиме реального времени, поэтому следующие селекторы в этой статье могут работать по-разному.
- Один и тот же элемент может содержать несколько полей данных. Например, у каждого фильма на картинке выше есть название фильма.
title,Связьurlи рейтингrateполе; - Целью сканирования является список (или даже список списков). Например, на приведенном выше рисунке нам нужно получить список информации о фильме;
- Частая, но простая обработка форматов. Например: преобразовать рейтинг фильма из строкового типа в число и удалить ненужный параметр url в ссылке на фильм.
temmeЭто инструмент для обработки HTML, разработанный на основе приведенных выше наблюдений. Основываясь на селекторах CSS, temme добавляет дополнительный синтаксис для изящной обработки трех вышеуказанных моментов:
- Поддержка одновременного использования нескольких селекторов, поддержка захвата нескольких полей одновременно;
- Поддержка очистки списка;
- Поддерживается обработка форматов.
установка и использование
# 全局安装
yarn global add temme # npm install --save temme
# 最基本的使用方式
temme <selector> <html>
# 省略html参数,使用来自stdin的输入;--format 参数表示格式化输出
temme <selector> --format
# 使用文件中的选择器
temme <path-to-a-selector-file> <html>
# 和 curl 配合使用
curl -s <url> | temme <selector>
Темме обеспечиваетОнлайн веб-версия, в котором редактор обеспечивает подсветку синтаксиса. Остальную часть этой статьи также можно выполнить в этой онлайн-версии, просто скопировав соответствующий HTML-код.
Пример 1. Получение информации о фильме с домашней страницы Douban Movies.
Возьмите название, рейтинг и ссылку первого фильма. Селектор Temme выглядит следующим образом:
Шаги работы с командной строкой следующие:
curl -s https://movie.douban.com | temme '.ui-slide-item[data-title=$title data-rate=$rate]; .ui-slide-item a[href=$url];' --format
# output:
# {
# "title": "烟花 打ち上げ花火、下から見るか?横から見るか?",
# "rate": "5.7",
# "url": "https://movie.douban.com/subject/26930504/?from=showing"
# }
Селекторы в примере очень похожи на селекторы CSS, разница в том, что селектор temme содержит следующую структуру:[foo=$bar]. Смысл этой структуры - "поместить свойство foo в поле bar результата". Селектор выше содержит три такие структуры, выбирающие сразу три поля. Селектор выше также содержит два подселектора (по одному на строку на диаграмме), каждый из которых заканчивается точкой с запятой.
Другой распространенной структурой являетсяdiv{$buzz}, что означает «поместить текстовое содержимое элемента div в поле результатов». если знакомыemmetЕсли это так, то можно увидеть, что текущее поведение temme является обратным процессом emmet.
Пример 2: Преобразование формата
в приведенном выше результатеrateэто строка, мы можем использовать фильтрNumberобработать это. На этот раз мы не выбираем другие поля.
curl -s https://movie.douban.com | temme '.ui-slide-item[data-rate=$rate|Number];'
# output: {"rate":5.7}
видно по результатамrateТип поля числовой. В настоящее время толькоrateполе, удобнее использовать значение поля непосредственно как результат:
curl -s https://movie.douban.com | temme '.ui-slide-item[data-rate=$|Number];'
# output: 5.7
пропускать$xxxсерединаxxx, то формат результата будет из{ xxx: yyy }сталиyyy.
Пример 3: список «Показывается в данный момент»
«Текущий показ» — это список, в котором информация о каждом фильме соответствует селектору CSS, который удовлетворяет.ui-slide-item[data-title]HTML-элемент. В приведенном выше примере мы выбрали только данные первого фильма, здесь мы используем@символ для выбора списка. Получите информацию обо всех фильмах в списке «Текущие показы», селектор выглядит следующим образом:
Эффект операции следующий:
curl -s https://movie.douban.com | temme '.ui-slide-item[data-title] @recentMovies { &[data-title=$title data-rate=$rate|Number]; a[href=$url]; }' --format
# output:
# {
# "recentMovies": [
# {
# "title": "烟花 打ち上げ花火、下から見るか?横から見るか?",
# "rate": 5.7,
# "url": "https://movie.douban.com/subject/26930504/?f rom=showing"
# },
# {
# "title": "相声大电影之我要幸福",
# "rate": 0,
# "url": "https://movie.douban.com/subject/26811605/?f rom=showing"
# },
# ......
# ]
# ]
значение селектора: каждый селектор CSS, который удовлетворяет.ui-slide-item[data-title]Элемент HTML является родительским элементом детали фильма, мы будем@Затем поставьте селектор, а затемrecentMoviesУказывает имя поля «Recently Hit List» в конечном результате, а затем мы помещаем два селектора в примере 1 в фигурные скобки, чтобы выбрать данные одного фильма.
если мы опустим здесь@recentMoviesсерединаrecentMoviews, оставить только один@символ, то конечным результатом будет массив (уровень JSON будет уменьшен на один уровень).
Захваты списка могут быть вложенными. Например, на странице вопросов stackoverflow есть несколько ответов, и каждый ответ имеет несколько комментариев.Следующий селектор может получить эти комментарии в формате двумерного списка:
curl -s https://stackoverflow.com/questions/1014861/is-there-a-css-parent-selector | temme '.answer@{ .comment@{ .comment-body{$|trim}; }; };'
Пример 4: страница сведений о фильме
После сканирования списка ссылок на фильмы на главной странице мы можем войти на страницу каждого фильма, чтобы просмотреть подробные данные о фильме. Здесь мы беремфейерверкЭтот фильм тому пример. Данные на странице введения фильма очень подробные, включая название фильма, режиссера, сценариста, главные роли, жанр фильма, официальный сайт и другую информацию. Здесь для сканирования выбираются некоторые данные, и селектор выглядит следующим образом:
// 电影的名称
[property="v:itemreviewed"]{$title};
// 电影上映年份
.year{$year|substring(1, 5)|Number};
// 电影导演
[rel="v:directedBy"]@directedBy { &{$} };
// 电影编剧(:contains是来自jQuery的选择器 https://api.jquery.com/contains-selector/)
:contains('编剧') + span{$storyFrom|split('/')||trim};
// 电影主演(前三位)
[rel="v:starring"]@starring|slice(0, 3){ &{$} };
// 平均评分
[property="v:average"]{$avgRating|Number};
// 具体的评分情况
.ratings-on-weight .item@ratingInfo{
span[title=$title];
.rating_per{$percentage};
};
// 电影剧情简介
[property="v:summary"]{$summary|trim};
// 喜欢这部电影的人也喜欢...
.recommendations-bd dl@recommendations{
img[alt=$name src=$imgUrl];
a[href=$url];
};
Селектор здесь длинный и писать в терминале не удобно Сохраняем селектор в файлdouban-movie.temme, затем запустите тему:
curl -s https://movie.douban.com/subject/26930504/ | temme douban-movie.temme --format
# output:
# {
# "title": "烟花 打ち上げ花火、下から見るか?横から見るか?",
# "year": 2017,
# "directedBy": [ "新房昭之", "武内宣之" ],
# "storyFrom": [ "岩井俊二", "大根仁" ],
# "starring": [ "广濑铃", "菅田将晖", "宫野真守" ],
# "avgRating": 5.4,
# "ratingInfo": [
# { "title": "力荐", "percentage": "7.2%" },
# { "title": "推荐", "percentage": "12.8%" },
# ......
# ],
# "summary": "川村元气即将再度与《你的名字。》制......",
# "recommendations": [
# {
# "name": "想要传达你的声音",
# "imgUrl": "https://img3.doubanio.com/vie......",
# "url": "https://movie.douban.com/subject......"
# }
# ......
# ]
# }
Хотя селектор выбирает много контента, он по-прежнему сохраняет четкую структуру и хорошую читабельность. можно открытьОнлайн-версия этого примера, сравните селектор и формат вывода, вы сможете понять значение селектора.
При написании краулера мы сначала анализируем структуру страницы, используем онлайн-версию, чтобы написать соответствующий селектор для каждого типа страницы, а затем сохраняем селектор в локальном файле. После запуска сканера и получения HTML-кода мы читаем соответствующий файл селектора, запускаем его и получаем желаемый результат.
Резюме и другие
Вышеупомянутое введение в основном включает в себя основное использование temme.Вы можете видеть, что temme реализует вышеупомянутые идеи улучшения. На практике структура страниц большинства веб-сайтов относительно ясна, и анализировать CSS-селекторы элементов страницы проще, а в настоящее время использование temme может значительно повысить эффективность выборки данных. Для более полного использования и документации temme, пожалуйста, переместитеGithub, добро пожаловать на развилку и звезду.
Ниже приведены некоторые из основных технологий, используемых при разработке: