Web scraping adalah metode yang efektif untuk mengekstrak data dari web. Banyak pengembang lebih suka menggunakan pustaka permintaan Python untuk menjalankan proyek web scraping karena sederhana dan efektif. Namun, meskipun bagus, request library memiliki keterbatasan. Salah satu masalah umum yang mungkin kita temui dalam web scraping adalah request yang gagal, yang sering menyebabkan ekstraksi data yang tidak stabil. Pada artikel ini, kita akan membahas proses implementasi request retries di Python, sehingga Anda dapat menangani kesalahan HTTP dan menjaga skrip web scraping Anda tetap stabil dan dapat diandalkan.
Mari kita siapkan lingkungan kita terlebih dahulu. Pastikan Anda telah menginstal Python dan IDE pilihan Anda. Kemudian instal library request jika Anda belum memilikinya.
pip install requests
Setelah terinstal, mari kita kirim permintaan ke example.com menggunakan modul permintaan Python. Berikut ini adalah fungsi sederhana yang melakukan hal tersebut:
import requests
def send_request(url):
"""
Mengirimkan permintaan HTTP GET ke URL yang ditentukan dan mencetak kode status respons.
Parameters:
url (str): URL untuk mengirim permintaan.
"""
response = requests.get(url)
print('Response Status Code: ', response.status_code)
send_request('https://example.com')
Output kode ditunjukkan di bawah ini:
Mari kita lihat lebih dekat kode status HTTP untuk memahaminya dengan lebih baik.
Server merespons permintaan HTTP dengan kode status yang menunjukkan hasil permintaan. Berikut adalah ikhtisar singkatnya:
Dalam contoh kita, kode status 200 berarti permintaan ke https://example.com telah selesai. Ini adalah cara server untuk mengatakan, "Semuanya baik-baik saja di sini, permintaan Anda berhasil".
Kode status ini juga dapat berperan dalam deteksi bot dan menunjukkan kapan akses dibatasi karena perilaku seperti bot.
Di bawah ini adalah ikhtisar singkat kode kesalahan HTTP yang terutama terjadi karena masalah deteksi dan autentikasi bot.
Sekarang mari kita tulis mekanisme percobaan ulang sederhana di Python untuk membuat permintaan HTTP GET dengan pustaka permintaan. Ada kalanya permintaan jaringan gagal karena masalah jaringan atau server yang kelebihan beban. Jadi, jika permintaan kita gagal, kita harus mencoba ulang permintaan tersebut.
Fungsi send_request_with_basic_retry_mechanism membuat permintaan HTTP GET ke URL yang diberikan dengan mekanisme percobaan ulang dasar yang hanya akan mencoba kembali jika terjadi pengecualian jaringan atau permintaan seperti kesalahan koneksi. Mekanisme ini akan mencoba ulang permintaan sebanyak maksimal max_retries kali. Jika semua percobaan gagal dengan pengecualian seperti itu, maka akan memunculkan pengecualian terakhir yang ditemui.
import requests
import time
def send_request_with_basic_retry_mechanism(url, max_retries=2):
"""
Mengirimkan permintaan HTTP GET ke URL dengan mekanisme percobaan ulang dasar.
Parameters:
url (str): URL untuk mengirim permintaan.
max_retries (int): Jumlah maksimum untuk mencoba kembali permintaan.
Raises:
requests.RequestException: Memunculkan pengecualian terakhir jika semua percobaan ulang gagal.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
print('Response status: ', response.status_code)
break # Keluar dari loop jika permintaan berhasil
except requests.RequestException as error:
print(f"Attempt {attempt+1} failed:", error)
if attempt < max_retries - 1:
print(f"Retrying...")
time.sleep(delay) # Tunggu sebelum mencoba kembali
else:
print("Max retries exceeded.")
# Naikkan kembali pengecualian terakhir jika percobaan ulang maksimum tercapai
raise
send_request_with_basic_retry_mechanism('https://example.com')
Sekarang mari kita mengadaptasi mekanisme percobaan ulang dasar untuk menangani skenario di mana situs web yang ingin kita scrape mengimplementasikan mekanisme deteksi bot yang dapat mengakibatkan pemblokiran. Untuk menangani skenario seperti itu, kita perlu mencoba ulang permintaan dengan tekun beberapa kali, karena mungkin bukan hanya pemblokiran karena deteksi bot tetapi juga karena masalah jaringan atau server.
Fungsi di bawah ini send_request_with_advance_retry_mechanism mengirim permintaan HTTP GET ke URL yang disediakan dengan upaya percobaan ulang opsional dan penundaan percobaan ulang. Fungsi ini mencoba mengirim permintaan beberapa kali untuk jumlah percobaan yang ditentukan dan mencetak kode status respons jika permintaan berhasil mendapatkan respons. Jika menemukan kesalahan selama operasi permintaan, ia akan mencetak pesan kesalahan dan mencobanya kembali. Ia menunggu penundaan percobaan ulang yang ditentukan di antara setiap percobaan. Jika permintaan gagal bahkan setelah jumlah percobaan ulang yang ditentukan, maka akan memunculkan pengecualian terakhir yang ditemui.
Parameter penundaan penting karena menghindari membombardir server dengan banyak permintaan dalam waktu yang berdekatan. Sebaliknya, ia menunggu server memiliki cukup waktu untuk memproses permintaan, membuat server berpikir bahwa manusia dan bukan bot yang membuat permintaan. Jadi, mekanisme percobaan ulang harus ditunda untuk menghindari server yang kelebihan beban atau respons server yang lambat yang dapat memicu mekanisme anti-bot.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1):
"""
Mengirimkan permintaan HTTP GET ke URL yang ditentukan dengan mekanisme percobaan ulang tingkat lanjut.
Parameters:
url (str): URL untuk mengirim permintaan.
max_retries (int): Jumlah maksimum untuk mencoba ulang permintaan. Standarnya adalah 3.
delay (int): Penundaan (dalam detik) di antara percobaan ulang. Standarnya adalah 1.
Raises:
requests.RequestException: Memunculkan pengecualian terakhir jika semua percobaan ulang gagal.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Membuat pengecualian untuk kode status 4xx atau 5xx
response.raise_for_status()
print('Response Status Code:', response.status_code)
except requests.RequestException as e:
# Mencetak pesan kesalahan dan nomor percobaan jika permintaan gagal
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
# Cetak pesan coba ulang dan tunggu sebelum mencoba kembali
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
# Jika percobaan ulang maksimum terlampaui, cetak pesan dan naikkan kembali pengecualian
print("Max retries exceeded.")
raise
# Contoh penggunaan
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Berikut ini adalah kode yang telah diperbaiki bersama dengan komentar yang membahas kekurangannya:
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Mengirimkan permintaan HTTP GET ke URL yang ditentukan dengan mekanisme percobaan ulang tingkat lanjut.
Parameters:
url (str): URL untuk mengirim permintaan.
max_retries (int): Jumlah maksimum untuk mencoba ulang permintaan. Standarnya adalah 3.
delay (int): Penundaan (dalam detik) di antara percobaan ulang. Standarnya adalah 1.
min_content_length (int): Panjang minimum konten respons yang dianggap valid. Standarnya adalah 10.
Raises:
requests.RequestException: Memunculkan pengecualian terakhir jika semua percobaan ulang gagal.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Membuat pengecualian untuk kode status 4xx atau 5xx
response.raise_for_status()
# Periksa apakah kode status respons adalah 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Keluar dari perulangan untuk kesalahan 404
# Periksa apakah panjang teks respons kurang dari panjang konten minimum yang ditentukan
if len(response.text) < min_content_length:
print("Response text length is less than specified minimum. Retrying...")
time.sleep(delay)
continue # Coba lagi permintaan tersebut
print('Response Status Code:', response.status_code)
# Jika kondisi terpenuhi, keluar dari loop
break
except requests.RequestException as e:
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
print("Max retries exceeded.")
# Naikkan kembali pengecualian terakhir jika percobaan ulang maksimum tercapai
raise
# Contoh penggunaan
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Untuk kesalahan tertentu seperti 429 Terlalu Banyak Permintaan, menggunakan proxy bergilir dapat membantu mendistribusikan permintaan Anda dan menghindari pembatasan kecepatan.
Kode di bawah ini mengimplementasikan strategi percobaan ulang tingkat lanjut bersama dengan penggunaan proksi. Dengan cara ini, kita dapat mengimplementasikan mekanisme permintaan ulang Python. Menggunakan proksi penggalian web berkualitas tinggi juga penting. Proksi ini harus memiliki algoritme yang baik untuk rotasi proksi dan pool yang andal.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Mengirimkan permintaan HTTP GET ke URL yang ditentukan dengan mekanisme percobaan ulang tingkat lanjut.
Parameters:
url (str): URL untuk mengirim permintaan.
max_retries (int): Jumlah maksimum untuk mencoba ulang permintaan. Standarnya adalah 3.
delay (int): Penundaan (dalam detik) di antara percobaan ulang. Standarnya adalah 1.
Raises:
requests.RequestException: Memunculkan pengecualian terakhir jika semua percobaan ulang gagal.
"""
proxies = {
"http": "http://USER:PASS@HOST:PORT",
"https": "https://USER:PASS@HOST:PORT"
}
for attempt in range(max_retries):
try:
response = requests.get(url, proxies=proxies, verify=False)
# Membuat pengecualian untuk kode status 4xx atau 5xx
response.raise_for_status()
# Periksa apakah kode status respons adalah 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Keluar dari perulangan untuk kesalahan 404
# Periksa apakah panjang teks respons kurang dari 10 karakter
if len(response.text) < min_content_length:
print("Response text length is less than 10 characters. Retrying...")
time.sleep(delay)
continue # Coba lagi permintaan tersebut
print('Response Status Code:', response.status_code)
# Jika kondisi terpenuhi, keluar dari loop
break
except requests.RequestException as e:
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
print("Max retries exceeded.")
# Naikkan kembali pengecualian terakhir jika percobaan ulang maksimum tercapai
raise
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Permintaan ulang di Python sangat penting untuk penggalian web yang efektif. Metode yang telah kita bahas untuk mengelola pengulangan permintaan dapat membantu mencegah pemblokiran dan meningkatkan efisiensi dan keandalan pengumpulan data. Menerapkan teknik-teknik ini akan membuat skrip scraping web Anda lebih kuat dan tidak mudah terdeteksi oleh sistem proteksi bot.
Komentar: 0