перейти к содержанию

Как очистить данные из Интернета с помощью Go и Colly

Веб-скрапинг — это процесс программного извлечения данных с веб-сайтов. Он позволяет вам собирать информацию из Интернета и использовать ее для анализа, архивирования, создания приложений, машинного обучения или любых других целей.

Несмотря на то, что существует множество языков и инструментов, которые можно использовать для парсинга веб-страниц, в этой статье мы сосредоточимся на том, как парсить данные в Go с помощью фантастической платформы Colly. Простой синтаксис Go, строгая типизация и встроенные функции параллелизма делают его отличным выбором для написания парсеров.

Мы рассмотрим практический пример использования Go и Colly для извлечения данных из ветки комментариев Hacker News. К концу этого урока вы будете знать, как:

  • Установите и настройте Колли
  • Навигация по веб-сайтам и переход по ссылкам
  • Извлечение текста, атрибутов и HTML из элементов на странице.
  • Разберитесь с пагинацией
  • Вывод очищенных данных

Давайте погрузимся!

Настройка среды Go

Во-первых, убедитесь, что у вас установлена ​​последняя версия Go (1.13+). Вы можете проверить текущую версию с помощью:

$ go version

Создайте новый каталог для вашего проекта и инициализируйте в нем модуль Go:

$ mkdir hackernews-scraper
$ cd hackernews-scraper 
$ go mod init github.com/yourusername/hackernews-scraper

Затем установите пакет Colly:

$ go get -u github.com/gocolly/colly/...

Теперь создайте файл с именем main.go – здесь мы напишем код нашего парсера.

Представляем Colly — мощный фреймворк для парсинга Go

Colly предоставляет чистый и выразительный API для написания парсеров на Go. Он обрабатывает множество низкоуровневых деталей, таких как управление одновременными запросами, обработка файлов cookie и сеансов, отслеживание перенаправлений, соблюдение robots.txt и т. д.

Основная концепция Colly — это «Коллекционер», который представляет собой очистку данных. Вы создаете коллектор, настраиваете его с помощью параметров и обратных вызовов, а затем начинаете работу, предоставляя один или несколько URL-адресов для посещения.

Когда Collector сканирует страницы, он выполняет обратные вызовы в ответ на определенные события — например, вы можете зарегистрировать обратные вызовы для запуска, когда Colly:

  • Посещает новый URL-адрес
  • Находит определенный элемент HTML
  • Получает HTTP-ответ
  • Обнаруживает ошибку

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

Извлечение данных из Hacker News с помощью Go и Colly

В качестве примера давайте напишем парсер, который извлекает комментарии верхнего уровня из публикации Hacker News и выводит их на консоль. Мы очистим этот пост: https://news.ycombinator.com/item?id=12345

Вот полный код нашего парсера:

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "strings"

    "github.com/gocolly/colly"
)

type comment struct {
    Author  string `selector:"a.hnuser"`
    URL     string `selector:".age a[href]" attr:"href"`
    Comment string `selector:".comment"`
}

type post struct {
    Title    string    `selector:"a.storylink"`
    URL      string    `selector:"a.storylink" attr:"href"`
    Comments []comment  
}

func main() {
    // Create a new collector
    c := colly.NewCollector(
        colly.AllowedDomains("news.ycombinator.com"),
    )

    p := post{}
    // Extract post title and URL
    c.OnHTML(".fatitem", func(e *colly.HTMLElement) {
        e.Unmarshal(&p)
    })

    // Extract comments
    c.OnHTML(".comment-tree tr.athing", func(e *colly.HTMLElement) {
        comment := comment{}
        e.Unmarshal(&comment)

        // Remove extra spacing from comments
        comment.Comment = strings.TrimSpace(comment.Comment)
        // Build absolute URL from relative URL
        comment.URL = e.Request.AbsoluteURL(comment.URL)  

        p.Comments = append(p.Comments, comment)
    })

    // Set max depth to 1 so we only visit the post and its comments
    c.MaxDepth = 1 

    c.OnRequest(func(r *colly.Request) {
        fmt.Println("Visiting", r.URL)
    })

    c.OnError(func(r *colly.Response, e error) {
        log.Printf("Error scraping %s: %s", r.Request.URL, e)
    })

    c.OnScraped(func(r *colly.Response) {
        // Dump results as JSON
        enc := json.NewEncoder(os.Stdout)
        enc.SetIndent("", "  ")
        enc.Encode(p)
    })

    c.Visit("https://news.ycombinator.com/item?id=12345")
}

Давайте разберемся:

  1. Мы определяем два типа структур: post и comment, для хранения очищенных данных. Обратите внимание на теги «selector» и «attr» — они сообщают Colly, как найти эти данные в DOM.

  2. In main, мы создаем новый Сборщик, указывая, что ему разрешено посещать только страницы на news.ycombinator.com.

  3. Регистрируем двоих OnHTML обратные вызовы:

    • Первый ищет .fatitem элемент, который содержит заголовок и URL-адрес публикации и использует Unmarshal извлечь их в нашу post структура.
    • Второй обратный вызов ищет .comment-tree элементы и извлекает автора, относительный URL-адрес и текст каждого комментария, немного очищая их и добавляя в Comments массив наших post структура.
  4. Регистрируем еще несколько обратных вызовов:

    • OnRequest регистрирует каждый URL-адрес, который мы посещаем
    • OnError регистрирует любые ошибки, возникающие во время парсинга
    • OnScraped запускается после завершения всего задания очистки и выгружает очищенные данные в формате JSON.
  5. Наконец, мы вызываем c.Visit с URL-адресом сообщения, которое мы хотим очистить, что запускает фактическую работу по парсингу. Colly будет переходить по ссылкам и вызывать наши обратные вызовы по мере сканирования.

Запустите код с помощью:

$ go run main.go

Вы должны увидеть вывод вроде:

Visiting https://news.ycombinator.com/item?id=12345
{
  "Title": "Example HN Post", 
  "URL":  "http://example.com",
  "Comments": [
    {
      "Author": "user1", 
      "Comment": "First comment!",
      "URL": "https://news.ycombinator.com/item?id=12346"
    },
    ...
  ]
}

Тада! Всего с помощью нескольких десятков строк кода мы извлекли структурированные данные с веб-страницы. Конечно, вы можете сделать гораздо больше – это лишь поверхностное представление API Colly. Обязательно ознакомьтесь с документацией и примерами Colly, чтобы узнать о таких функциях, как:

  • Автоматическая обработка файлов cookie и сеансов
  • Параллельное парсинг с помощью горутин
  • Кэширование ответов
  • Настройка заголовков запросов, прокси и таймаутов
  • Ограничение скорости и глубины сканирования

За пределами базового парсинга – масштабные проблемы

Хотя Colly и Go упрощают начало работы с веб-скрапингом, все становится сложнее, когда вы пытаетесь собрать большие объемы данных с крупных веб-сайтов. Вы быстро столкнетесь с такими мерами противодействия ботам, как:

  • Ограничение скорости и CAPTCHA
  • Баны по IP при слишком быстром или слишком большом сканировании с одного IP
  • Динамические страницы, отображаемые на JavaScript, которые трудно очистить.
  • Частые изменения в структуре сайта, которые нарушают работу парсеров.

Чтобы обойти это, вам придется распределить парсеры по множеству IP-адресов, автоматизировать CAPTCHA и прокси, визуализировать JS, а также постоянно отслеживать и обновлять свой код. Это выполнимо, но для правильной реализации требуется значительное время и инфраструктура.

Если вы предпочитаете сосредоточиться на фактическом использовании данных, которые вы очищаете, а не на борьбе с мерами по борьбе с ботами, попробуйте ScrapingBee. Это API, который решает всю эту головную боль за вас — просто отправьте ему URL-адрес и получите обратно структурированные данные JSON, не беспокоясь о прокси, CAPTCHA или запретах IP. Он даже будет отображать для вас страницы JavaScript. Первые 1000 вызовов API бесплатны, так что попробуйте его в своем следующем проекте по парсингу!

Заключение

Парсинг веб-страниц — невероятно полезный навык, который должен быть в вашем арсенале разработчика, а сочетание Go и Colly делает его доступным и приятным. В этой статье мы рассмотрели полный пример парсинга ветки комментариев Hacker News – надеюсь, этот реальный пример использования дал вам представление о том, что возможно, и вдохновил вас попробовать парсить самостоятельно!

Помните, всегда будьте уважительны при очистке и соблюдайте файл robots.txt веб-сайтов и условия обслуживания. А теперь иди и освободи немного данных!

Присоединяйтесь к беседе

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