Odpowiedzialne praktyki web scrapingu
Przestrzeganie robots.txt, nagłówki user agenta, opóźnienia między żądaniami i buforowanie.
Odpowiedzialne praktyki web scrapingu to bezpłatna lekcja AI Agents na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Agents, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Agents zawiera 4 lekcji w sumie.
Dlaczego odpowiedzialny scraping ma znaczenie
Scraping stron internetowych może obciążać serwery, naruszać warunki korzystania z usługi i doprowadzić do zablokowania adresu IP agenta. Odpowiedzialne narzędzia do scrapingu przestrzegają limitów zapytań, identyfikują się i respektują zasady publikowane przez witryny.
Ta lekcja obejmuje narzędzia i techniki służące etycznemu i zrównoważonemu scrapingowi.
Sprawdzanie robots.txt
Każda witryna może opublikować plik robots.txt określający, do których ścieżek agenci automatyczni mogą uzyskiwać dostęp, a do których nie. Biblioteka standardowa języka Python zawiera moduł urllib.robotparser do analizowania tego pliku.
Przed rozpoczęciem scrapingu witryny należy zawsze sprawdzić jej plik robots.txt.
import urllib.robotparser
rp = urllib.robotparser.RobotFileParser()
rp.set_url('https://example.com/robots.txt')
rp.read()
# Check if our bot can fetch a specific path
can_fetch = rp.can_fetch('MyAgent/1.0', 'https://example.com/public-data')
print(f'Can fetch: {can_fetch}') # True or False
cannot_fetch = rp.can_fetch('*', 'https://example.com/private/admin')
print(f'Admin allowed: {cannot_fetch}') # Often FalseUstawianie opisowego User-Agent
Nagłówek HTTP User-Agent identyfikuje podmiot wysyłający żądanie. Rzetelny User-Agent pozwala administratorom witryny dowiedzieć się, czym jest dany bot i jak skontaktować się z jego właścicielem w razie problemów. Podszywanie się pod przeglądarkę w celu omijania blokad budzi wątpliwości natury etycznej.
import httpx
headers = {
# Honest, descriptive User-Agent
'User-Agent': 'MyResearchBot/1.0 (contact: me@example.com; purpose: academic research)'
}
response = httpx.get(
'https://example.com/data',
headers=headers,
timeout=10.0
)
print(response.status_code)Ograniczanie częstotliwości zapytań za pomocą time.sleep()
Wysyłanie setek żądań na sekundę może przeciążyć serwer i często jest traktowane jak atak typu odmowa usługi. Należy dodawać opóźnienia między żądaniami za pomocą time.sleep(). Można użyć random.uniform(), aby opóźnienie było mniej mechaniczne i bardziej zbliżone do zachowania człowieka.
import time
import random
import httpx
urls = [
'https://example.com/page/1',
'https://example.com/page/2',
'https://example.com/page/3'
]
for url in urls:
response = httpx.get(url, timeout=10.0)
print(f'Fetched {url}: {response.status_code}')
# Wait between 1 and 3 seconds before the next request
delay = random.uniform(1, 3)
print(f'Sleeping {delay:.1f}s...')
time.sleep(delay)Przestrzeganie nagłówków Retry-After
Gdy serwer odpowiada kodem 429 Too Many Requests, często dołącza nagłówek Retry-After określający, ile sekund należy odczekać. Agent powinien odczytać tę wartość i zastosować się do niej, zamiast natychmiast ponawiać żądanie.
import time
import httpx
def fetch_with_retry(url: str) -> httpx.Response:
while True:
response = httpx.get(url, timeout=10.0)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 5))
print(f'Rate limited. Waiting {retry_after}s...')
time.sleep(retry_after)
continue # retry
response.raise_for_status()
return responseBuforowanie odpowiedzi w celu uniknięcia ponownego pobierania
requests-cache automatycznie buforuje odpowiedzi HTTP na dysku. Jeśli agent musi wielokrotnie pobrać ten sam adres URL (np. podczas tworzenia lub ponownego uruchamiania aplikacji), buforowane odpowiedzi są zwracane natychmiast, bez wysyłania kolejnego żądania do serwera.
# pip install requests-cache
import requests_cache
# Install the cache globally — cached responses expire after 1 hour
requests_cache.install_cache(
'agent_cache',
backend='sqlite',
expire_after=3600 # seconds
)
import requests
# First call: fetches from network and caches
response = requests.get('https://api.example.com/data')
print(response.from_cache) # False
# Second call: returns cached result instantly
response2 = requests.get('https://api.example.com/data')
print(response2.from_cache) # TrueRęczne buforowanie w plikach za pomocą httpx
Jeśli nie chcą Państwo używać requests-cache, dobrze sprawdzi się prosty bufor oparty na plikach. Należy przechowywać odpowiedzi jako pliki JSON, których nazwy wynikają z hasza adresu URL, i wczytywać je ponownie, jeśli plik jest wystarczająco świeży.
import hashlib
import json
import os
import time
import httpx
CACHE_DIR = '/tmp/agent_cache'
os.makedirs(CACHE_DIR, exist_ok=True)
def cached_get(url: str, ttl_seconds: int = 3600) -> dict:
key = hashlib.md5(url.encode()).hexdigest()
cache_file = os.path.join(CACHE_DIR, key + '.json')
if os.path.exists(cache_file):
age = time.time() - os.path.getmtime(cache_file)
if age < ttl_seconds:
with open(cache_file) as f:
return json.load(f)
response = httpx.get(url, timeout=10.0)
response.raise_for_status()
data = response.json()
with open(cache_file, 'w') as f:
json.dump(data, f)
return dataCzytanie warunków korzystania z usługi
Przed rozpoczęciem scrapingu dowolnej witryny należy przeczytać jej warunki korzystania z usługi. W wielu z nich wyraźnie zabrania się automatycznego dostępu lub komercyjnego wykorzystywania danych. Naruszenie ToS może skutkować podjęciem kroków prawnych, a nie tylko zablokowaniem adresu IP.
Jeśli istnieje oficjalny interfejs API, należy zawsze wybrać go zamiast scrapingu kodu HTML — jest szybszy, stabilniejszy i bezpieczniejszy pod względem prawnym.
Wykładnicze zwiększanie opóźnienia po błędach
Gdy żądanie się nie powiedzie, nie należy ponawiać go natychmiast. Należy zastosować wykładnicze zwiększanie opóźnienia: odczekać 1 s, następnie 2 s, potem 4 s itd. Pozwala to uniknąć przeciążania serwera, który ma problemy, i jest profesjonalnym wzorcem stosowanym w agentach produkcyjnych.
import time
import httpx
def fetch_with_backoff(url: str, max_retries: int = 4) -> dict:
for attempt in range(max_retries):
try:
response = httpx.get(url, timeout=10.0)
response.raise_for_status()
return response.json()
except (httpx.HTTPStatusError, httpx.RequestError) as e:
if attempt == max_retries - 1:
raise
wait = 2 ** attempt # 1, 2, 4, 8 seconds
print(f'Attempt {attempt+1} failed: {e}. Retrying in {wait}s...')
time.sleep(wait)
return {}Pobieranie tylko potrzebnych danych
Należy minimalizować obciążenie serwera, pobierając tylko dane, których agent rzeczywiście potrzebuje. Zamiast pobierać całe strony, warto używać niewielkich punktów końcowych API, jeśli zwracają te same dane. Przed pobraniem pełnej treści można użyć żądań HEAD, aby sprawdzić, czy zasób się zmienił.
import httpx
def has_page_changed(url: str, last_etag: str = None) -> bool:
headers = {}
if last_etag:
headers['If-None-Match'] = last_etag
response = httpx.head(url, headers=headers, timeout=5.0)
if response.status_code == 304: # Not Modified
return False
new_etag = response.headers.get('ETag')
print(f'New ETag: {new_etag}')
return TruePodsumowanie zasad odpowiedzialnego scrapingu
Krótka lista kontrolna przed rozpoczęciem scrapingu dowolnej witryny przez agenta:
- Sprawdzić plik
robots.txti przestrzegać reguł disallow - Ustawić rzetelny i opisowy nagłówek
User-Agent - Dodawać losowe opóźnienia między żądaniami (
time.sleep(random.uniform(1,3))) - Przestrzegać nagłówków
Retry-Afterw odpowiedziach 429 - Buforować odpowiedzi, aby uniknąć zbędnego pobierania
- Przeczytać warunki korzystania z usługi danej witryny
- Jeśli to możliwe, wybierać oficjalne interfejsy API zamiast scrapingu HTML
Sprawdzenie wiedzy: odpowiedzialny scraping
Proszę sprawdzić swoją wiedzę na temat etycznych i odpowiedzialnych praktyk scrapingu.
Podsumowanie: odpowiedzialne praktyki scrapingu
Ma już Pan/Pani kompletny zestaw narzędzi do odpowiedzialnego scrapingu:
robotparserdo sprawdzania, do jakich zasobów można uzyskać dostęp- Opisowe nagłówki
User-Agentidentyfikujące bota time.sleep(random.uniform(1,3))między żądaniamirequests-cachelub ręczne buforowanie w celu unikania powtarzających się pobrań- Wykładnicze zwiększanie opóźnienia do obsługi błędów
- Świadomość prawna: należy zawsze sprawdzać ToS
Odpowiedzialny scraping sprzyja zdrowszemu internetowi i pozwala agentom działać bez blokad.
Często zadawane pytania
Czy lekcja „Odpowiedzialne praktyki web scrapingu” jest bezpłatna?
Tak — pełny tekst „Odpowiedzialne praktyki web scrapingu” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Agents, przejdź na CoddyKit PRO. Kurs AI Agents zawiera 4 lekcji w sumie.
Co nauczysz się w „Odpowiedzialne praktyki web scrapingu”?
Przestrzeganie robots.txt, nagłówki user agenta, opóźnienia między żądaniami i buforowanie. Ćwiczysz AI Agents z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć AI Agents?
Nie wymagamy żadnego doświadczenia. AI Agents w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Odpowiedzialne praktyki web scrapingu”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji AI Agents?
Tak. Każda lekcja AI Agents zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Klienty HTTP dla agentów: httpx i requests
- Parsowanie HTML za pomocą BeautifulSoup
- Obsługa paginacji i treści dynamicznych
- Odpowiedzialne praktyki web scrapingu