MechanicalSoup: Automatize a Extração de Dados Baseada em Formulários em Python
Senior Web Scraping Engineer
TL;DR:
- MechanicalSoup automatiza sites com formulários ao emparelhar
requestscom BeautifulSoup. Um objetoStatefulBrowserabre uma página, seleciona um formulário, preenche seus campos, o submete e analisa a resposta — sem processo de navegador e sem engine JavaScript. - O navegador mantém cookies e estado de sessão entre requisições para você. Após um login ou um
Set-Cookie, o mesmoStatefulBrowserenvia o cookie armazenado de volta em cada requisição posterior, fazendo com que fluxos multi-etapas se comportem como uma sessão real. select_formmais atribuição de campo estilo dicionário é toda a superfície da API. Você direciona um formulário por seletor CSS, definebrowser["nome_do_campo"] = valor, e chamasubmit_selected()— a biblioteca cuida da codificação e do redirecionamento.- MechanicalSoup lê apenas o HTML que o servidor retorna — não executa JavaScript. Uma página que constrói seu conteúdo do lado do cliente retorna vazia, porque não há etapa de renderização do DOM entre a resposta HTTP e o BeautifulSoup.
- Quando uma página precisa de renderização ou ativa um desafio para bots, passe a busca ao Scrapeless Scraping Browser e continue analisando com BeautifulSoup. O SDK do Scrapeless cria uma sessão na nuvem, o Playwright a controla via CDP para executar o JavaScript, e o HTML renderizado retorna diretamente para os mesmos seletores
soup.select(...). - Gratuito para começar. Novas contas Scrapeless incluem tempo de execução gratuito do Scraping Browser — inscreva-se em app.scrapeless.com.
Introdução: os formulários ainda são onde a maior parte do trabalho de scraping se esconde
Uma grande parte dos dados úteis está atrás de um formulário — uma caixa de pesquisa, um login, um painel de filtros, um assistente de múltiplas páginas. MechanicalSoup existe exatamente para esse tipo de site. Ele envolve a biblioteca HTTP requests e o BeautifulSoup em um único objeto de navegador com estado: busca uma página, permite que você preencha e submeta formulários HTML nela, segue o redirecionamento e analisa o que voltar. Sem Selenium, sem Chromium, sem binário do driver.
O minimalismo mantém a velocidade e também estabelece um limite claro sobre o que a biblioteca pode acessar. MechanicalSoup fala semântica HTTP e analisa HTML. Ele nunca executa o JavaScript da página, então qualquer coisa renderizada do lado do cliente — um feed de rolagem infinita, uma lista de resultados React, uma caixa de pesquisa que busca resultados via XHR — retorna como a casca vazia que o servidor enviou inicialmente. Ele continua rápido em um formulário renderizado pelo servidor e fica cego em um renderizado pelo cliente.
Este guia percorre um fluxo de trabalho real do MechanicalSoup do início ao fim — instalar, abrir uma página, preencher e submeter um formulário, carregar cookies ao longo de uma sessão e extrair os resultados — e então mostra o limite honesto. Quando um alvo é renderizado no navegador ou está atrás de um desafio anti-bot ativo, a busca é transferida para o Scrapeless Scraping Browser através do Protocolo de Ferramentas de Desenvolvimento do Chrome, enquanto seu código de análise com BeautifulSoup permanece exatamente como estava.
O Que Você Pode Fazer Com Isso
- Submeter formulários de login e manter a autenticação. Preencha os campos de nome de usuário e senha, submeta, e o
StatefulBrowsermantém os cookies de sessão para cada página depois disso. - Dirigir formulários de busca e filtro. Defina um campo de consulta, submeta e analise as linhas de resultado que o servidor retorna — o clássico loop de busca e scraping.
- Percorrer fluxos de múltiplas páginas. Siga links e submeta formulários sucessivos em um único objeto de navegador, com o jarro de cookies e o referer transportados automaticamente.
- Ler tabelas e listas renderizadas pelo servidor. Qualquer coisa presente no HTML bruto — tabelas de preços, listagens, páginas de diretório — está a um
soup.select()de distância. - Scriptar envios repetitivos. Execute novamente o mesmo formulário com diferentes valores de campo para varrer um catálogo de consultas sem tocar em um navegador real.
Por Que Scrapeless Scraping Browser
O Scrapeless Scraping Browser é um navegador em nuvem personalizável, projetado para web crawlers e agentes de IA. Para as páginas que o MechanicalSoup não consegue acessar por conta própria, ele traz:
- Renderização de JavaScript do lado da nuvem — os scripts da página são executados no navegador remoto, então o conteúdo construído pelo cliente existe no HTML quando você o analisa.
- Proxies residenciais em mais de 195 países — prenda a saída com
proxy_countrypara que páginas geograficamente bloqueadas e formulários limitados à região sirvam o conteúdo que serviriam a um visitante local. - Fingerprinting anti-detekção — a sessão se apresenta como um navegador real, então a página de formulário ou resultado é renderizada em vez de retornar um desafio intersticial.
- Persistência de sessão — cookies e estado de autenticação permanecem ativos durante as navegações dentro de uma sessão, a mesma propriedade que o MechanicalSoup oferece localmente.
- Um endpoint CDP padrão —
browser_ws_endpointé uma URL WebSocket comum, então o Playwright (ou qualquer cliente CDP) se conecta com uma chamada e seu código de análise permanece inalterado.
Obtenha sua chave de API no plano gratuito em app.scrapeless.com.
Pré-requisitos
- Python 3.10 ou mais recente
- Uma conta Scrapeless e chave de API — inscreva-se em app.scrapeless.com (somente necessário para a seção do navegador em nuvem)
- Familiaridade básica com seletores CSS e o terminal
Instalação
MechanicalSoup é um único pacote que inclui requests e beautifulsoup4 como dependências:
bash
pip install mechanicalsoup
Confirme a instalação e a versão:
bash
python -c "import mechanicalsoup; print(mechanicalsoup.__version__)"
# 1.4.0
Configurar: abrir uma página com um StatefulBrowser
Tudo no MechanicalSoup é executado através de um StatefulBrowser. Ele mantém a página atual, a sessão e o jar de cookies. Defina um agente de usuário na construção para que as solicitações carreguem uma identidade sensata:
python
import mechanicalsoup
browser = mechanicalsoup.StatefulBrowser(
user_agent="Mozilla/5.0 (compatible; data-collector)"
)
browser.open("https://httpbingo.org/forms/post")
# browser.page agora é um objeto BeautifulSoup que você pode consultar diretamente
browser.open() retorna a resposta requests; browser.page é a árvore BeautifulSoup analisada para a página que você acabou de carregar.
Implementação básica: preencher e enviar um formulário
O loop principal consiste em três chamadas — selecionar o formulário, atribuir seus campos, enviar. select_form recebe um seletor CSS; a atribuição de campos é feita no estilo dicionário no navegador; submit_selected() posta o formulário e segue o redirecionamento.
python
import mechanicalsoup
browser = mechanicalsoup.StatefulBrowser(
user_agent="Mozilla/5.0 (compatible; data-collector)"
)
browser.open("https://httpbingo.org/forms/post")
# Alvo o formulário pela sua ação, depois preencho campos pelo nome
browser.select_form('form[action="/post"]')
browser["custname"] = "Ada Lovelace"
browser["custtel"] = "555-0100"
browser["custemail"] = "ada@example.com"
browser["size"] = "medium" # botão de rádio
browser["topping"] = ["bacon", "cheese"] # caixas de seleção de múltiplos valores
browser["comments"] = "Deixar na porta"
response = browser.submit_selected()
print(response.status_code)
data = response.json()
print(data["url"])
print(data["form"])
O endpoint httpbin ecoa o corpo do formulário analisado, que confirma exatamente o que o MechanicalSoup enviou:
json
{
"url": "https://httpbingo.org/post",
"form": {
"comments": "Deixar na porta",
"custemail": "ada@example.com",
"custname": "Ada Lovelace",
"custtel": "555-0100",
"delivery": "",
"size": "medium",
"topping": ["bacon", "cheese"]
}
}
// Os valores refletem a submissão real; o "delivery" vazio é um campo não definido no formulário.
Botões de rádio aceitam uma única string, grupos de caixas de seleção aceitam uma lista, e qualquer campo deixado não definido é enviado vazio — a mesma codificação que um navegador produziria.
Padrões avançados
Carregar cookies através de uma sessão
Um StatefulBrowser reutiliza uma única requests.Session, então qualquer cookie que o servidor define persiste para solicitações futuras automaticamente. É isso que faz os logins e fluxos de vários passos funcionarem:
python
import mechanicalsoup
browser = mechanicalsoup.StatefulBrowser()
# O servidor define um cookie nesta solicitação
browser.open("https://httpbingo.org/cookies/set?session_id=abc123")
print(browser.session.cookies.get_dict())
# {'session_id': 'abc123'}
# Uma solicitação posterior no mesmo navegador envia o cookie armazenado de volta
echo = browser.open("https://httpbingo.org/cookies")
print(echo.json())
# {'cookies': {'session_id': 'abc123'}}
Para um login real, envie primeiro o formulário de login, depois continue usando o mesmo objeto browser — o cookie de autenticação acompanha todas as páginas subsequentes.
Enviar um formulário de busca e extrair os resultados
Um formulário de busca GET segue o mesmo padrão: defina o campo da consulta, envie, analise as linhas de resultado de browser.page.
python
import mechanicalsoup
browser = mechanicalsoup.StatefulBrowser(
user_agent="Mozilla/5.0 (compatible; data-collector)"
)
browser.open("https://www.scrapethissite.com/pages/forms/")
browser.select_form('form[action="/pages/forms/"]')
browser["q"] = "boston"
browser.submit_selected()
print(browser.url) # https://www.scrapethissite.com/pages/forms/?q=boston
rows = browser.page.select("table.table tr.team")
print(f"{len(rows)} linhas")
for row in rows[:3]:
name = row.select_one(".name").get_text(strip=True)
year = row.select_one(".year").get_text(strip=True)
wins = row.select_one(".wins").get_text(strip=True)
print(name, year, "vitórias:", wins)
Como a página de resultados é renderizada pelo servidor, as linhas estão no HTML que o MechanicalSoup já possui — nenhuma nova busca é necessária.
Obtenha sua chave API no plano gratuito: app.scrapeless.com
Onde o MechanicalSoup para: páginas que são renderizadas no navegador
MechanicalSoup entrega ao BeautifulSoup tudo o que o servidor retornou via HTTP — nada mais. Quando uma página constrói seu conteúdo com JavaScript do lado do cliente, esse HTML bruto é uma casca vazia, e os seletores não encontram nada:
python
import mechanicalsoup
browser = mechanicalsoup.StatefulBrowser()
browser.open("https://quotes.toscrape.com/js/")
quotes = browser.page.select(".quote .text")
print("Cotações encontradas pelo MechanicalSoup:", len(quotes))
# Cotações encontradas pelo MechanicalSoup: 0
Zero. A variante /js/ dessa página injeta suas citações com JavaScript após o carregamento, então não há nada no HTML do servidor para o BeautifulSoup combinar. A mesma barreira aparece em páginas que estão sob um desafio anti-bot ou que servem conteúdo apenas para um IP residencial — nada disso um cliente apenas HTTP pode superar.
A solução mantém tudo que você já escreveu. Deixe o Scrapeless Scraping Browser fazer a renderização: o SDK cria uma sessão em nuvem, o Playwright se conecta a ela via CDP e executa o JavaScript da página, e você passa o HTML renderizado diretamente para os mesmos seletores do BeautifulSoup.
Instale o SDK e um cliente Playwright, depois busque o executável do navegador que o Playwright controla:
bash
pip install scrapeless playwright beautifulsoup4
python -m playwright install chromium
Defina sua chave no ambiente — nunca a codifique diretamente:
bash
export SCRAPELESS_API_KEY="seu_token_api_aqui"
Agora renderize a página do lado da nuvem e analise o resultado localmente:
python
import os
from scrapeless import Scrapeless
from scrapeless.types import ICreateBrowser
from playwright.sync_api import sync_playwright
from bs4 import BeautifulSoup
client = Scrapeless() # lê SCRAPELESS_API_KEY do ambiente
# Crie uma sessão em nuvem; fixe a saída residencial dos EUA para páginas com restrições geográficas
session = client.browser.create(ICreateBrowser(
session_name="mechanicalsoup-guide",
session_ttl=180,
proxy_country="US",
))
with sync_playwright() as p:
# browser_ws_endpoint é uma URL padrão wss:// CDP
browser = p.chromium.connect_over_cdp(session.browser_ws_endpoint)
page = browser.contexts[0].pages[0]
page.goto("https://quotes.toscrape.com/js/", wait_until="domcontentloaded")
page.wait_for_selector(".quote .text")
html = page.content()
browser.close()
# Mesma análise do BeautifulSoup que você usou com o MechanicalSoup
soup = BeautifulSoup(html, "html.parser")
quotes = soup.select(".quote .text")
print("Cotações encontradas pelo Scrapeless + BeautifulSoup:", len(quotes))
print(quotes[0].get_text())
# Cotações encontradas pelo Scrapeless + BeautifulSoup: 10
# “O mundo como o criamos é um processo do nosso pensamento. …”
A página que retornou 0 linhas para o MechanicalSoup retorna 10 através do navegador em nuvem, porque o JavaScript realmente foi executado antes que o HTML fosse lido. A renderização e a saída ocorrem do lado da nuvem; a camada de análise — soup.select(...) — é idêntica. Para uma abordagem nativa da biblioteca sobre a mesma escalada, o guia de navegador em nuvem Scrapling roteia um buscador de seletor adaptativo através do mesmo browser_ws_endpoint.
Solução de Problemas
| Sintoma | Causa | Solução |
|---|---|---|
LinkNotFoundError em select_form |
O seletor CSS não corresponde a nenhum formulário na página | Imprima browser.page.select("form") e dirija-se ao action/atributos reais |
| Seletor de resultados retorna uma lista vazia | A página renderiza seu conteúdo com JavaScript | Renderize do lado da nuvem com o Scraping Browser, depois analise o HTML retornado |
| A submissão ignora um campo | O campo é um rádio/caixa de seleção que precisa de uma string ou lista, e não um valor simples | Atribua uma única string aos rádios, uma lista aos grupos de caixas de seleção |
| Uma página logada age como se estivesse desconectada | Um novo StatefulBrowser (nova jar de cookies) por passo |
Reutilize um objeto browser para que o cookie da sessão persista |
| A página retorna um desafio em vez de conteúdo | Desafio anti-bot ativo ou uma verificação de região em um cliente apenas HTTP | Defina proxy_country e deixe a impressão digital do navegador em nuvem renderizar a página real |
Conclusão: mantenha o parser, troque o fetch
MechanicalSoup é a ferramenta certa para o grande conjunto de sites que ainda são HTML simples e formulários: abra uma página, select_form, atribua campos, submit_selected(), e leia as linhas do BeautifulSoup. O jarro de cookies permite que logins e fluxos de múltiplas etapas funcionem sem código extra. Sua única limitação é JavaScript — ele lê HTML, não o renderiza. Quando um alvo se constrói no navegador ou se esconde atrás de um muro anti-bot, a solução mais limpa é mudar apenas a busca: crie uma sessão Scrapeless, renderize a página através do CDP e alimente o HTML resultante nos mesmos seletores. Quando a página precisa de um navegador headless completo com sua própria saída de proxy, o guia de proxy do Puppeteer cobre o mesmo padrão do lado da nuvem, e a doc do Scraping Browser documenta toda a superfície do CDP. Fixe a saída dos EUA para páginas geo-limitadas, reutilize uma sessão entre etapas e trate campos ausentes como nulos.
Pronto para Construir Seu Pipeline de Dados Potencializado por IA?
Junte-se à nossa comunidade para reivindicar um plano gratuito e conectar-se com desenvolvedores que estão construindo automações de formulários e pipelines de rendering: Discord · Telegram.
Inscreva-se em app.scrapeless.com para obter o tempo de execução gratuito do Scraping Browser e adapte os padrões acima aos formulários, logins e páginas renderizadas que seu fluxo de trabalho precisa. Veja preços para escalabilidade.
FAQ
P: O MechanicalSoup executa JavaScript?
Não. O MechanicalSoup envolve requests e BeautifulSoup, portanto, ele só vê o HTML que o servidor retorna. Páginas que constroem seu conteúdo no lado do cliente retornam vazias; renderize essas através de um navegador na nuvem e analise o HTML resultante com os mesmos seletores do BeautifulSoup.
P: Como o MechanicalSoup lida com logins e sessões?
Um único StatefulBrowser reutiliza uma requests.Session, então qualquer cookie que o servidor definir persiste em cada solicitação posterior automaticamente. Envie o formulário de login uma vez, então continue usando o mesmo objeto de navegador e o cookie de autenticação segue junto.
P: Como seleciono um formulário específico em uma página?
Passe um seletor CSS para select_form, por exemplo browser.select_form('form[action="/post"]'). Se nenhum formulário corresponder, você receberá um LinkNotFoundError — imprima browser.page.select("form") para ver os atributos reais e direcionar um deles.
P: É legal fazer scraping em um site com MechanicalSoup?
Fazer scraping de dados visíveis publicamente é geralmente permitido, mas as regras variam de acordo com a jurisdição e os termos de serviço do site. Revise os ToS do alvo, respeite as diretrizes dos robôs, evite dados pessoais ou restritos e consulte um advogado para qualquer coisa ambígua.
P: Preciso de um proxy com MechanicalSoup?
Para páginas abertas renderizadas pelo servidor, muitas vezes não. Para páginas que restrigem por região ou que servem conteúdo apenas para IPs residenciais, direcione a busca através do Scraping Browser do Scrapeless e fixe proxy_country para que a solicitação saia de um IP que o site confia.
P: Posso manter meu código BeautifulSoup quando me mover para o navegador na nuvem?
Sim. O navegador na nuvem substitui apenas a etapa de busca — ele devolve HTML renderizado, que você analisa com as mesmas chamadas soup.select(...) que usou com o MechanicalSoup. A camada de parsing não muda.
Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.



