I siti di notizie sono tra le risorse più protette su Internet. Cloudflare, limitazione della velocità, blocchi per IP: tutto ciò rende il parsing delle notizie una seria sfida tecnica. In questa guida vedremo come configurare correttamente i proxy per una raccolta dati stabile dai portali di notizie, quale tipo di proxy scegliere per diverse attività e come bypassare i moderni sistemi di protezione.
Perché i siti di notizie bloccano i parser
I portali di notizie sono particolarmente sensibili alla raccolta automatica di dati per diverse ragioni. In primo luogo, il contenuto è il loro principale attivo, che monetizzano attraverso la pubblicità e gli abbonamenti. Il parsing massivo consente ai concorrenti di copiare i materiali e riduce il traffico unico. In secondo luogo, l'elevato carico dei bot aumenta i costi per server e CDN.
I moderni siti di notizie utilizzano una protezione multilivello:
- Cloudflare e simili — controllano JavaScript, impronte TLS del browser, modelli comportamentali
- Limitazione della velocità — limitano il numero di richieste da un IP (di solito 10-50 richieste al minuto)
- Blocco per User-Agent — bloccano intestazioni standard delle librerie (Python-requests, curl)
- CAPTCHA — mostrano in caso di attività sospette
- Geoblock — alcuni portali di notizie sono accessibili solo da determinati paesi
I segni tipici con cui i siti di notizie rilevano i parser: lo stesso IP effettua molte richieste consecutive, assenza di JavaScript, ordine non standard delle intestazioni HTTP, velocità di richiesta troppo rapida (una persona non può aprire 10 pagine al secondo), assenza di cookie e referrer.
Importante: Il parsing dei siti di notizie si trova in una zona grigia. Controlla sempre il robots.txt e i Termini di Servizio della risorsa target. Per l'uso commerciale dei dati, è consigliabile utilizzare API ufficiali o stipulare accordi di partnership.
Quale tipo di proxy scegliere per il parsing delle notizie
La scelta del tipo di proxy dipende dalla scala del compito, dal budget e dal livello di protezione dei siti target. Consideriamo tre opzioni principali e la loro applicabilità per il parsing delle notizie.
| Tipo di proxy | Velocità | Costo | Quando utilizzare |
|---|---|---|---|
| Proxy dei data center | Alta (50-100 ms) | Basso | Siti senza Cloudflare, grande volume di dati, test |
| Proxy residenziali | Media (200-500 ms) | Alta | Siti con Cloudflare, protezione rigorosa, geotargeting |
| Proxy mobili | Media (300-600 ms) | Molto alta | Massima protezione, versioni mobili dei siti di notizie |
Proxy dei data center per il parsing delle notizie
Adatti per il parsing di siti di notizie senza protezione seria: pubblicazioni regionali, blog, piccoli portali informativi. Vantaggi: alta velocità (importante quando si esegue il parsing di centinaia di fonti), basso costo (è possibile affittare un pool di 50-100 IP), connessione stabile.
Svantaggi: facilmente rilevabili per ASN (appartenenza a un data center), spesso già inseriti nelle blacklist di grandi siti, non superano il Cloudflare Challenge nel 70% dei casi. Utilizzare i proxy dei data center per il parsing massivo di feed RSS, sitemap.xml, endpoint API o per la raccolta di metadati (intestazioni, date di pubblicazione) senza scaricare il contenuto completo.
Proxy residenziali — lo standard d'oro
I proxy residenziali sono indirizzi IP di utenti domestici reali, forniti dai provider di servizi Internet. Per i siti di notizie sembrano visitatori normali, il che è fondamentale quando si lavora con risorse protette.
Quando i proxy residenziali sono obbligatori: parsing di grandi portali di notizie (CNN, BBC, Reuters, RBC, Kommersant), siti dietro Cloudflare o protezioni simili, raccolta di dati da determinati paesi (geotargeting), sessioni prolungate con autenticazione. I proxy residenziali superano i controlli JavaScript di Cloudflare, hanno una reputazione IP pulita, supportano sessioni sticky (fissazione IP per 10-30 minuti).
Consiglio pratico: utilizzare proxy residenziali con rotazione temporale (sticky sessions), anziché per richiesta. Ad esempio, un IP funziona per 10 minuti, raccoglie 20-30 articoli, poi cambia. Questo appare più naturale rispetto al cambio di IP per ogni richiesta.
Proxy mobili per casi particolari
I proxy mobili utilizzano IP di operatori mobili (MTS, Beeline, Tele2). Hanno la massima fiducia, poiché milioni di persone utilizzano Internet mobile per leggere notizie. Applicali per il parsing delle versioni mobili dei siti di notizie (spesso hanno una protezione semplificata), siti con protezione estremamente rigorosa, pagine AMP di Google News.
Caratteristica dei proxy mobili: l'IP cambia spesso automaticamente (gli operatori mobili utilizzano CGNAT), un IP può appartenere a centinaia di utenti contemporaneamente, il che rende il blocco inutile. Svantaggio: alto costo, quindi utilizzali in modo mirato, solo per obiettivi altamente protetti.
Bypass di Cloudflare e altri sistemi anti-bot
Cloudflare è il principale nemico dei parser dei siti di notizie. Circa il 40% dei grandi portali di notizie utilizza Cloudflare per proteggersi dai bot. Le librerie standard (requests, urllib) non superano il controllo, poiché Cloudflare analizza l'impronta TLS, l'esecuzione di JavaScript, l'ordine delle intestazioni HTTP, i modelli comportamentali.
Strategie di bypass di Cloudflare
1. Browser headless (Selenium, Playwright, Puppeteer)
Emulano un vero browser con esecuzione di JavaScript. Cloudflare vede un'impronta TLS corretta di Chrome/Firefox e consente la richiesta. Svantaggi: lenti (2-5 secondi per pagina), richiedono molte risorse (RAM, CPU).
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# Configurazione del proxy per Selenium
chrome_options = Options()
chrome_options.add_argument('--proxy-server=http://username:password@proxy.example.com:8080')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
driver = webdriver.Chrome(options=chrome_options)
driver.get('https://news-site.com/article')
# Aspettiamo il caricamento di JavaScript
driver.implicitly_wait(10)
html = driver.page_source
driver.quit()
2. Librerie con TLS-fingerprinting (curl_cffi, tls-client)
Imitano l'impronta TLS di un vero browser senza avviare un browser headless. Funzionano 10-20 volte più velocemente di Selenium, ma non eseguono JavaScript. Adatte per siti con verifica di base di Cloudflare (senza JS-challenge).
from curl_cffi import requests
proxies = {
'http': 'http://username:password@proxy.example.com:8080',
'https': 'http://username:password@proxy.example.com:8080'
}
response = requests.get(
'https://news-site.com/article',
proxies=proxies,
impersonate='chrome110' # Imitazione dell'impronta TLS di Chrome 110
)
print(response.text)
3. Servizi di bypass di Cloudflare (scraperapi, scrapingbee)
API a pagamento che bypassano automaticamente Cloudflare. Inviate l'URL, restituiscono l'HTML pronto. Vantaggi: non è necessario comprendere i dettagli tecnici, rotazione automatica dei proxy, gestione dei CAPTCHA. Svantaggi: costosi per grandi volumi (da $50/mese per 100K richieste).
Intestazioni HTTP corrette
Anche con i proxy è importante inviare intestazioni corrette, altrimenti il sito rileverà il bot per un User-Agent non standard o l'assenza di Accept-Language.
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
'Accept-Encoding': 'gzip, deflate, br',
'DNT': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Cache-Control': 'max-age=0'
}
Aggiorna periodicamente l'User-Agent: utilizza versioni aggiornate dei browser. Puoi controllare la tua impronta su siti come whoer.net o browserleaks.com.
Configurazione della rotazione IP e gestione delle richieste
La corretta rotazione dei proxy è la chiave per un parsing stabile senza blocchi. I siti di notizie monitorano la frequenza delle richieste da un IP, e superare il limite porta a un ban temporaneo o permanente.
Tipi di rotazione dei proxy
Rotazione per richieste — ogni richiesta passa attraverso un nuovo IP. Adatta per il parsing rapido di un gran numero di siti diversi, minimizza il rischio di ban per frequenza di richieste. Svantaggi: non adatta per siti con sessioni (cookie, autenticazione), può apparire sospetta per alcune protezioni.
Rotazione per tempo (sticky sessions) — un IP viene utilizzato per un tempo fisso (5-30 minuti), poi cambia. Adatta per il parsing di un singolo portale di notizie con molte pagine, mantiene i cookie e le sessioni, appare come il comportamento di un utente reale. Raccomandata per la maggior parte delle attività di parsing delle notizie.
Rotazione per geolocalizzazione — cambio di IP da diversi paesi/città. Utilizzata per il parsing di contenuti geodipendenti (notizie regionali), bypass delle geoblock.
Frequenza ottimale delle richieste
Anche con la rotazione dei proxy non è possibile effettuare richieste troppo frequentemente. Intervalli sicuri per diversi tipi di siti:
- Grandi portali di notizie (RBC, Kommersant, Vedomosti) — 2-5 secondi tra le richieste da un IP
- Siti medi — 1-3 secondi
- Piccoli blog e pubblicazioni regionali — 0.5-1 secondo
Aggiungi ritardi casuali (randomization) per rendere il modello delle richieste più naturale:
import time
import random
def fetch_article(url, proxies):
response = requests.get(url, proxies=proxies, headers=headers)
# Ritardo casuale da 2 a 5 secondi
delay = random.uniform(2, 5)
time.sleep(delay)
return response.text
Esempio di rotazione dei proxy da un pool
Se hai un elenco di proxy, puoi implementare una semplice rotazione manualmente:
import itertools
import requests
# Pool di proxy
proxy_list = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080',
]
# Creiamo un iteratore infinito
proxy_pool = itertools.cycle(proxy_list)
def get_next_proxy():
proxy = next(proxy_pool)
return {'http': proxy, 'https': proxy}
# Utilizzo
urls = ['https://news1.com/article', 'https://news2.com/article']
for url in urls:
proxies = get_next_proxy()
response = requests.get(url, proxies=proxies, headers=headers)
print(f'Fetched {url} via {proxies["http"]}')
Esempi di codice: Python + Scrapy + proxy
Scrapy è un framework professionale per il parsing che supporta nativamente proxy, middleware, rotazione e gestione degli errori. Consideriamo un esempio completo di un parser di un sito di notizie con rotazione dei proxy.
Installazione delle dipendenze
pip install scrapy scrapy-rotating-proxies
Configurazione di Scrapy con proxy (settings.py)
# settings.py
# Attiviamo il middleware per la rotazione dei proxy
ROTATING_PROXY_LIST = [
'http://user:pass@proxy1.example.com:8080',
'http://user:pass@proxy2.example.com:8080',
'http://user:pass@proxy3.example.com:8080',
]
DOWNLOADER_MIDDLEWARES = {
'rotating_proxies.middlewares.RotatingProxyMiddleware': 610,
'rotating_proxies.middlewares.BanDetectionMiddleware': 620,
}
# Impostazioni per bypassare i blocchi
CONCURRENT_REQUESTS = 8 # Non più di 8 richieste simultanee
DOWNLOAD_DELAY = 2 # Ritardo di 2 secondi tra le richieste
RANDOMIZE_DOWNLOAD_DELAY = True # Ritardo casuale
# User-Agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
# Tentativi di ripetizione in caso di errori
RETRY_TIMES = 3
RETRY_HTTP_CODES = [500, 502, 503, 504, 408, 429]
Spider per il parsing delle notizie
# news_spider.py
import scrapy
from datetime import datetime
class NewsSpider(scrapy.Spider):
name = 'news_parser'
# Elenco dei siti di notizie per il parsing
start_urls = [
'https://example-news.com/latest',
]
def parse(self, response):
# Parsing dell'elenco degli articoli nella pagina principale
articles = response.css('article.news-item')
for article in articles:
article_url = article.css('a.title::attr(href)').get()
if article_url:
# Passiamo alla pagina dell'articolo
yield response.follow(article_url, callback=self.parse_article)
def parse_article(self, response):
# Estraiamo i dati dell'articolo
yield {
'url': response.url,
'title': response.css('h1.article-title::text').get(),
'date': response.css('time.published::attr(datetime)').get(),
'author': response.css('span.author::text').get(),
'text': ' '.join(response.css('div.article-body p::text').getall()),
'tags': response.css('a.tag::text').getall(),
'scraped_at': datetime.now().isoformat(),
}
Avvio del parser
# Salvataggio in JSON
scrapy crawl news_parser -o news_data.json
# Salvataggio in CSV
scrapy crawl news_parser -o news_data.csv
Parser semplice con requests + BeautifulSoup
Se non è necessaria una logica complessa, puoi utilizzare la combinazione requests + BeautifulSoup:
import requests
from bs4 import BeautifulSoup
import time
import random
# Configurazione del proxy
proxies = {
'http': 'http://user:pass@proxy.example.com:8080',
'https': 'http://user:pass@proxy.example.com:8080'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
def parse_news_article(url):
try:
response = requests.get(url, proxies=proxies, headers=headers, timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# Estrazione dei dati (i selettori dipendono dal sito)
title = soup.find('h1', class_='article-title').text.strip()
date = soup.find('time', class_='published')['datetime']
text = ' '.join([p.text for p in soup.find_all('p', class_='article-text')])
return {
'url': url,
'title': title,
'date': date,
'text': text
}
except Exception as e:
print(f'Error parsing {url}: {e}')
return None
# Parsing dell'elenco degli articoli
urls = [
'https://news-site.com/article-1',
'https://news-site.com/article-2',
]
for url in urls:
article_data = parse_news_article(url)
if article_data:
print(article_data)
# Ritardo tra le richieste
time.sleep(random.uniform(2, 4))
Errori comuni nel parsing delle notizie
Anche con la corretta configurazione dei proxy, i parser ricevono spesso blocchi a causa di errori tecnici. Esaminiamo i problemi più comuni e le loro soluzioni.
Errore 1: Frequenza delle richieste troppo alta
Sintomi: HTTP 429 (Too Many Requests), ban temporanei dell'IP, CAPTCHA. Causa: il parser effettua 10-50 richieste al secondo da un IP. Soluzione: aggiungere ritardi (time.sleep()), utilizzare DOWNLOAD_DELAY in Scrapy, limitare CONCURRENT_REQUESTS.
Errore 2: Utilizzo di un solo proxy per tutte le richieste
Sintomi: il proxy viene rapidamente bannato, anche con ritardi. Causa: un solo IP effettua centinaia di richieste a un sito. Soluzione: utilizzare un pool di proxy con rotazione, per grandi siti — almeno 10-20 proxy, per sessioni sticky cambiare IP ogni 10-15 minuti.
Errore 3: Ignorare i cookie
Molti siti di notizie impostano cookie al primo accesso e controllano la loro presenza nelle richieste successive. L'assenza di cookie è un segno di bot. Soluzione: utilizzare requests.Session() per salvare automaticamente i cookie, in Scrapy attivare COOKIES_ENABLED = True.
import requests
session = requests.Session()
session.proxies = {'http': 'http://proxy.com:8080', 'https': 'http://proxy.com:8080'}
# Prima richiesta — otteniamo i cookie
response1 = session.get('https://news-site.com')
# Le richieste successive inviano automaticamente i cookie
response2 = session.get('https://news-site.com/article')
Errore 4: Gestione errata dei reindirizzamenti
I siti di notizie utilizzano spesso reindirizzamenti (301, 302) per versioni mobili, sottodomini regionali, pagine AMP. Se il parser non segue i reindirizzamenti, ottiene una pagina vuota. Soluzione: in requests è abilitato per impostazione predefinita (allow_redirects=True), controlla l'URL finale tramite response.url.
Errore 5: Parsing di contenuti dinamici senza JavaScript
Molti moderni siti di notizie caricano contenuti tramite JavaScript (React, Vue). La libreria requests ottiene solo uno scheletro HTML vuoto senza articoli. Soluzione: utilizzare Selenium/Playwright per eseguire JavaScript, controlla la rete in DevTools — è possibile che i dati vengano caricati tramite API (puoi fare parsing direttamente in JSON).
Scalabilità: parsing di centinaia di fonti
Quando è necessario fare parsing non di un solo sito di notizie, ma di centinaia di fonti contemporaneamente (aggregatori di notizie, monitoraggio dei media), è necessaria un'architettura scalabile.
Parsing distribuito con Scrapy Cloud
Scrapy Cloud (creato dagli sviluppatori di Scrapy) consente di eseguire parser nel cloud con scalabilità automatica. Vantaggi: non sono necessari server propri, rotazione automatica dei proxy, monitoraggio e log. Costo: a partire da $9/mese per il piano base.
Code di lavoro (Celery + Redis)
Per il dispiegamento autonomo utilizza Celery — un sistema di task distribuiti. Architettura: Redis memorizza la coda degli URL per il parsing, più worker (server) prelevano i task dalla coda e fanno parsing in parallelo, ogni worker utilizza il proprio pool di proxy.
# tasks.py
from celery import Celery
import requests
app = Celery('news_parser', broker='redis://localhost:6379/0')
@app.task
def parse_article(url, proxy):
proxies = {'http': proxy, 'https': proxy}
response = requests.get(url, proxies=proxies, timeout=10)
# Parsing e salvataggio dei dati
return response.text
# Aggiunta di task alla coda
urls = ['https://news1.com/article', 'https://news2.com/article']
proxies = ['http://proxy1.com:8080', 'http://proxy2.com:8080']
for url in urls:
proxy = random.choice(proxies)
parse_article.delay(url, proxy) # Esecuzione asincrona
Monitoraggio e gestione degli errori
Nel parsing su larga scala, il monitoraggio è fondamentale: quanti URL sono stati elaborati, quanti errori, quali proxy sono stati bannati. Utilizza Sentry per il monitoraggio degli errori Python, Grafana + Prometheus per le metriche (richieste al secondo, tempo di risposta), logging in ELK Stack (Elasticsearch, Logstash, Kibana).
Consiglio: Crea un sistema di verifica automatica dei proxy. Ogni 5-10 minuti invia una richiesta di test tramite ogni proxy su whoer.net o httpbin.org. Se il proxy non risponde o è bannato — escludilo dal pool e aggiungi un nuovo proxy.
Ottimizzazione dei costi per i proxy
Quando si fa parsing di centinaia di fonti, i costi per i proxy possono raggiungere migliaia di dollari al mese. Strategie di ottimizzazione: utilizza proxy dei data center per siti semplici (RSS, API), proxy residenziali solo per quelli protetti, memorizza i dati — non fare parsing dello stesso articolo due volte, effettua il parsing in orari non di punta (di notte il carico sui siti è inferiore, minore rischio di ban).
Esempio: per il parsing di 500 siti di notizie, puoi utilizzare l'80% di proxy dei data center (per RSS e siti semplici) e il 20% di proxy residenziali (per i primi 100 portali protetti). Questo ridurrà i costi di 3-5 volte.
Conclusione
Il parsing dei siti di notizie è un compito tecnicamente complesso, che richiede la scelta corretta dei proxy, la configurazione della rotazione e il bypass dei sistemi anti-bot. Le conclusioni chiave dell'articolo: per portali di notizie protetti (Cloudflare, limitazione rigorosa della velocità) utilizza proxy residenziali con sticky sessions, per il parsing massivo di centinaia di fonti sono adatti i proxy dei data center con rotazione rapida, assicurati di aggiungere ritardi tra le richieste (2-5 secondi) e intestazioni HTTP corrette, per bypassare Cloudflare utilizza browser headless (Selenium, Playwright) o librerie con TLS-fingerprinting.
Quando si scala, utilizza sistemi distribuiti (Celery, Scrapy Cloud) e monitoraggio degli errori. Ricorda che il parsing deve essere etico: rispetta il robots.txt, non creare un carico eccessivo sui server e rispetta i diritti d'autore sui contenuti.
Se prevedi di fare parsing di grandi portali di notizie con protezione Cloudflare, ti consigliamo di utilizzare proxy residenziali — offrono un alto livello di fiducia e un rischio minimo di blocchi. Per attività in cui la velocità e il volume dei dati sono importanti (parsing di RSS, endpoint API), sono adatti proxy dei data center.