O Web scraping é um método eficaz de extração de dados da Web. Muitos programadores preferem utilizar a biblioteca de pedidos Python para realizar projectos de recolha de dados da Web, uma vez que é simples e eficaz. No entanto, por muito boa que seja, a biblioteca de pedidos tem as suas limitações. Um problema típico que podemos encontrar no web scraping são os pedidos falhados, que muitas vezes levam a uma extração de dados instável. Neste artigo, vamos passar pelo processo de implementação de novas tentativas de pedidos em Python, para que possa lidar com os erros HTTP e manter os seus scripts de recolha de dados da Web estáveis e fiáveis.
Primeiro, vamos configurar o nosso ambiente. Certifique-se de que tem o Python instalado e qualquer IDE da sua escolha. Em seguida, instale a biblioteca requests, se ainda não a tiver.
pip install requests
Uma vez instalado, vamos enviar um pedido para example.com usando o módulo requests do Python. Aqui está uma função simples que faz exatamente isso:
import requests
def send_request(url):
"""
Envia um pedido HTTP GET para o URL especificado e imprime o código de estado da resposta.
Parameters:
url (str): O URL para o qual enviar o pedido.
"""
response = requests.get(url)
print('Response Status Code: ', response.status_code)
send_request('https://example.com')
A saída do código é mostrada abaixo:
Vamos analisar mais detalhadamente os códigos de estado HTTP para os compreender melhor.
O servidor responde a um pedido HTTP com um código de estado que indica o resultado do pedido. Eis um resumo rápido:
No nosso exemplo, o código de estado 200 significa que o pedido para https://example.com foi concluído. É a forma de o servidor dizer: "Está tudo bem aqui, o seu pedido foi um sucesso".
Estes códigos de estado podem também desempenhar um papel na deteção de bots e indicar quando o acesso é restringido devido a um comportamento semelhante ao de um bot.
Segue-se um rápido resumo dos códigos de erro HTTP que ocorrem principalmente devido a problemas de deteção e autenticação de bots.
Vamos agora escrever um mecanismo simples de repetição em Python para efetuar um pedido HTTP GET com a biblioteca requests. Há alturas em que os pedidos de rede falham devido a algum problema de rede ou sobrecarga do servidor. Assim, se o nosso pedido falhar, devemos tentar novamente estes pedidos.
A função send_request_with_basic_retry_mechanism efectua pedidos HTTP GET a um determinado URL com um mecanismo básico de repetição que só repetirá se for encontrada uma exceção de rede ou de pedido, como um erro de ligação. O pedido será repetido no máximo max_retries vezes. Se todas as tentativas falharem com essa exceção, é levantada a última exceção encontrada.
import requests
import time
def send_request_with_basic_retry_mechanism(url, max_retries=2):
"""
Envia um pedido HTTP GET para um URL com um mecanismo básico de repetição.
Parameters:
url (str): O URL para o qual enviar o pedido.
max_retries (int): O número máximo de tentativas para repetir o pedido.
Raises:
requests.RequestException: Levanta a última exceção se todas as tentativas falharem.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
print('Response status: ', response.status_code)
break # Sair do ciclo se o pedido for bem sucedido
except requests.RequestException as error:
print(f"Attempt {attempt+1} failed:", error)
if attempt < max_retries - 1:
print(f"Retrying...")
time.sleep(delay) # Esperar antes de tentar de novo
else:
print("Max retries exceeded.")
# Aumentar novamente a última exceção se o número máximo de tentativas for atingido
raise
send_request_with_basic_retry_mechanism('https://example.com')
Vamos agora adaptar o mecanismo básico de repetição para lidar com cenários em que o sítio Web que estamos a tentar extrair implementa mecanismos de deteção de bots que podem resultar em bloqueio. Para lidar com esses cenários, precisamos de repetir o pedido diligentemente várias vezes, uma vez que podem não ser apenas bloqueios de deteção de bots, mas também podem ser devidos a problemas de rede ou de servidor.
A função abaixo, send_request_with_advance_retry_mechanism, envia um pedido HTTP GET para o URL fornecido com tentativas de repetição opcionais e atraso de repetição. Tenta enviar o pedido várias vezes para o número de tentativas especificado e imprime o código de estado da resposta se o pedido obtiver a resposta com êxito. Se encontrar um erro durante a operação do pedido, imprime a mensagem de erro e volta a tentar. Aguarda o atraso de repetição especificado entre cada tentativa. Se o pedido falhar mesmo após o número especificado de tentativas de repetição, levanta a última exceção encontrada.
O parâmetro de atraso é importante porque evita bombardear o servidor com vários pedidos num intervalo próximo. Em vez disso, espera que o servidor tenha tempo suficiente para processar o pedido, fazendo com que o servidor pense que é um humano e não um bot que está a fazer os pedidos. Assim, o mecanismo de repetição deve ser atrasado para evitar a sobrecarga do servidor ou a lentidão da resposta do servidor, o que pode acionar mecanismos anti-bot.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1):
"""
Envia um pedido HTTP GET para o URL especificado com um mecanismo avançado de repetição.
Parameters:
url (str): O URL para o qual enviar o pedido.
max_retries (int): O número máximo de tentativas para repetir o pedido. A predefinição é 3.
delay (int): O atraso (em segundos) entre novas tentativas. A predefinição é 1.
Raises:
requests.RequestException: Levanta a última exceção se todas as tentativas falharem.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Levantar uma exceção para códigos de estado 4xx ou 5xx
response.raise_for_status()
print('Response Status Code:', response.status_code)
except requests.RequestException as e:
# Imprimir mensagem de erro e número da tentativa se o pedido falhar
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
# Imprimir a mensagem de nova tentativa e aguardar antes de tentar novamente
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
# Se o número máximo de tentativas for excedido, imprimir a mensagem e voltar a aumentar a exceção
print("Max retries exceeded.")
raise
# Exemplo de utilização
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Aqui está o código corrigido, juntamente com comentários que abordam os inconvenientes:
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Envia um pedido HTTP GET para o URL especificado com um mecanismo avançado de repetição.
Parameters:
url (str): O URL para o qual enviar o pedido.
max_retries (int): O número máximo de vezes para tentar novamente o pedido. A predefinição é 3.
delay (int): O atraso (em segundos) entre novas tentativas. A predefinição é 1.
min_content_length (int): O comprimento mínimo do conteúdo da resposta a considerar válido. A predefinição é 10.
Raises:
requests.RequestException: Levanta a última exceção se todas as tentativas falharem.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Levantar uma exceção para códigos de estado 4xx ou 5xx
response.raise_for_status()
# Verificar se o código de estado da resposta é 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Exit loop for 404 errors
# Verificar se o comprimento do texto da resposta é inferior ao comprimento mínimo especificado para o conteúdo
if len(response.text) < min_content_length:
print("Response text length is less than specified minimum. Retrying...")
time.sleep(delay)
continue # Repetir o pedido
print('Response Status Code:', response.status_code)
# Se as condições forem cumpridas, sair do ciclo
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.")
# Aumentar novamente a última exceção se o número máximo de tentativas for atingido
raise
# Exemplo de utilização
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Para determinados erros como 429 Too Many Requests, a utilização de proxies rotativos pode ajudar a distribuir os seus pedidos e evitar a limitação da taxa.
O código abaixo implementa uma estratégia de repetição avançada juntamente com o uso de proxies. Desta forma, podemos implementar um mecanismo de repetição de pedidos Python. A utilização de proxies de raspagem da Web de alta qualidade também é importante. Estes proxies devem ter um bom algoritmo de rotação de proxies e um conjunto fiável.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Envia um pedido HTTP GET para o URL especificado com um mecanismo avançado de repetição.
Parameters:
url (str): O URL para o qual enviar o pedido.
max_retries (int): O número máximo de tentativas para repetir o pedido. A predefinição é 3.
delay (int): O atraso (em segundos) entre novas tentativas. A predefinição é 1.
Raises:
requests.RequestException: Levanta a última exceção se todas as tentativas falharem.
"""
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)
# Levantar uma exceção para códigos de estado 4xx ou 5xx
response.raise_for_status()
# Verificar se o código de estado da resposta é 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Sair do ciclo para erros 404
# Verificar se o comprimento do texto de resposta é inferior a 10 caracteres
if len(response.text) < min_content_length:
print("Response text length is less than 10 characters. Retrying...")
time.sleep(delay)
continue # Repetir o pedido
print('Response Status Code:', response.status_code)
# Se as condições forem cumpridas, sair do ciclo
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.")
# Aumentar novamente a última exceção se o número máximo de tentativas for atingido
raise
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
As novas tentativas de pedidos em Python são cruciais para uma recolha eficaz de dados da Web. Os métodos que discutimos para gerir as novas tentativas podem ajudar a evitar o bloqueio e melhorar a eficiência e a fiabilidade da recolha de dados. A implementação dessas técnicas tornará seus scripts de raspagem da Web mais robustos e menos suscetíveis à deteção por sistemas de proteção de bots.
Мы получили вашу заявку!
Ответ будет отправлен на почту в ближайшее время.
С уважением proxy-seller.ru!
Comentários: 0