Парсинг сайта кинотеатра на Golang

от автора

Всем привет, в этой статье мы рассмотрим небольшой пример кода, написанный для сбора данных с сайта на популярном сегодня языке программирования Go.

Эта статья будет особенно интересна тем, кто много слышал о Go, но пока еще не попробовал его самостоятельно.

Для одного из внутренних проектов, нам нужно было собрать данные о фильмах, которые идут в прокате и расписании показов, сейчас рассмотрим первую (простейшую) версию парсера, с которой все и началось.

Для тех, кому лень читать код статьи, сразу привожу ссылку на репозиторий.

В первой своей версии парсер умел собирать лишь следующую информацию:

  • О сеансах в одном кинотеатре,
  • Детальное описание,
  • Название,
  • Киностудия,

И сохранять ее в JSON. Первоначально необходимо выбрать подходящую библиотеку для парсинга.

Google выдает большое количество вариантов по запросу `golang web scraping`, многие из них отражены в этом списке, советую ознакомиться с ним, свой же выбор я остановил на geziyor, так как он поддерживает JS Rendering (который, кстати мы не будем использовать в этом примере, однако эта фича бывает очень полезной при парсинге сайтов) и довольно прост в использовании.

Итак, библиотека выбрана, следующий шаг — установить ее и начать использовать ее в коде.
Установка библиотеки крайне проста:

go get -u github.com/geziyor/geziyor

Теперь перейдем к написанию кода.

Внутри тела главной функции вызовем парсер, передадим ему URL страницы, с которой начнем сбор данных и укажем, что хотим экспортировать результат в JSON файл:

 func main() {      geziyor.NewGeziyor(&geziyor.Options{          StartURLs: []string{"https://kinoteatr.ru/raspisanie-kinoteatrov/city/#"},          ParseFunc: parseMovies,          Exporters: []export.Exporter{&export.JSON{}},      }).Start()  } 

Начало положено, но не хватает логики сбора данных, для этого нужно реализовать функцию parseMovies.

Логика сбора будет следующей:

  • Поиск блока, содержащего информацию о фильме,
  • Сбор информации о всех сеансах внутри этого блока,
  • Сбор названия фильма и киностудии,
  • Сбор ссылки на страницу с подробной информацией о фильме,
  • Сбор описания с этой страницы

Перейдем к реализации этой функции

Здесь выбираются все блоки, содержащие информацию о фильме, для дальнейшей их обработки.

func parseMovies(g *geziyor.Geziyor, r *client.Response) {     r.HTMLDoc.Find("div.shedule_movie").Each(func(i int, s *goquery.Selection) { 

Таким образом собирается информация о сеансах, и тут же приводится в удобный человеку вид (убираем лишние пробелы и отступы на новую строку).

 var sessions = strings.Split(s.Find(".shedule_session_time").Text(), " \n ")  sessions = sessions[:len(sessions)-1]   for i := 0; i < len(sessions); i++ {      sessions[i] = strings.Trim(sessions[i], "\n ")  } 

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

 if href, ok := s.Find("a.gtm-ec-list-item-movie").Attr("href"); ok {     g.Get(r.JoinURL(href), func(_g *geziyor.Geziyor, _r *client.Response) {         description = _r.HTMLDoc.Find("span.announce p.movie_card_description_inform").Text()          description = strings.ReplaceAll(description, "\t", "")          description = strings.ReplaceAll(description, "\n", "")          description = strings.TrimSpace(description)  

Так вызывается API для экспортирования результатов в JSON файл.

 g.Exports <- map[string]interface{}{      "title":        strings.TrimSpace(s.Find("span.movie_card_header.title").Text()),      "subtitle":    strings.TrimSpace(s.Find("span.sub_title.shedule_movie_text").Text()),      "sessions":    sessions,      "description": description,  } 

Ура, все готово! Осталось только объединить написанные блоки кода воедино и запустить парсинг.

Так выглядит процесс работы парсера, видим в терминале сообщения об успешном получении страниц, это удобно.

А так выглядит результат парсинга.

Спасибо за чтение статьи, любите программирование на Go.

ссылка на оригинал статьи https://habr.com/ru/post/493088/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *