🎯 カスタマイズ可能で検出回避型のクラウドブラウザ。自社開発のChromiumを搭載し、ウェブクローラーAIエージェント向けに設計されています。👉今すぐ試す
ブログに戻ります

MechanicalSoup:Pythonでフォーム駆動のスクレイピングを自動化する

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

29-Jun-2026

TL;DR:

  • MechanicalSoupは、requestsとBeautifulSoupを組み合わせてフォーム駆動型サイトを自動化します。 一つのStatefulBrowserオブジェクトがページを開き、フォームを選択し、フィールドに入力し、送信し、レスポンスを解析します — ブラウザプロセスもJavaScriptエンジンも不要です。
  • ブラウザは、リクエスト間でクッキーとセッション状態を保持します。 ログインやSet-Cookieの後、同じStatefulBrowserが保存されたクッキーを以降のリクエストで返送するため、マルチステップフローも実際のセッションのように動作します。
  • select_formと辞書スタイルのフィールド割り当てがAPI全体です。 CSSセレクタでフォームを対象にし、browser["fieldname"] = valueを設定し、submit_selected()を呼び出します — ライブラリがエンコードとリダイレクトを処理します。
  • MechanicalSoupはサーバーから返されたHTMLのみを読み取ります — JavaScriptは実行しません。 クライアント側でコンテンツを生成するページは空になって返ってきます。HTTPレスポンスとBeautifulSoupの間にDOMレンダリングステップが存在しないからです。
  • ページがレンダリングが必要な場合やボットチャレンジに引っかかる場合は、Scrapeless Scraping Browserにフェッチを渡し、BeautifulSoupでの解析を続けます。 Scrapeless SDKはクラウドセッションを生成し、PlaywrightがCDP経由でそれを駆動してJavaScriptを実行し、レンダリングされたHTMLがそのまま同じsoup.select(...)セレクタに流れ込みます。
  • 無料で始めることができます。 新しいScrapelessアカウントには無料のスクレイピングブラウザランタイムが含まれています — app.scrapeless.comでサインアップしましょう。

はじめに:フォームは未だに多くのスクレイピング作業が隠れている場所です

有用なデータの大部分はフォームの背後に存在します — 検索ボックス、ログイン、フィルターパネル、多段階ウィザード。MechanicalSoupは、まさにその形のサイトのために存在します。requests HTTPライブラリとBeautifulSoupを単一のステートフルブラウザオブジェクトにラップします:ページを取得し、そこにあるHTMLフォームを入力して送信し、リダイレクトに従い、返ってくるものを解析します。SeleniumもChromiumもドライババイナリも不要です。

このミニマリズムは速さを保ち、ライブラリが到達できる範囲を厳格に定義します。MechanicalSoupはHTTPセマンティクスを話し、HTMLを解析します。ページ上のJavaScriptは決して実行しないため、クライアント側でレンダリングされたコンテンツ — 無限スクロールフィード、React結果リスト、XHRを介して結果を取得する検索ボックス — はサーバーが最初に送った空のシェルとして返ってきます。サーバーレンダリングされたフォームでは迅速に動作し、クライアントレンダリングされたものには盲目になります。

このガイドは、実際のMechanicalSoupワークフローを端から端まで説明します — インストール、ページを開く、フォームを入力して送信する、セッション間でクッキーを保持する、結果をスクレイピングする — そして honest limit を示します。ターゲットがブラウザ内でレンダリングされている場合やアクティブなアンチボットチャレンジの背後にある場合、フェッチはScrapeless Scraping Browserに移行し、その間、あなたのBeautifulSoup解析コードはそのまま維持されます。


できること

  • ログインフォームを送信し、認証を維持します。 ユーザー名とパスワードのフィールドに入力し、送信すると、StatefulBrowserはその後のすべてのページのセッションクッキーを保持します。
  • 検索とフィルターフォームをドライブします。 クエリフィールドを設定し、送信して、サーバーが返す結果の行を解析します — 典型的な検索およびスクレイピングループです。
  • マルチページフローを渡ります。 リンクに従い、1つのブラウザオブジェクト内で連続するフォームを送信し、クッキージャーとリファラーを自動的に持ち運びます。
  • サーバーでレンダリングされたテーブルやリストを読み取ります。 生のHTMLに存在するもの — 価格表、リスティング、ディレクトリページ — は、1つのsoup.select()ですぐにアクセスできます。
  • 繰り返しの提出をスクリプト化します。 フィールド値を変更しながら同じフォームを再実行して、実際のブラウザに触れずにクエリのカタログを一掃できます。

Scrapeless Scraping Browserの理由

Scrapeless Scraping Browserは、ウェブクローラーやAIエージェント向けに設計されたカスタマイズ可能なアンチ検出クラウドブラウザです。MechanicalSoupが自力で届かないページに対して、以下を提供します:

  • クラウド側のJavaScriptレンダリング — ページのスクリプトはリモートブラウザ上で実行されるため、クライアントが構築したコンテンツは、解析する時点でHTML内に存在します。
  • 195か国以上の住宅用プロキシproxy_countryで出口を固定し、ジオゲート付きページや地域ロックされたフォームがローカルの訪問者に提供するコンテンツを提供します。
  • アンチ検出フィンガープリンティング — セッションは実際のブラウザとして表示されるため、フォームや結果ページはチャレンジのインタースティシャルを返さずにレンダリングされます。
  • セッションの持続性 — クッキーと認証状態は一つのセッション内のナビゲーションを通じて保持され、これがMechanicalSoupがローカルで提供する同じ特性です。
  • 標準CDPエンドポイントbrowser_ws_endpointは通常のWebSocket URLであり、したがってPlaywright(または任意のCDPクライアント)は1回の呼び出しで接続し、あなたの解析コードはそのまま変わりません。

無料プランのAPIキーを取得するには、app.scrapeless.comにアクセスしてください。


前提条件

  • Python 3.10以上
  • ScrapelessアカウントとAPIキー — app.scrapeless.comでサインアップ(クラウドブラウザセクションのみ必要)
  • CSSセレクタとターミナルの基本的な知識

インストール

MechanicalSoupは、依存関係としてrequestsbeautifulsoup4を取り込む単一パッケージです:

bash Copy
pip install mechanicalsoup

インストールとバージョンを確認します:

bash Copy
python -c "import mechanicalsoup; print(mechanicalsoup.__version__)"
# 1.4.0

設定:StatefulBrowserでページを開く

MechanicalSoupのすべてはStatefulBrowserを通じて実行されます。これは現在のページ、セッション、およびクッキージャーを保持します。リクエストに意味のあるアイデンティティを持たせるために、構築時にユーザーエージェントを設定します:

python Copy
import mechanicalsoup

browser = mechanicalsoup.StatefulBrowser(
    user_agent="Mozilla/5.0 (compatible; data-collector)"
)

browser.open("https://httpbingo.org/forms/post")
# browser.pageは現在直接クエリできるBeautifulSoupオブジェクトです

browser.open()requestsのレスポンスを返します;browser.pageはあなたがちょうど読み込んだページの解析されたBeautifulSoupツリーです。


基本的な実装:フォームを入力して送信する

コアループは3つの呼び出しです — フォームを選択し、フィールドを割り当て、送信します。select_formはCSSセレクタを取り、フィールドの割り当てはブラウザ上で辞書スタイルです;submit_selected()はフォームをPOSTし、リダイレクトに従います。

python Copy
import mechanicalsoup

browser = mechanicalsoup.StatefulBrowser(
    user_agent="Mozilla/5.0 (compatible; data-collector)"
)
browser.open("https://httpbingo.org/forms/post")

# アクションでフォームをターゲットにし、その後名前でフィールドを埋める
browser.select_form('form[action="/post"]')
browser["custname"] = "Ada Lovelace"
browser["custtel"] = "555-0100"
browser["custemail"] = "ada@example.com"
browser["size"] = "medium"             # ラジオボタン
browser["topping"] = ["bacon", "cheese"]  # 複数選択チェックボックス
browser["comments"] = "Leave at door"

response = browser.submit_selected()
print(response.status_code)
data = response.json()
print(data["url"])
print(data["form"])

httpbinエンドポイントは解析されたフォームボディをエコーし、MechanicalSoupが送ったものを正確に確認します:

json Copy
{
  "url": "https://httpbingo.org/post",
  "form": {
    "comments": "Leave at door",
    "custemail": "ada@example.com",
    "custname": "Ada Lovelace",
    "custtel": "555-0100",
    "delivery": "",
    "size": "medium",
    "topping": ["bacon", "cheese"]
  }
}
// 値は実際の送信を反映しています;空の"delivery"はフォーム上の未設定フィールドです。

ラジオボタンは単一の文字列を取り、チェックボックスグループはリストを取り、未設定のフィールドは空で送信されます — これはブラウザが生成するのと同じエンコーディングです。


高度なパターン

セッションを跨いでクッキーを保持する

StatefulBrowserは1つのrequests.Sessionを再利用するため、サーバーが設定したクッキーは自動的に以降のリクエストに持ち越されます。これがログインや複数ステップのフローを機能させる理由です:

python Copy
import mechanicalsoup

browser = mechanicalsoup.StatefulBrowser()

# サーバーはこのリクエストでクッキーを設定します
browser.open("https://httpbingo.org/cookies/set?session_id=abc123")
print(browser.session.cookies.get_dict())
# {'session_id': 'abc123'}

# 同じブラウザでの後続のリクエストでは、保存されたクッキーを返します
echo = browser.open("https://httpbingo.org/cookies")
print(echo.json())
# {'cookies': {'session_id': 'abc123'}}

実際のログインの場合、まずログインフォームを送信し、その後は同じbrowserオブジェクトを使い続けます — 認証クッキーはその後の各ページに持ち運ばれます。

検索フォームを送信し、結果をスクレイピングする

GET検索フォームは同じパターンです:クエリフィールドを設定し、送信し、browser.pageから結果の行を解析します。

python Copy
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)} 行")
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, "勝利:", wins)

結果ページはサーバーレンダーされるため、行はMechanicalSoupがすでに保持しているHTMLに含まれています — 追加のフェッチは必要ありません。
APIキーを無料プランで取得するには、app.scrapeless.comにアクセスしてください。


MechanicalSoupの限界: ブラウザでレンダリングされるページ

MechanicalSoupは、HTTP経由でサーバーが返したものをBeautifulSoupに渡すだけです — それ以上でもそれ以下でもありません。ページがクライアントサイドのJavaScriptでコンテンツを生成すると、その生のHTMLは空のシェルになり、セレクターは何も見つけられません:

python Copy
import mechanicalsoup

browser = mechanicalsoup.StatefulBrowser()
browser.open("https://quotes.toscrape.com/js/")
quotes = browser.page.select(".quote .text")
print("MechanicalSoupが見つけた引用:", len(quotes))
# MechanicalSoupが見つけた引用: 0

ゼロです。このページの/js/バリアントは、ロード後にJavaScriptで引用を挿入するため、BeautifulSoupが一致させるためのサーバーのHTMLには何もありません。同様の壁は、ボット対策のチャレンジがあるページや住宅IPにのみコンテンツを提供するページにも現れます — これらはすべて、HTTP専用クライアントではクリアできません。

修正は、あなたがすでに書いたものをすべて保持します。Scrapeless Scraping Browserにレンダリングを任せましょう:SDKはクラウドセッションを生成し、PlaywrightがCDP経由で接続し、ページのJavaScriptを実行し、レンダリングされたHTMLを同じBeautifulSoupセレクターに直接渡します。

SDKとPlaywrightクライアントをインストールし、Playwrightが操作するブラウザバイナリを取得します:

bash Copy
pip install scrapeless playwright beautifulsoup4
python -m playwright install chromium

環境にAPIキーを設定します — ハードコーディングは避けてください:

bash Copy
export SCRAPELESS_API_KEY="your_api_token_here"

今度はページをクラウド側でレンダリングし、ローカルで結果を解析します:

python Copy
import os
from scrapeless import Scrapeless
from scrapeless.types import ICreateBrowser
from playwright.sync_api import sync_playwright
from bs4 import BeautifulSoup

client = Scrapeless()  # 環境からSCRAPELESS_API_KEYを読み取る

# クラウドセッションを生成; 地理制限のあるページ用に米国の住宅出口を設定
session = client.browser.create(ICreateBrowser(
    session_name="mechanicalsoup-guide",
    session_ttl=180,
    proxy_country="US",
))

with sync_playwright() as p:
    # browser_ws_endpointは標準的なwss:// CDP URL
    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()

# MechanicalSoupで使用したのと同じBeautifulSoup解析
soup = BeautifulSoup(html, "html.parser")
quotes = soup.select(".quote .text")
print("Scrapeless + BeautifulSoupが見つけた引用:", len(quotes))
print(quotes[0].get_text())
# Scrapeless + BeautifulSoupが見つけた引用: 10
# “私たちが創り出した世界は、私たちの思考のプロセスである。”

MechanicalSoupに0行を返したページは、クラウドブラウザを介して10行を返します。なぜなら、JavaScriptが実行された後にHTMLが読み取られたからです。レンダリングとエグレスはクラウド側で行われ、解析レイヤー — soup.select(...) — は同一です。同じエスカレーションについてライブラリネイティブな見解を得るために、Scrapling cloud-browser guideでは、同じbrowser_ws_endpointを介した適応セレクターフェッチャーを提供しています。


トラブルシューティング

症状 原因 修正
LinkNotFoundErrorselect_formで発生 CSSセレクターがページ上のフォームにマッチしない browser.page.select("form")を印刷し、実際のaction/属性をターゲットにする
結果セレクターが空のリストを返す ページがJavaScriptでコンテンツをレンダリングしている Scraping Browserでクラウド側でレンダリングし、返されたHTMLを解析する
送信がフィールドを無視する フィールドが文字列またはリストを必要とするラジオ/チェックボックスであるため、単純な値ではない ラジオには単一の文字列を割り当て、チェックボックスグループにはリストを割り当てる
ログインしたページがログアウトしたように振る舞う 各ステップに対して新しいStatefulBrowser(新しいクッキージャー) セッションクッキーを持続させるために1つのbrowserオブジェクトを再利用する
ページがコンテンツの代わりにチャレンジを返す アクティブなボット対策またはHTTP専用クライアントに対する地域チェック proxy_countryを固定し、クラウドブラウザのフィンガープリンティングに実際のページをレンダリングさせる

結論: パーサーを維持し、フェッチを入れ替える

MechanicalSoupは、まだプレーンHTMLおよびフォームの大規模なセットのサイトに適したツールです:ページを開いてselect_form、フィールドを設定し、submit_selected()を実行して、BeautifulSoupから行を読み取ります。クッキージャーにより、ログインやマルチステップフローが追加コードなしで機能します。その一つの厳しい境界はJavaScriptです — HTMLを読み取りますが、レンダリングはしません。ターゲットがブラウザで自ら構築される場合や、アンチボットの壁の背後にある場合、最もクリーンな修正はフェッチを変更するだけです:Scrapelessセッションを生成し、CDPを介してページをレンダリングし、その結果のHTMLを同じセレクタに供給します。ページが独自のプロキシ出口を持つ完全なヘッドレスブラウザを必要とする場合、Puppeteerプロキシガイドは同じクラウド側のパターンをカバーしており、Scraping BrowserのドキュメントはCDPの全体的な表面を文書化しています。地理制約のあるページ向けには米国の出口を固定し、ステップ間で一つのセッションを再利用し、欠損フィールドをnullableとして扱います。


AIパワードデータパイプラインの構築準備は整いましたか?

無料プランを請求し、フォームの自動化やレンダリングパイプラインを構築している開発者とつながるためにコミュニティに参加してください:Discord · Telegram

app.scrapeless.comにサインアップして、無料のScraping Browserランタイムを利用し、上記のパターンを自分のワークフローに必要なフォーム、ログイン、およびレンダリングされたページに適応させてください。価格についてはスケールを確認してください。


FAQ

Q: MechanicalSoupはJavaScriptを実行しますか?
いいえ。MechanicalSoupはrequestsとBeautifulSoupをラップしているため、サーバーが返すHTMLしか見えません。クライアント側でコンテンツを構築するページは空のまま返されます;それらをクラウドブラウザを介してレンダリングし、同じBeautifulSoupセレクタで結果のHTMLを解析します。

Q: MechanicalSoupはログインやセッションをどのように処理しますか?
単一のStatefulBrowserが一つのrequests.Sessionを再利用するため、サーバーが設定したクッキーはすべての後続リクエストに自動的に保持されます。ログインフォームを一度送信した後は、同じブラウザオブジェクトを使い続け、認証クッキーが同伴します。

Q: ページ上の特定のフォームをどのように選択しますか?
CSSセレクタをselect_formに渡します。例えば、browser.select_form('form[action="/post"]')のようにです。マッチするフォームがない場合、LinkNotFoundErrorが発生します — 実際の属性を見るにはbrowser.page.select("form")を印刷して、その中からターゲットを選んでください。

Q: MechanicalSoupでサイトをスクレイピングすることは合法ですか?
公然と見えるデータをスクレイピングすることは一般的に許可されますが、ルールは管轄区域とサイトの利用規約によって異なります。ターゲットの利用規約を確認し、ロボット指令を尊重し、個人のデータや制限されたデータを避け、あいまいなことについては法律相談を受けてください。

Q: MechanicalSoupでプロキシは必要ですか?
オープンでサーバーがレンダリングしたページの場合は、しばしば必要ありません。地域によって制限されるページや、居住者IPにのみコンテンツを提供するページの場合、Scrapeless Scraping Browserを通じてフェッチをルーティングし、proxy_countryを固定して、リクエストがサイトに信頼されるIPから出るようにします。

Q: クラウドブラウザに移行するときにBeautifulSoupのコードを保持できますか?
はい。クラウドブラウザはフェッチステップのみを置き換えます — レンダリングされたHTMLを返し、それをMechanicalSoupで使用していたのと同じsoup.select(...)呼び出しで解析します。解析レイヤーは変わりません。

Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。

最も人気のある記事

カタログ