Intégration

Utilisez Shifter avec Beautiful Soup

Associez les proxies résidentiels et ISP de Shifter à Beautiful Soup pour un scraping Python propre et expressif. Beautiful Soup gère l'analyse HTML, Shifter gère les IPs résidentielles — aucun navigateur sans interface graphique requis.

Démarrage rapide

Installer

pip install beautifulsoup4 requests lxml

Utilisation de base

import requests
from bs4 import BeautifulSoup

proxy_url = "customer-USERNAME-country-us-sid-123ABC:PASSWORD@p.shifter.io:443"
proxies   = {"http": proxy_url, "https": proxy_url}

response = requests.get("https://example.com", proxies=proxies, timeout=30)
soup = BeautifulSoup(response.text, "lxml")

print(soup.title.string)
for article in soup.select("article.post"):
    print(article.h2.text.strip(), "->", article.a["href"])

Fonctionnalités

S'intègre parfaitement avec requests, httpx, aiohttp et tout client HTTP Python prenant en charge un dictionnaire proxies
Rotation par requête par défaut, avec `sid` pour les sessions persistantes et `ttl-N` pour des épinglages temporisés de N secondes
Compatible avec bs4 4.x et Python 3.7+ — fonctionne avec les backends lxml et html.parser
Ciblage géographique dans 195+ pays via des paramètres de nom d'utilisateur : pays, région, ville, ASN
Plusieurs fois plus rapide que le scraping par navigateur sans interface pour les cibles statiques ou légères en JS
Remplacement direct pour Scrapy, les scrapers FastAPI, les tâches Airflow, AWS Lambda et tout pipeline de données Python

Exemples

Session persistante + exploration multi-pages

Fixez une IP résidentielle pour l'ensemble d'un crawl paginé en ajoutant `sid-XXX` au nom d'utilisateur du proxy. Ajoutez `country-uk` et `city-london` pour le géociblage.

import requests
import secrets
from bs4 import BeautifulSoup
from urllib.parse import urljoin

sid = secrets.token_hex(4)

proxy_url = (
    f"customer-USERNAME-country-uk-city-london-sid-{sid}-ttl-300:"
    f"PASSWORD@p.shifter.io:443"
)

# Use a session so connection pooling and cookies persist across requests.
session = requests.Session()
session.proxies = {"http": proxy_url, "https": proxy_url}
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
    "Accept-Language": "en-GB,en;q=0.9",
})

products  = []
url       = "https://example.co.uk/products"

while url:
    response = session.get(url, timeout=30)
    soup     = BeautifulSoup(response.text, "lxml")

    for card in soup.select(".product-card"):
        products.append({
            "title": card.select_one("h2").text.strip(),
            "price": card.select_one(".price").text.strip(),
            "url":   urljoin(url, card.select_one("a")["href"]),
        })

    next_link = soup.select_one("a.next-page")
    url       = urljoin(url, next_link["href"]) if next_link else None

print(f"Scraped {len(products)} products")

Scraping parallèle avec concurrent.futures

Supprimez le sid pour une rotation par requête. ThreadPoolExecutor + requests + Shifter passe à des dizaines de récupérations simultanées sans déclencher les limites de débit par IP.

import requests
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor, as_completed

# No sid -> every request gets a different residential IP.
PROXY_URL = "customer-USERNAME-country-us:PASSWORD@p.shifter.io:443"

def scrape(url: str) -> dict:
    response = requests.get(
        url,
        proxies={"http": PROXY_URL, "https": PROXY_URL},
        headers={"User-Agent": "Mozilla/5.0 AppleWebKit/537.36"},
        timeout=30,
    )
    soup = BeautifulSoup(response.text, "lxml")

    return {
        "url":   url,
        "title": (soup.title.string or "").strip(),
        "h1":    [h.text.strip() for h in soup.select("h1")],
        "links": [a["href"] for a in soup.select("a[href]")[:20]],
    }

urls = [
    "https://example.com/category/laptops",
    "https://example.com/category/phones",
    "https://example.com/category/tablets",
    "https://example.com/category/wearables",
    # ... hundreds more
]

with ThreadPoolExecutor(max_workers=16) as pool:
    futures = {pool.submit(scrape, u): u for u in urls}
    for f in as_completed(futures):
        try:
            result = f.result()
            print(result["url"], "->", result["title"])
        except Exception as exc:
            print("error:", futures[f], exc)

Exploration robuste avec tentatives et recul exponentiel

Le scraping en production nécessite des tentatives sur les erreurs 5xx et les erreurs de connexion. Combinez urllib3 Retry avec Shifter et un nouveau sid par tentative pour contourner les blocages transitoires.

import requests
import secrets
from bs4 import BeautifulSoup
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

class ShifterClient:
    """requests.Session that rotates the residential IP on retry."""

    def __init__(self, country="us"):
        self.country = country
        self._session = requests.Session()

        retry = Retry(
            total=5,
            backoff_factor=1.5,
            status_forcelist=[429, 500, 502, 503, 504],
            allowed_methods=["GET", "POST", "HEAD"],
        )
        adapter = HTTPAdapter(max_retries=retry, pool_connections=20)
        self._session.mount("http://",  adapter)
        self._session.mount("https://", adapter)

    def _proxy(self) -> str:
        sid = secrets.token_hex(4)
        return (
            f"customer-USERNAME-country-{self.country}-sid-{sid}:"
            f"PASSWORD@p.shifter.io:443"
        )

    def get(self, url: str, **kwargs) -> requests.Response:
        return self._session.get(
            url,
            proxies={"http": self._proxy(), "https": self._proxy()},
            timeout=kwargs.pop("timeout", 30),
            **kwargs,
        )

client   = ShifterClient(country="de")
response = client.get("https://example.de/products")
soup     = BeautifulSoup(response.text, "lxml")

for product in soup.select(".product"):
    print(product.h2.text.strip(), product.select_one(".price").text.strip())

httpx (async) + Beautiful Soup

Si vous avez besoin d'une diffusion asynchrone pour des milliers de pages, remplacez requests par httpx. Même URL Shifter, async/await natif, compatibilité complète avec Beautiful Soup.

# pip install httpx beautifulsoup4 lxml
import asyncio
import httpx
from bs4 import BeautifulSoup

PROXY = "customer-USERNAME-country-fr-sid-789GHI:PASSWORD@p.shifter.io:443"

async def fetch(client: httpx.AsyncClient, url: str) -> dict:
    resp = await client.get(url, timeout=30)
    soup = BeautifulSoup(resp.text, "lxml")
    return {
        "url":      url,
        "title":    (soup.title.string or "").strip(),
        "headings": [h.text.strip() for h in soup.select("h2")],
    }

async def main():
    async with httpx.AsyncClient(proxy=PROXY) as client:
        urls = [
            f"https://example.fr/products?page={i}" for i in range(1, 51)
        ]
        results = await asyncio.gather(*[fetch(client, u) for u in urls])

    for r in results:
        print(r["url"], "->", r["title"])

asyncio.run(main())
FAQ

Questions fréquentes Questions FAQ

Questions fréquentes sur l'utilisation de Shifter avec Beautiful Soup.

Non. Beautiful Soup est un analyseur — il n'effectue pas de requêtes HTTP. Le proxy est configuré sur le client HTTP que vous associez à bs4 (requests, httpx, aiohttp, urllib). Une fois le HTML récupéré via Shifter, vous le transmettez à BeautifulSoup() comme d'habitude.

Commencer

Commencer à utiliser Shifter avec Beautiful Soup

Associez les 205M+ proxies résidentiels et ISP de Shifter à Beautiful Soup pour un scraping Python propre et expressif. Rotation par requête, sessions persistantes et prise en charge complète de l'asynchrone via httpx.

Essayez Shifter gratuitementConfiguration en quelques minutes. Annulez à tout moment.