Meteen naar de inhoud

Hoe u kunt webscrapen met HTTPX en Python

Webscrapen is het proces waarbij automatisch gegevens van websites worden geëxtraheerd. Het is een veelgebruikte techniek die wordt gebruikt om grote hoeveelheden gegevens te verzamelen voor analyse, machinaal leren en meer. In Python zijn er veel geweldige bibliotheken die webscrapen eenvoudig maken. Een populaire optie is HTTPX.

HTTPX is een krachtige en moderne HTTP-client voor Python. Het is gemaakt door de ontwikkelaars achter Requests en haalt veel inspiratie uit Requests, terwijl het ook nieuwe functionaliteit toevoegt, zoals HTTP/2-ondersteuning.

In deze uitgebreide handleiding onderzoeken we hoe u effectief websites in Python kunt schrapen met behulp van HTTPX.

Aan de slag met HTTPX

Om te beginnen kan HTTPX worden geïnstalleerd via pip:

pip install httpx

Als alternatief kan poëzie worden gebruikt:

poetry add httpx

Eenmaal geïnstalleerd, kan HTTPX worden geïmporteerd en gebruikt:

import httpx

response = httpx.get(‘https://example.com‘)
print(response.text)

Hierdoor wordt een GET-verzoek ingediend bij example.com en wordt de HTML van de startpagina afgedrukt.

HTTPX heeft een eenvoudige API en ondersteunt alle populaire HTTP-werkwoorden zoals GET, POST, PUT, DELETE, HEAD, OPTIONS, enz.

Enkele belangrijke kenmerken zijn:

  • HTTP/1.1- en HTTP/2-ondersteuning
  • Asynchrone API in aiohttp-stijl
  • Verbindingspooling en keepalive
  • Proxy-ondersteuning
  • Time-outconfiguratie
  • Cookie-persistentie
  • Bekende API in verzoekstijl

Laten we vervolgens eens kijken naar enkele veelvoorkomende gebruikspatronen.

Verzoeken indienen met HTTPX

Om een ​​GET-verzoek in te dienen, moet de httpx.get() methode kan worden gebruikt:

response = httpx.get(‘https://example.com‘)

Evenzo httpx.post(), httpx.put(), httpx.delete(), etc. kunnen worden gebruikt voor andere HTTP-werkwoorden.

Parameters zoals headers, cookies, time-out, etc. kunnen worden doorgegeven als trefwoordargumenten:

response = httpx.get(
  ‘https://httpbin.org/headers‘,
  headers = {
    ‘User-Agent‘: ‘MyBot 1.0‘
  },
  timeout = 10.0
)

Het antwoord bevat eigenschappen zoals status_code, headers, text, json()etc:

print(response.status_code)
print(response.headers)
print(response.text)
json = response.json()

U kunt het antwoord ook incrementeel streamen door het antwoordobject te herhalen.

Een HTTPX-client gebruiken

Voor de meeste schraaptaken wordt het gebruik van een persistent httpx.Client aanleg.

De client verwerkt zaken als het poolen van verbindingen, sessies, cookies, enz. voor meerdere verzoeken.

import httpx

client = httpx.Client()

response = client.get(‘https://example.com‘)
print(response.text)

response = client.get(‘https://httpbin.org/cookies/set?name=foo‘)
print(response.text) 

response = client.get(‘https://httpbin.org/cookies‘)
print(response.json())

Hier doen we meerdere verzoeken met dezelfde client, die de cookie-persistentie automatisch afhandelt.

U kunt ook opties zoals headers, proxy's, auth, enz. configureren bij het maken van de client:

client = httpx.Client(
  headers = {
    ‘User-Agent‘: ‘MyBot 1.0‘,
    ‘Authorization‘: ‘Bearer xxx‘   
  },
  proxies = ‘http://192.168.1.1:8181/‘,
  auth = (‘username‘, ‘password‘)
)

Laten we nu asynchroon kijken naar het maken van verzoeken.

Asynchrone verzoeken met HTTPX

Om verzoeken asynchroon in Python te kunnen doen, biedt HTTPX een AsyncClient:

import httpx

async with httpx.AsyncClient() as client:
  response = await client.get(‘https://example.com‘) 

Wij gebruiken async with om de client te initialiseren, await op verzoek en sluit de client daarna automatisch af.

Om meerdere URL's tegelijkertijd te schrapen, kunnen we gebruiken asyncio.gather():

import httpx
import asyncio

async def get_url(url):
  async with httpx.AsyncClient() as client:
    response = await client.get(url)
    return response.text

urls = [‘https://example.com‘, ‘https://httpbin.org‘, ‘https://python.org‘]

async def main():
  responses = await asyncio.gather(*[get_url(url) for url in urls])
  print(responses)

asyncio.run(main())

asyncio.gather() wacht tegelijkertijd op meerdere coroutines en retourneert resultaten in de volgorde van de verwachte resultaten.

Er zijn ook andere opties zoals asyncio.as_completed() om ze te verwerken zodra ze zijn voltooid:

tasks = [get_url(url) for url in urls]

async def main():
  for result in asyncio.as_completed(tasks):
    print(await result)

Async IO maakt het gelijktijdig ophalen van meerdere pagina's in één keer mogelijk, wat handig is om het scrapen te versnellen.

Laten we vervolgens eens kijken naar het schrapen van gegevens uit HTML- en JSON-reacties.

HTML- en JSON-reacties schrapen

Voor HTML-scraping kunnen we een parser zoals Beautiful Soup gebruiken om gegevens te extraheren:

from bs4 import BeautifulSoup

response = httpx.get(‘https://en.wikipedia.org/wiki/Python_(programming_language)‘)

soup = BeautifulSoup(response.text, ‘html.parser‘)

for link in soup.select(‘.toctext‘):
  print(link.text.strip())

Hiermee wordt de inhoud van de inhoudsopgave van de Wikipedia-pagina afgedrukt.

Voor JSON-antwoorden biedt HTTPX een ingebouwd .json() methode:

response = httpx.get(‘https://api.github.com/repos/encode/httpx‘)

json = response.json()
print(json[‘description‘])

De json= parameter kan ook worden gebruikt om JSON-gegevens in verzoeken te serialiseren.

Samen met een parser kunnen we scrapers bouwen om gegevens uit API’s en websites te extraheren.

Problemen en fouten afhandelen

Tijdens het scrapen komen er vaak problemen naar voren zoals verbindingsfouten, time-outs, snelheidslimieten, enz.

HTTPX biedt uitzonderingen en hulpmiddelen om deze op de juiste manier af te handelen.

Time-outs

Om trage reacties af te handelen, kunt u een gewoonte opgeven timeout parameter. De standaardwaarde is 5 seconden.

response = httpx.get(‘https://example.com‘, timeout=10.0) 

Indien dit wordt overschreden, wordt a httpx.TimeoutException voordoet:

try:
  response = httpx.get(‘https://example.com‘, timeout=0.001)
except httpx.TimeoutException:
  print(‘Request timed out‘)

Voor bepaalde sites of pagina's kunnen langere time-outs nodig zijn.

HTTP-fouten

Voor HTTP-fouten zoals 400, 500 enz. wordt het response.raise_for_status() methode kan worden gebruikt:

try:
  response = httpx.get(‘https://httpbin.org/status/500‘)
  response.raise_for_status()
except httpx.HTTPStatusError:
  print(‘HTTP Error occurred‘)  

Hierdoor ontstaat er een uitzondering op elke 4xx- of 5xx-statuscode.

Aanvragen opnieuw proberen

Om logica voor opnieuw proberen toe te voegen, kunnen externe pakketten zoals tenacity kunnen worden gebruikt:

from tenacity import retry, stop_after_attempt

@retry(stop=stop_after_attempt(3))
def make_request():
  response = httpx.get(‘https://example.com‘)
  response.raise_for_status()
  return response.json()

data = make_request()

Hier proberen we het bij elke uitzondering maximaal 3 keer opnieuw. Er kan ook meer geavanceerde logica voor opnieuw proberen worden gedefinieerd.

Limieten voor parallelle verzoeken

Wanneer u veel verzoeken tegelijkertijd indient, kunt u verbindingslimieten tegenkomen.

De limits parameter kan worden gebruikt om opties zoals maximale verbindingen te configureren:

client = httpx.AsyncClient(
  limits = httpx.Limits(max_connections=20)
)

Door deze parameter af te stemmen op de doelsite kunnen limieten worden vermeden.

Door deze veelvoorkomende problemen aan te pakken, kunnen veerkrachtiger schrapers worden gebouwd.

Best practices schrappen

Hier zijn enkele tips voor het maken van effectieve webschrapers met HTTPX:

  • Gebruik een HTTPX-client – Klanten bieden verbindingspooling, cookie-persistentie en andere voordelen.

  • Schraap beleefd – Beperk de aanvraagsnelheid om overweldigende servers te voorkomen. Gebruik willekeurige vertragingen en beperking.

  • Fouten afhandelen – Gebruik try/except-blokken, statuscontroles en nieuwe pogingen om problemen op te lossen.

  • Gebruik Asynchrone IO – Schraap pagina's gelijktijdig om de snelheid te verbeteren. Maar beperk gelijktijdigheid om verboden te voorkomen.

  • Willekeurige gebruikersagenten – Roteer willekeurige tekenreeksen van user-agents om er menselijker uit te zien.

  • Gebruik proxy's – Roteer verschillende proxy’s/IP’s om verzoeken te distribueren.

  • Cache- en persistente gegevens – Sla geschraapte gegevens op in bestanden/databases om opnieuw schrappen te voorkomen.

Door dit soort best practices te volgen, kunnen robuustere en onderhoudbare scrapers worden gebouwd.

Geavanceerde schraaptechnieken

Laten we eens kijken naar enkele meer geavanceerde scrapingmogelijkheden van HTTPX.

Authenticatiepagina's schrapen

Om geauthenticeerde pagina's te schrapen, ondersteunt HTTPX meerdere verificatietypen, zoals Basic, Digest en Bearer-authenticatie:

client = httpx.Client(
  auth = (‘username‘, ‘password‘)
)

response = client.get(‘https://api.example.com/users/me‘)

Authenticatiegegevens worden automatisch bij alle aanvragen bewaard.

Omgaan met cookies

De cookies parameter kan worden gebruikt om aangepaste cookies te verzenden:

client = httpx.Client(
  cookies = {
    ‘sessionId‘: ‘xxxx‘
  }
)

response = client.get(‘https://example.com/dashboard‘) 

En cookies die door de server zijn ingesteld, blijven automatisch in de client aanwezig.

Streaming reacties

Voor grote reacties kunt u deze stapsgewijs streamen door het responsobject te herhalen:

response = client.get(‘https://example.com/bigfile‘)
for chunk in response:
  process(chunk) 

Dit voorkomt dat u het gehele antwoord in het geheugen moet laden.

Proxy-ondersteuning

Om verzoeken via een proxyserver te routeren, moet de proxies parameter kan worden gebruikt:

proxy = ‘http://192.168.0.1:8888‘ 

client = httpx.Client(proxies = {‘http‘: proxy, ‘https‘: proxy})

Door verschillende proxy's te roteren, kunnen verzoeken van verschillende IP's worden gedistribueerd.

Aangepaste kopteksten

U kunt verzoekheaders zoals user-agents spoofen of willekeurig maken:

client = httpx.Client(headers = {
  ‘User-Agent‘: ‘MyBot 1.0‘ 
})

Dit bootst headers van een echte browser na.

Via deze meer geavanceerde functies kunnen robuuste scrapers worden gebouwd met behulp van HTTPX en Python.

Voorbeeld schrapers

Laten we nu eens kijken naar enkele voorbeeldschrapers die met HTTPX zijn gebouwd.

Reddit API-scraper

Hier is een basisschraper voor de Reddit API:

import httpx

client = httpx.Client()

subreddit = ‘python‘ 
listing = ‘hot‘
limit = 10

response = client.get(f‘https://www.reddit.com/r/{subreddit}/{listing}.json?limit={limit}‘)

data = response.json()[‘data‘]

for post in data[‘children‘]:
   title = post[‘data‘][‘title‘]
   score = post[‘data‘][‘score‘]
   print(f"{title} (Score: {score})")

Hiermee worden gegevens over de topberichten van de Python-subreddit opgehaald. De API retourneert JSON die we kunnen parseren.

We zouden deze scraper kunnen uitbreiden om gegevens uit meerdere subreddits te extraheren, resultaten in een database op te slaan, enz.

Nieuwsartikelschraper

Hier is een eenvoudige nieuwsschraper die artikelen van een site haalt:

from bs4 import BeautifulSoup
import httpx

client = httpx.Client()

response = client.get("https://example.com/news")
soup = BeautifulSoup(response.text, ‘html.parser‘)

for article in soup.select(‘.article‘):

  title = article.select_one(‘.article-title‘).text
  content = article.select_one(‘.article-content‘).text

  print(title) 
  print(content)
  print() 

Dit vindt alles .article elementen, extraheert de titel- en inhoudsvelden en drukt de artikelen af.

Opnieuw kan dit worden uitgebreid om extra velden te schrapen, datums te ontleden, op te slaan in een database, enz.

Zoekresultaten Schraper

En hier is een voorbeeldschraper voor de zoekresultaten van Google:

import httpx

query = "httpx python"
url = f"https://www.google.com/search?q={query}"

client = httpx.Client()
response = client.get(url)

from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text, ‘html.parser‘)

for result in soup.select(‘.tF2Cxc‘):

  title = result.select_one(‘.DKV0Md‘).text
  link = result.select_one(‘.yuRUbf a‘)[‘href‘]

  print(title)
  print(link) 
  print()

Hiermee wordt op Google gezocht naar een bepaalde zoekopdracht, worden de resultaatlinks/titels ontleed en worden ze afgedrukt.

Opnieuw kunnen er veel verbeteringen worden aangebracht, zoals het extraheren van zoekresultaten, extra velden, het schrapen van resultaatpagina's, het detecteren van captcha's, enz.

Deze voorbeelden demonstreren algemene scraping-patronen met HTTPX. Dezelfde technieken kunnen worden toegepast om scrapers voor veel websites en API's te bouwen.

Samengevat

Samenvattend biedt HTTPX een krachtige HTTP-client voor het bouwen van Python-webschrapers. Hier zijn enkele belangrijke punten:

  • HTTPX heeft een eenvoudige API in verzoekstijl voor het doen van verzoeken.

  • Asynchrone ondersteuning maakt het gelijktijdig indienen van verzoeken mogelijk.

  • Robuuste foutafhandeling met time-outs, nieuwe pogingen en statuscontroles.

  • Schraap eenvoudig HTML-pagina's met Beautiful Soup en JSON API's.

  • Persistente clients bieden verbindingspooling, sessies en cookie-afhandeling.

  • Geavanceerde technieken zoals proxy's, headers en auth maken geavanceerde scrapers mogelijk.

  • Volg best practices zoals het gebruik van beperking, willekeurige vertragingen en user-agents.

HTTPX maakt het gemakkelijk om te beginnen met scrapen met Python. Met robuuste foutafhandeling en asynchrone gelijktijdigheid kunnen schaalbare scrapers worden ontwikkeld.

Probeer HTTPX eens uit bij uw volgende Python-webscraping-project!

Tags:

Doe mee aan het gesprek

Uw e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd *