Веб-скрейпінг для навчання ШІ та RAG: як збирати дані відповідально
Як збирати публічні дані з вебу для навчання LLM і RAG: правила, які перевірити першими, ввічливий краулінг, очищення, дедуплікація, походження даних і видалення.
Великі мовні моделі та генерація з доповненням пошуком (RAG) починаються з тексту з вебу. Зібрати його легко. Зібрати відповідально — означає ухвалити рішення ще до першого запиту: які джерела, на яких умовах, з якою швидкістю і як ви згодом покажете, звідки взято кожен документ.
У цьому посібнику розділено RAG і навчання, наведено правила, що визначають, які дані можна збирати, і розібрано конвеєр: перевірити правила, ввічливо завантажити, очистити, прибрати дублікати, записати походження, зберегти й видалити. Це загальна інформація, а не юридична консультація. Для реального датасету зверніться до юриста, який знає авторське право та захист даних на ваших ринках.
- RAG зберігає копії сторінок і показує джерела під час відповіді. Навчання перетворює текст на ваги моделі. В обох випадках потрібні права й правила, а навчання вимагає більшої обережності, бо видалити дані важко.
- «Публічний» не означає «вільний для використання». Перш ніж збирати, перевірте
robots.txt, умови використання, ліцензію та будь-яку машиночитну відмову, і збережіть докази. - Персональні дані на публічних сторінках лишаються персональними даними. Збирайте мінімум і дотримуйтеся правил захисту даних, зокрема GDPR.
- Краулте повільно, вказуйте чесний
User-Agentі тримайте ліміт запитів на рівні сайту. Проксі змінює те, звідки йде запит, але не те, чи маєте ви право його надсилати. - Очищуйте, прибирайте дублікати й записуйте походження кожного документа. Саме це дає змогу вказувати джерело, фільтрувати за ліцензією та видаляти на вимогу.
- Трафік оплачується за ГБ: завантажуйте текст, використовуйте умовні запити й кешуйте те, що вже маєте.
1.RAG і навчання — різні завдання
Один і той самий краулер може постачати дані для обох випадків, але вимоги до них різні. Вирішіть, що саме ви будуєте, ще до початку збору.
| Питання | RAG | Навчання чи донавчання |
|---|---|---|
| Що зберігається | Копії сторінок або фрагментів в індексі | Текст, перетворений на ваги моделі, і датасет, на якому навчали |
| Коли використовується | Під час відповіді, щоб спертися на джерело | Перед навчанням і під час нього |
| Чи видно джерело читачеві | Зазвичай так: можна цитувати й давати посилання | Зазвичай ні |
| Актуальність даних | Повторно завантажувати змінені сторінки | Нове навчання |
| Видалення джерела | Видалити його з індексу | Складно: виключити з майбутніх запусків і датасетів |
Оскільки з індексу видалити легко, а з навченої моделі важко, багато команд починають із RAG і зберігають джерело кожного фрагмента. Решта посібника стосується обох варіантів.
2.Правила, що визначають, що можна збирати
Єдиного правила немає. Одночасно діють кілька речей, і переважає найсуворіша:
- robots.txt. Домовленість (RFC 9309), за якою власники сайтів повідомляють краулерам, які шляхи відкриті. Це не закон сам по собі, але ігнорування файлу — слабка позиція в будь-якому спорі. Багато сайтів тепер прямо називають у ньому ШІ-краулери; приклади токенів —
GPTBot,ClaudeBot,CCBotіGoogle-Extended. - Умови використання. Це договір. Деякі сайти забороняють автоматизований збір або використання свого вмісту для навчання ШІ.
- Авторське право й ліцензії. Сторінки є захищеними творами, якщо в них немає відкритої ліцензії (наприклад, Creative Commons) і вони не належать до суспільного надбання. У ЄС правила інтелектуального аналізу тексту й даних (стаття 4 Директиви 2019/790) дозволяють правовласникам застерегти свої права у машиночитний спосіб, і запис у
robots.txtзазвичай розглядають як один із таких сигналів. Деталі ще уточнюються, тож вважайте відмову обов’язковою. - Персональні дані. Імена, адреси електронної пошти і профілі лишаються персональними даними, навіть коли вони публічні. GDPR вимагає правової підстави, мінімізації даних і видалення на вимогу.
- Контроль доступу. Сторінки за входом чи платним доступом лежать поза межами цього посібника. Збирайте їх лише за дозволом.
Якщо сумніваєтеся, віддавайте перевагу джерелам, які дають ліцензію: відкриті дані, офіційні API, партнерські стрічки та власний вміст. У політиці прийнятного використання перелічено, для чого сервіс використовувати не можна, а безпечне й відповідальне використання проксі описує звички навколо цього.
3.Відповідальний конвеєр загалом
- Правила. Прочитайте
robots.txt, умови та ліцензію кожного джерела і запишіть рішення. - Завантаження. Запитуйте сторінки повільно, з чесним
User-Agent, і лише потрібне. - Очищення. Залиште вміст, приберіть меню, спливні вікна та скрипти.
- Дедуплікація. Приберіть точні та майже точні копії.
- Зберігання. Тримайте текст разом із походженням, строком зберігання та способом видалення.
4.Перевірте правила до першого запиту
Завантажте robots.txt один раз на сайт через ту саму сесію та проксі, з якими будете краулити, і питайте в парсера дозвіл для кожного URL перед запитом. Відсутній файл (404) означає, що нічого не заборонено. Помилка сервера означає, що в сайту проблеми, тож зачекайте й повторіть пізніше:
from urllib.parse import urlsplit
from urllib.robotparser import RobotFileParser
import requests
UA = "my-crawler/1.0 (+https://example.com/crawler; contact: [email protected])"
_robots: dict[str, RobotFileParser] = {}
def allowed(session: requests.Session, url: str) -> bool:
parts = urlsplit(url)
base = f"{parts.scheme}://{parts.netloc}"
if base not in _robots:
r = session.get(base + "/robots.txt", timeout=(5, 20))
if r.status_code >= 500:
return False # the site is in trouble: try again later
rp = RobotFileParser()
rp.parse(r.text.splitlines() if r.status_code == 200 else [])
_robots[base] = rp
return _robots[base].can_fetch(UA, url)Парсер зі стандартної бібліотеки простий і не реалізує всього в RFC 9309, наприклад шаблонів, тож для великого краулінгу беріть суворіший парсер. Читайте також тег meta robots і заголовок X-Robots-Tag сторінок, які завантажуєте, та умови використання сайту. Збережіть дату й хеш прочитаного robots.txt: це частина ваших доказів.
5.Завантажуйте ввічливо
Ввічливість — це ще й те, що дає краулінгу працювати місяцями. Вказуйте чесний User-Agent зі сторінкою про ваш краулер і контактною адресою, тримайте один запит одночасно на сайт, робіть паузи між запитами й сповільнюйтеся, коли цього просить сайт. Умовні запити теж заощаджують трафік: відповідь 304 не має тіла.
import random
import time
def retry_after(r) -> int:
value = r.headers.get("Retry-After", "")
return int(value) if value.isdigit() else 60
def polite_get(session, url, etag=None, pause=(2, 5)):
if not allowed(session, url):
return None # the site asks crawlers to stay out
headers = {"If-None-Match": etag} if etag else {}
r = session.get(url, headers=headers, timeout=(5, 30))
if r.status_code in (429, 503):
time.sleep(retry_after(r)) # the site asked us to slow down
return None
time.sleep(random.uniform(*pause)) # a pause between requests to the same site
return r # status 304 means: unchanged, keep the stored copyБюджети запитів, обробку помилок і перевірку даних розібрано в матеріалі веб-скрейпінг у масштабі, а посібник із проксі для Python показує сесії, тайм-аути й повторні спроби.
6.Де в конвеєрі місце проксі
Проксі — це один з інструментів кроку завантаження. Вони корисні, коли потрібна публічна сторінка залежить від країни: місцеві ціни, наявність товарів, регуляторні повідомлення, документація для одного ринку. Датасет чи індекс RAG для ринку має містити ту сторінку, яку бачить цей ринок.
- Один IP на одне завдання краулінгу. У Xameleon IP лишається тим самим, поки ви працюєте. Змінюйте його між завданнями: у кабінеті чи через API, і записуйте країну кожного завантаження. У матеріалі як ротувати проксі описано підходи.
- Обирайте тип під сторінку. Публічна документація й відкриті дані зазвичай добре працюють через проксі дата-центрів. Сторінки, адаптовані до мобільних мереж, краще завантажувати через 4G мобільні проксі. У матеріалі мобільні проксі проти проксі дата-центрів їх порівняно.
- Тримайте ліміт на рівні сайту, а не IP. Десять проксі — це не дозвіл на десятикратне навантаження.
Проксі змінює те, звідки йде запит. Він не змінює того, чи дозволено вам його надсилати: якщо правила сайту кажуть «ні», то відповідь «ні» з будь-якої адреси. Як підключити проксі до краулера чи агента — у статті проксі для ШІ-агентів.
7.Очистіть текст
Сирий HTML здебільшого не є вмістом. Модель чи ретривер, що бачить меню, повідомлення про cookie та футери, навчається на шумі й повертає шум, а ви платите за це за ГБ і за токен.
| Крок | Що робити |
|---|---|
| Витягти основний вміст | Залишити заголовки, абзаци, списки й таблиці. Прибрати навігацію, спливні вікна, форми та скрипти. |
| Зберегти структуру | Перетворити на Markdown чи простий текст із заголовками, щоб фрагменти відповідали структурі сторінки. |
| Нормалізувати | Застосувати Unicode NFC, звести пробіли й виправити зіпсовані кодування. |
| Відфільтрувати | Відкинути дуже короткі сторінки, сторінки з помилками та сторінки мовами, які вам не потрібні. |
| Зменшити обсяг персональних даних | Прибрати адреси електронної пошти, номери телефонів та імена користувачів, якщо вони не потрібні й немає підстави їх зберігати. |
8.Прибирайте дублікати перед індексацією
Той самий текст трапляється під багатьма URL: версії для друку, дзеркала, параметри відстеження. Дублікати марнують сховище й токени, змушують ретривер повертати п’ять копій однієї відповіді та збільшують ризик, що модель запам’ятає текст. Точні копії прибирайте за хешем нормалізованого тексту:
import hashlib
import re
import unicodedata
def normalize(text: str) -> str:
text = unicodedata.normalize("NFC", text).lower()
return re.sub(r"\s+", " ", text).strip()
def content_hash(text: str) -> str:
return hashlib.sha256(normalize(text).encode("utf-8")).hexdigest()
seen: set[str] = set()
def is_new(text: str) -> bool:
h = content_hash(text)
if h in seen:
return False
seen.add(h)
return TrueМайже точні копії, як-от сторінка з одним зміненим абзацом, потребують міри подібності. Порівнюйте множини словесних шинглів за індексом Жаккара:
def shingles(text: str, n: int = 5) -> set[str]:
words = normalize(text).split()
return {" ".join(words[i:i + n]) for i in range(max(1, len(words) - n + 1))}
def jaccard(a: set[str], b: set[str]) -> float:
union = a | b
return len(a & b) / len(union) if union else 1.0
# pairs above about 0.8 are usually the same articleПорівняння кожної пари не масштабується. Для великого корпусу використовуйте MinHash із хешуванням, чутливим до локальності, яке знаходить пари-кандидати без повного порівняння.
9.Записуйте походження кожного документа
Походження — це запис про те, звідки взято документ, коли й як його зібрано. Без нього неможливо вказати джерело у відповіді RAG, відфільтрувати за ліцензією чи видалити документ на прохання власника. Записуйте його поруч із текстом, у тому самому рядку файлу JSONL:
import datetime
import json
def make_record(url: str, status: int, text: str, licence: str, country: str) -> dict:
return {
"url": url,
"fetched_at": datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds"),
"status": status,
"sha256": content_hash(text),
"licence": licence, # for example "CC BY 4.0", "terms forbid AI use", "unknown"
"country": country, # the vantage point of the fetch
"text": text,
}
with open("corpus.jsonl", "a", encoding="utf-8") as f:
f.write(json.dumps(make_record("https://example.com/docs/a", 200, "Page text", "CC BY 4.0", "UA"),
ensure_ascii=False) + "\n")В індексі RAG зберігайте URL джерела й дату завантаження з кожним фрагментом, щоб відповідь могла посилатися на своє джерело. Не додавайте до жодного навчального набору документи зі значенням ліцензії unknown, доки хтось їх не перевірить.
10.Зберігання, строки та видалення
- Зберігайте потрібне. Текст і метадані, а не сирий HTML, зображення та відео, якщо проєкт їх не потребує.
- Задайте строк зберігання. Повторно завантажуйте або видаляйте старі документи за розкладом і запишіть цей розклад.
- Вкажіть контакт. Сторінка, на яку веде ваш
User-Agent, має казати, хто керує краулером і як із вами зв’язатися. - Видаляйте на вимогу. Знаходьте документи за доменом, URL або хешем, видаляйте їх зі сховища й індексу, записуйте факт видалення та виключайте джерело з майбутніх запусків навчання.
- Захистіть сховище. Обмежте доступ, шифруйте дані на диску й не пускайте персональні дані до журналів. У політиці конфіденційності описано, що ми зберігаємо про ваш акаунт і трафік.
11.Типові помилки
| Помилка | Чим це шкодить | Виправлення |
|---|---|---|
| Вважати «публічне» «вільним для використання» | Умови, ліцензії та відмови все одно діють | Перевіряти їх для кожного джерела й записувати результат |
Один раз прочитати robots.txt багато років тому | Правила змінюються, а ваші докази застарівають | Перечитувати його при кожному краулінгу й зберігати хеш |
| Багато воркерів на один сайт | Навантаження підсумовується незалежно від кількості IP | Обмежувати паралельність для сайту, а не для проксі |
| Зберігати сирий HTML | Шум, витрати й більше персональних даних для захисту | Зберігати очищений текст із метаданими |
| Немає походження | Не можна вказати джерело, відфільтрувати чи видалити | Записувати один запис на документ |
| Індексувати дублікати | Ретривер повертає той самий текст п’ять разів | Хешувати точні копії й порівнювати майже точні |
| Змішувати країни в одному індексі | Відповідь для одного ринку цитує сторінку іншого | Зберігати країну кожного завантаження й фільтрувати за нею |
12.Часті запитання
Чи законний веб-скрейпінг для навчання ШІ?
Це залежить від джерела, країни та способу використання. Авторське право, умови використання, відмови й закони про захист даних — усе має значення, а правила ще розвиваються. Збирайте з джерел, які дають ліцензію, коли це можливо, записуйте свої рішення й порадьтеся з юристом, перш ніж будувати великий датасет.
Чи стосується robots.txt ШІ-краулерів?
На практиці так. Саме так власники сайтів повідомляють, що відкрито, і багато хто називає в ньому ШІ-краулери. Це домовленість, а не закон сам по собі, але його ігнорування послаблює вашу позицію, а в ЄС він може слугувати машиночитним застереженням прав.
Чим відрізняються дані для RAG і для навчання?
RAG зберігає копії в індексі та вказує джерела у відповідях. Навчання перетворює текст на ваги моделі, і це важко скасувати. Дивіться таблицю в розділі 1.
З якою швидкістю має працювати ШІ-краулер?
Повільніше, ніж здається. Надсилайте один запит одночасно на сайт, робіть паузи між запитами, поважайте Retry-After і сповільнюйтеся при відповідях 429 та 5xx. Якщо сайт публікує затримку краулінгу, дотримуйтеся її.
Чи потрібен проксі для збору публічних даних?
Не для кожного джерела. Користуйтеся ним, коли сторінка залежить від країни або коли потрібна одна адреса на весь час одного завдання краулінгу. Дивіться проксі для веб-скрейпінгу і проксі для AI та LLM-інструментів.
Що зберігати з кожним документом?
URL, час завантаження, статус, хеш вмісту, примітку про ліцензію, країну завантаження й текст. Цього досить, щоб вказати джерело, відфільтрувати й видалити.
Чи можна використовувати вміст сайту, який забороняє використання для ШІ?
Ні. Поважайте відмову й шукайте ліцензоване джерело. Можна також попросити дозвіл у власника. Коли ваш конвеєр даних запрацює, перевірте, як відповіді ШІ-пошуку подають ваш власний вміст у кожній країні.
Лишилися запитання про мобільні проксі? Відвідайте нашу сторінку FAQ щоб отримати детальні відповіді, або зверніться до нашої підтримки — ми допоможемо.