---
title: "Установка и первый скрапер на Colly"
description: "Первый скрапер на colly за десять минут: go mod init, go get github.com/gocolly/colly/v2, NewCollector, OnHTML и Visit — построчный разбор первой программы."
course: "Colly: парсинг и веб-скрапинг на Go"
url: "https://golangmaster.ru/courses/colly/lessons/02-ustanovka-pervyj-skreper/"
published: "2026-09-19"
updated: "2026-09-21"
minutes: 18
---

# Установка и первый скрапер на Colly

*Курс «Colly: парсинг и веб-скрапинг на Go», урок 2 из 25. ~18 минут. Обновлено 21.09.2026. Источник: https://golangmaster.ru/courses/colly/lessons/02-ustanovka-pervyj-skreper/*

Установка colly и первый скрапер — дело десяти минут: go mod init, go get github.com/gocolly/colly/v2, и тридцать строк, которые печатают цитаты с тренировочного сайта. В этом уроке соберём такую программу целиком, разберём каждый вызов построчно и поймаем две ошибки, на которых ломаются почти все новички.

Go стоит, терминал открыт, и на столе задача из первого урока: вытащить данные с сайта. Для тренировки берём quotes.toscrape.com — песочницу, которую специально держат для обучения скрапингу: список цитат с авторами и тегами, десять штук на страницу, разметка простая и стабильная. Цель этого урока скромная и конкретная: программа, которая скачивает страницу и печатает в терминал каждую цитату. Задача на вид маленькая, но за ней стоит весь каркас: подключение библиотеки к модулю, создание коллектора, правило, по которому colly находит нужные узлы, и запуск обхода. Всё остальное в курсе — вариации этого же скелета: другие селекторы, больше страниц, задержки, повторы, прокси. Поэтому первый скрапер стоит не пропустить, а разобрать построчно — так, чтобы каждая строка была объяснима, а не скопирована из устаревшего туториала. Запускать будем локально: скрапер ходит по сети, и песочница в браузере ему не помощник; если Go ещё не стоит, [урок об установке из базового курса](/courses/go-basics/lessons/02-ustanovka-go/) закроет вопрос за те же десять минут.

### go mod init и go get: подключаем colly/v2

Начало стандартное для любого Go-проекта со внешними зависимостями. В пустой папке создаём модуль: go mod init example.com/scraper — имя модуля может быть любым, для локальных упражнений хватает домена-заглушки. Затем добавляем зависимость: go get github.com/gocolly/colly/v2 — и go подкачивает библиотеку, записывая её в go.mod. Обратите внимание на хвост /v2: в Go-модулях второй мажор версии обязан жить в пути импорта, это не украшение, а часть адреса пакета. В коде импорт будет выглядеть как import "github.com/gocolly/colly/v2", и всё, что вы объявляете дальше, — colly.NewCollector, colly.HTMLElement — приходит именно оттуда. Команда go get сама выберет свежий релиз второй версии; первая версия с путём без /v2 существует отдельно, заморожена в прошлом и мы её не касаемся. Если после установки открыть go.mod, там появится строка require github.com/gocolly/colly/v2 с номером версии — это и есть фиксация зависимости, которую видят все, кто соберёт ваш проект. Рядом появится go.sum с контрольными суммами: благодаря ей сборка на другой машине получит ровно те же байты библиотеки, что и у вас, а не что-то похожее по названию.

### Первый скрапер целиком

```go
package main

import (
        "fmt"
        "github.com/gocolly/colly/v2"
)

func main() {
        c := colly.NewCollector()

        c.OnHTML("span.text", func(e *colly.HTMLElement) {
                fmt.Println(e.Text)
        })

        err := c.Visit("https://quotes.toscrape.com/")
        if err != nil {
                fmt.Println("не удалось открыть сайт:", err)
        }
}
```

Вся программа — создание коллектора, одно правило и один запрос. NewCollector возвращает *colly.Collector с настройками по умолчанию; OnHTML регистрирует функцию для узлов span.text; Visit скачивает страницу, разбирает её и запускает ваши колбэки. После go get зависимость программа компилируется как есть — запустите и посмотрите на десять цитат в терминале.

### Построчный разбор: NewCollector, OnHTML, Visit

Три вызова — три разных роли. colly.NewCollector создаёт коллектор: объект, который ведёт очередь адресов, держит настройки — домены, глубину, лимиты — и хранит зарегистрированные правила. Пока он создан с нулём аргументов: дефолтов для тренировочной страницы хватает. c.OnHTML("span.text", функция) — главное правило скрапера: когда ответ скачан и разобран, colly ищет в DOM все элементы, подходящие под селектор span.text, и для каждого вызывает вашу функцию, передавая элемент обёрткой *colly.HTMLElement. У обёртки есть всё, что нужно для извлечения данных: e.Text отдаёт текст узла уже без тегов, e.Attr достаёт атрибут, а вложенные поиски мы разберём в уроках про извлечение данных. Наконец, c.Visit(url) — точка запуска: синхронный запрос, загрузка ответа, разбор в DOM и прогон всех правил. Пока Visit выполняется, программа занята; закончится обход — закончится и работа. Такая синхронность — удобный дефолт для отладки: вывод появляется предсказуемо, и рассуждать о нём легко. Кавычки, в которые обёрнута каждая цитата, — часть текста на сайте, поэтому в выводе они приедут вместе с содержимым.

### Второе правило: вытаскиваем авторов

Правил у одного коллектора может быть сколько угодно, и каждое смотрит в свой селектор. Добавим второе: рядом с каждой цитатой на странице стоит small.author с именем автора, и селектор .author ловит его по классу. Регистрируем по тому же образцу — c.OnHTML(".author", ...) и внутри печатаем e.Text — и получаем вывод, где после каждой цитаты стоит её автор. Здесь важно не спешить со следующим шагом: два независимых правила дают два независимых потока значений, и связать конкретную цитату с конкретным автором по номеру вызова — ненадёжная идея. Правильный приём — вложенный обход от контейнера цитаты, который мы разберём в [уроке про механику OnHTML](/courses/colly/lessons/05-onhtml-kolbeki/), а все способы достать значение из элемента собраны в [уроке про Text, Attr и ChildText](/courses/colly/lessons/06-izvlechenie-dannyh/). Сейчас достаточно того, что вы поняли сам механизм: правило — это пара «селектор плюс функция», и функций может быть столько, сколько полей вы собираете. Попробуйте сразу добавить третье правило для a.tag — тегов цитаты, — и убедитесь, что третьим потоком всё работает точно так же: это займёт минуту и закрепит регистрацию правил лучше любого перечитывания.

> **Живое место: импорт v1 вместо v2.** Самая частая ошибка первых минут — импорт github.com/gocolly/colly без /v2. Это другой пакет первой версии: компилятор выдаёт тёмные ошибки вроде undefined: colly.HTMLElement или несовпадения типов в колбэках, а человек тратит вечер на охоту за призраком. Лечение одно: путь импорта github.com/gocolly/colly/v2 и свежая запись в go.mod. Проверяйте первую строку import до того, как гуглить ошибку.

### Что именно появилось в терминале

Полезно остановиться и рассмотреть вывод, потому что он показывает работу всей цепочки. Десять строк — по числу цитат на странице, причём порядок строк повторяет порядок цитат в разметке: colly идёт по DOM сверху вниз, и колбэк получает элементы в том же порядке. Каждая строка — чистый текст узла span.text: никаких HTML-тегов внутри, потому что e.Text возвращает текстовое содержимое, а не сырую разметку. Зато кавычки в начале и конце строки — часть данных: сайт оборачивает каждую цитату в кавычки прямо в тексте, и скрапер честно привозит их вместе со смыслом; обрезать их при желании можно обычным strings.Trim, но это уже вопрос парсинга, а не скачивания. Если вы вместо цитат увидели пустоту — программа всё равно сработала правильно: значит, промахнулся селектор, и следующая пара уроков про HTML и селекторы создана ровно для этого случая. И последнее: одна страница — это десять цитат из сорока, которые есть на сайте; до остальных мы доберёмся, когда научимся ходить по пагинации, а пока навык зафиксирован на компактном материале.

### Visit возвращает ошибку, и её стоит проверить

c.Visit(url) возвращает error, и это не формальность: сеть обрывается, домен опечатан, сервер отдаёт 404 или таймаут. В минимальном примере достаточно напечатать ошибку и выйти — как в программе выше. Но у ошибки есть и второй потребители: colly регистрирует колбэк OnError, который получает ответ и ошибку для каждого неудавшегося запроса, — туда переезжает логирование и решение, что делать дальше: повторить, пропустить адрес или остановить сбор. Полная обработка ошибок — тема отдельного урока про [OnError и повторы](/courses/colly/lessons/16-oshibki-retry/); здесь зафиксируем привычку: любой Visit в коде курса сопровождается проверкой возвращаемого значения, потому что скрапер без неё молча рапортует об успехе на пустом выводе. Да и в бытовом смысле сообщение не удалось открыть сайт: dial tcp: no such host сэкономит вам десять минут взгляда в терминал вместо допроса селекторов, которые тут ни при чём.

### Чек-лист перед запуском

- в go.mod появилась запись require github.com/gocolly/colly/v2
- путь импорта в файле — github.com/gocolly/colly/v2, без хвоста /v2 только у первой версии
- функция OnHTML зарегистрирована до вызова Visit
- селектор скопирован с живой страницы, а не придуман по памяти
- ошибка Visit проверяется, а не отбрасывается подчёркиванием
- терминал открыт рядом: первый запуск надо видеть глазами
- вы знаете, что должно появиться в выводе: догадка про десять строк — уже тест

### Проверка: путь импорта

**Вопрос:** Какой импорт правильный для второй версии colly?

- import "github.com/gocolly/colly"
- ✅ import "github.com/gocolly/colly/v2"
- import "github.com/gocolly/colly@v2"
- import "colly"

Go-модули требуют мажорную версию в пути: github.com/gocolly/colly/v2. Путь без /v2 — это старый пакет первой версии с другим API, а суффикс @v2 в import — синтаксис go get, не языка.

### Проверка: когда срабатывает правило

**Вопрос:** Колбэк из OnHTML("span.text") вызывается…

- сразу при регистрации правила
- ✅ после Visit: на каждый элемент, найденный в разобранном ответе по селектору
- один раз на всю страницу, в независимости от числа совпадений
- только если сайт отдал статус 500

Правило регистрируется заранее, но срабатывает при разборе ответа: colly находит все узлы под селектор и вызывает функцию на каждый из них. Десять цитат на странице — десять вызовов колбэка, по одному на элемент.

### Правило, зарегистрированное поздно

```go
c := colly.NewCollector()

err := c.Visit("https://quotes.toscrape.com/")
if err != nil {
        fmt.Println(err)
}

c.OnHTML("span.text", func(e *colly.HTMLElement) {
        fmt.Println(e.Text)
})
```

**Что выведет программа?**

- Десять цитат напечатаются, как обычно
- ✅ Ничего не напечатается: к моменту регистрации правило опоздало
- Программа упадёт с паникой
- Colly повторно скачает страницу и напечатает цитаты

Visit выполняется синхронно: к моменту выхода из него страница уже скачана и разобрана, все правила сработали. OnHTML, зарегистрированный после, ни на что не влияет — он дождётся следующего Visit, которого здесь нет. Правила регистрируют до запуска обхода.

### Восстановите второй скрапер

Допишите программу: версия в пути импорта, создание коллектора, селектор авторов и адрес страницы.

```go
package main

import (
        "fmt"
        "github.com/gocolly/colly/___"
)

func main() {
        c := colly.___()

        c.OnHTML("___", func(e *colly.HTMLElement) {
                fmt.Println(e.Text)
        })

        c.___("https://quotes.toscrape.com/")
}
```

Подсказка: Второй мажор в пути импорта; коллектор создаёт конструктор NewCollector; автор лежит в элементе с классом author; точка запуска — Visit.

Правильные ответы в пропусках: `v2`, `NewCollector`, `.author`, `Visit`

### Соберите первый скрапер по строкам

Расставьте строки в правильном порядке: от объявления пакета до проверки ошибки Visit.

Правильный порядок строк:

1. `package main`
2. `import (`
3. `  "fmt"`
4. `  "github.com/gocolly/colly/v2"`
5. `)`
6. `func main() {`
7. `  c := colly.NewCollector()`
8. `  c.OnHTML(".author", func(e *colly.HTMLElement) { fmt.Println(e.Text) })`
9. `  err := c.Visit("https://quotes.toscrape.com/")`
10. `  if err != nil {`
11. `    fmt.Println(err)`
12. `  }`
13. `}`

### Карточки: каркас colly

- **go get github.com/gocolly/colly/v2** — Команда подключения colly второй версии к модулю: фиксировала зависимость в go.mod. Хвост /v2 — часть пути импорта, не опция.
- **colly.NewCollector()** — Конструктор коллектора: очередь адресов, настройки и зарегистрированные правила. Без аргументов — настройки по умолчанию.
- **c.OnHTML(селектор, функция)** — Регистрация правила: после разбора ответа функция вызывается на каждый элемент, найденный по CSS-селектору.
- **c.Visit(url)** — Точка запуска: синхронно скачивает страницу, разбирает её в DOM и прогоняет правила. Возвращает error.
- **e.Text** — Текст элемента без тегов — то, что colly достаёт из узла DOM в колбэке OnHTML.
- **c.OnError** — Колбэк для неудавшихся запросов: получает ответ и ошибку. Место для логов и решений о повторе.

### Что дальше

Первый скрапер работает, но пока мы знаем про разметку ровно то, что подсказала задача со стороны: span.text и .author. Следующий урок закрывает пробел — [HTML для скрапера](/courses/colly/lessons/03-html-dlya-skrepera/): как читать дерево документа и находить селекторы самому. Потом — [CSS-селекторы в colly](/courses/colly/lessons/04-css-selektory/) во всей красе: классы, вложенность, атрибуты. А если хочется сразу к механике — пятый урок разбирает, как именно OnHTML обходит страницу и почему правил у коллектора может быть много.

> **Напоминание про песочницу.** Код этого урока запускается только локально: скраперу нужна сеть, которой у браузерного интерпретатора нет. Порядок простой: mkdir папка, go mod init, go get github.com/gocolly/colly/v2, go run main.go — и десять цитат в терминале.

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

- Подключение colly: go mod init в папке проекта, затем go get github.com/gocolly/colly/v2 — хвост /v2 обязателен в пути импорта.
- Скелет скрапера: NewCollector, правила OnHTML, запуск Visit — всё остальное в курсе вариации этого каркаса.
- OnHTML — пара «селектор плюс функция»: colly вызывает функцию на каждый элемент, найденный в разобранном ответе.
- Правил у коллектора сколько угодно, но регистрируют их до Visit: правило, добавленное после загрузки страницы, опоздало.
- Visit возвращает error — проверка обязательна, иначе неудачный запуск выглядит как успех с пустым выводом.
- Импорт v1-пути github.com/gocolly/colly даёт тёмные ошибки компиляции — проверяйте первую строку import.
- e.Text отдаёт текст узла без тегов; способы достать данные разобраны в шестом уроке.

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

Повторите установку с нуля в новой папке: go mod init, go get github.com/gocolly/colly/v2, программа из урока. Потом усложните: добавьте второе правило OnHTML для .author и третье для a.tag — тегов цитаты. Запустите и посмотрите на порядок вывода. Сознательно поменяйте импорт на путь без /v2, соберите проект, прочитайте ошибки компилятора и верните v2 обратно — умение распознавать эту ошибку по первым строкам вывода экономит вечер в будущем.

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

### Какая версия colly сейчас актуальна?

Вторая: путь импорта github.com/gocolly/colly/v2. Первая версия живёт по пути без /v2, заморожена и в новые проекты не берётся. go get сам подтянет свежий релиз второй версии.

### Почему Visit ничего не напечатал, хотя сайт открывается?

Проверьте три вещи: правило зарегистрировано до Visit, селектор совпадает с реальной разметкой (проверьте во вкладке Elements), а e.Text выводится внутри колбэка. И убедитесь, что ошибка Visit не отброшена подчёркиванием.

### Нужно ли закрывать коллектор или освобождать ресурсы?

Нет: коллектор — обычный объект Go, сборщик мусора приберёт его после выхода из программы. Close-подобных методов у него нет; единственное, о чём стоит помнить, — про Wait при асинхронном режиме, о нём отдельный урок про параллельный скрапинг.
