Pythonによるウェブスクレイピング:初心者向けガイド
Scrapeless Scraping Browserは、ブラウザ出力が必要なPythonスクレイピングワークフローのためにJavaScript駆動の公開ページをレンダリングします。
TL;DR
- 基本的なPythonスクレイパーには4つのステージがあります:リクエスト、解析、選択、および保存。 各ステージを別々に保ち、エラーが見つけやすくします。
- アクセス許可を得た安定したページから始めてください。 セレクタやループを書く前にレスポンスを検査します。
- HTMLパーサーはJavaScriptを実行しません。 必要なコンテンツがページスクリプトの実行後にのみ表示される場合、ブラウザバックのパスを使用します。
- セレクタはデータ契約の一部です。 生成されたクラス名よりも、セマンティックタグ、ラベル、安定した属性、URLパターンを好みます。
- 責任あるスクレイピングは制約があり透明です。 アクセスルール、条件、プライバシー、著作権、サイトにかかる運用負荷を尊重します。
Pythonによるウェブスクレイピングの意味
Pythonによるウェブスクレイピングとは、ウェブリソースを取得し、返されたコンテンツを構造化データに変換することを意味します。小さなスクレイパーは1つのHTMLページを読み取り、そのタイトルを抽出することができます。生産コレクターはJavaScriptをレンダリングし、許可されたページネーションに従い、レコードを検証し、出所を保存し、ソース構造の変更を監視することができます。
Pythonは成熟したHTTP、パース、ブラウザ、データ、およびストレージライブラリを持っているため一般的な選択肢です。この言語はただの1つの層です。信頼できるスクレイパーは、明確なターゲットスキーマ、ソースポリシー、安定したページ機能に一致するセレクタ、およびエラーページや空のシェルから実際のデータを区別するチェックも必要です。
公開コンテンツと狭い目標から始めます。「許可されたページからタイトルと正規URLを収集する」は「サイト全体をスクレイピングする」よりも確認が容易です。狭いバージョンはメカニクスを明らかにし、無制限のクロールを促すことはありません。
4段階のスクレイピングモデル
| ステージ | 質問 | 一般的なPythonツール |
|---|---|---|
| リクエスト | サーバーは意図したリソースを返しましたか? | urllib.requestまたはRequests |
| パース | レスポンスを文書ツリーとして表現できますか? | html.parser、Beautiful Soup、またはlxml |
| 選択 | どの要素が必要なフィールドにマッピングされますか? | CSSセレクタ、タグ検索、属性、またはXPath |
| 保存 | クリーンなレコードと出所はどのように保存されますか? | csv、json、sqlite3、またはデータベースクライアント |
学習中にこれらのステージを一つの不透明な関数にまとめないでください。パースする前に、ステータス、コンテンツタイプ、最終URL、および短いレスポンスプレビューを出力してください。パース後、出力を書く前に選択した要素を検査します。ステージの境界は、タイトルがネットワークアクセス、JavaScriptレンダリング、セレクタの変更、またはデータクリーンアップから来たかを明示します。
その Python urllib.requestドキュメント は標準ライブラリのリクエストインターフェースをカバーします。サードパーティの Requestsドキュメント はセッション、ヘッダー、デコード、プロキシ、およびタイムアウトを伴うよりエルゴノミクスなHTTP APIを提供します。
実行可能な最初のスクレイパー
この例は、Pythonの標準ライブラリとexample.comの安定したデモページのみを使用します。ページを取得し、レスポンスタイプを確認し、最初の見出しをパースし、1つのJSONレコードを出力します。コードには認証情報やサイト固有のアクセス回避策は含まれていません。
import json
from html.parser import HTMLParser
from urllib.request import Request, urlopen
class FirstHeadingParser(HTMLParser):
def __init__(self):
super().__init__()
self.in_h1 = False
self.heading_parts = []
def handle_starttag(self, tag, attrs):
if tag == "h1" and not self.heading_parts:
self.in_h1 = True
def handle_endtag(self, tag):
if tag == "h1":
self.in_h1 = False
def handle_data(self, data):
if self.in_h1:
self.heading_parts.append(data.strip())
url = "https://example.com/"
request = Request(url, headers={"User-Agent": "LearningScraper/1.0"})
with urlopen(request, timeout=15) as response:
content_type = response.headers.get_content_type()
html_text = response.read().decode(response.headers.get_content_charset() or "utf-8")
if content_type != "text/html":
raise ValueError(f"Expected HTML, received {content_type}")
parser = FirstHeadingParser()
parser.feed(html_text)
record = {"url": url, "heading": " ".join(parser.heading_parts)}
print(json.dumps(record, indent=2))
期待される見出しは「Example Domain」です。スクリプトは記述的なユーザーエージェント、タイムアウト、コンテンツタイプのチェック、および明示的なデコードを使用します。それらの詳細は小さいですが、ターゲットが予測できなくなったときに重要な習慣を確立します。
RequestsとBeautiful Soupの使用
RequestsとBeautiful Soupは同じワークフローを短くします。Requestsはレスポンスを取得し、Beautiful SoupはHTMLをパースし、CSSスタイルの選択をサポートします。公式の Beautiful Soupドキュメント はパーサーの選択、タグ検索、CSSセレクタ、およびツリーナビゲーションについて説明します。
import requests
from bs4 import BeautifulSoup
url = "https://example.com/"
response = requests.get(
url,
headers={"User-Agent": "LearningScraper/1.0"},
timeout=15,
)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
heading = soup.select_one("h1")
if heading is None:
raise ValueError("The page did not contain an h1 element")
print({"url": response.url, "heading": heading.get_text(" ", strip=True)})
依存関係を仮想環境にインストールします。 python -m pip install requests beautifulsoup4. 実際のプロジェクトでバージョンを固定し、新しい環境が同じ依存関係セットを解決するようにします。スクレイパーが成長する際には、リクエストと解析コードを別に保っておきます。
持続するセレクタの選択
セマンティック要素
見出し、記事、時間、価格ラベル、またはカノニカルリンクは、視覚的ラッパークラスよりも意味をより明確に表現することがよくあります。
安定した属性
ドキュメント化されたデータ属性、アイテムプロパティ、アクセシブルラベル、およびIDは、生成されたスタイリングクラスよりも長く存在することがあります。
URLパターン
リンクが持続可能なパス形状を持つ場合、ビジュアルカードのレイアウトが変更されるときに発見をサポートできます。
構造化ページデータ
公開JSONまたは埋め込まれた構造化データは、アクセスが許可されている場合、プレゼンテーションマークアップよりもフィールド名をよりよく保持する可能性があります。
セレクタは必要なフィールドと同じくらい具体的でなければならず、それ以上ではない。6つのネストされたクラスのチェーンは簡単に壊れる。裸 div セレクタが広すぎます。認可されたソースから小さなHTMLフィクスチャを保存し、必須フィールドが存在し続ける一方で、オプションフィールドはnullである可能性があることをテストしてください。
最初の一致する要素が正しいとは限らない。ラベル、親コンテキスト、単位、および標準URLを確認してください。価格がセール、定価、または分割払いを表すことができる場合、スキーマはすべての値を1つのフィールドに強制するのではなく、区別を保持するべきです。
静的HTML対動的ページ
Requestsとurllibはサーバーの応答を取得しますが、ページのJavaScriptは実行しません。もしブラウザーに表示されるデータが欠落している場合、 response.text、ページはロード後にそのコンテンツを取得または構築する場合があります。初期ソースとレンダリングされたドキュメントを表示して、違いを確認してください。
ダイナミックページは、必ずしもブラウザの自動化を必要としません。ページは、サイトが文書化またはブラウザに公開するパブリックJSONエンドポイントを呼び出すことがあります。直接使用が許可され、安定している場合、構造化データは検証が容易になります。コンテンツがインタラクション、クライアントレンダリング、または可視状態に依存する場合は、ブラウザを使用し、曖昧な遅延ではなく、意味のある要素が表示されるのを待ちます。
Scrapeless Scraping Browserは、JavaScriptのレンダリングとインタラクションのための管理されたブラウザセッションを提供します。Pythonアプリケーションは、サポートされているブラウザフレームワークまたはScrapeless統合を通じて接続し、レンダリングされたコンテンツを収集し、その後通常の解析および検証ステージを再利用することができます。
記録のクリーニングと保存
抽出された文字列は通常、正規化が必要です。周囲の空白を削除し、有意義な内部スペースを保持し、数値をその通貨または単位で解析し、変換が情報を失う可能性があるときは生のソース値を保持します。欠落しているオプションフィールドは、発明されたゼロまたは空の主張ではなく、nullとして表現します。
レコードには出所が含まれているべきです:ソースURL、利用可能な場合の標準URL、フィールド値、およびデータセットに関連する時間またはソースバージョン。小規模プロジェクトでは、JSON Linesが便利です。なぜなら、各行が独立したオブジェクトだからです。CSVはフラットなレコードに適しています。SQLiteは、サーバーを必要とせずに型、インデックス、一意性制約、およびクエリを追加します。
ストレージ前に検証してください。必須フィールドが存在する必要があり、URLは絶対的である必要があり、列挙された値はスキーマと一致し、数値範囲は妥当である必要があります。表示タイトルが変更される可能性があるため、安定したソース識別子を使用して重複を排除してください。
責任ある保守可能なスクレイピング
責任あるスクレイピングは、許可と範囲から始まります。サイトの利用規約、ロボット指令、適用法、著作権、プライバシー義務、および公式APIを確認してください。記載された目的に必要な公開フィールドのみを収集します。承認なしに、プライベート、機密、制限された、または認証された資料にアクセスしないでください。
作業量を制限してください。適切な場合には変更されていないページをキャッシュし、不必要な繰り返しリクエストを避け、同時実行を控えめに保つ。文脈が許すときにはクライアントを特定してください。収集した個人データを保護し、それを収集する前に保存と削除のルールを定義してください。
メンテナンス性は可視的な契約から生じます。最終的なURL、ステータス、コンテンツタイプ、セレクターカウント、検証の失敗を秘密を保持せずにログに記録してください。代表的なHTMLに対するテストを追加します。セレクターが変更された場合、新しいページを確認し、空の出力で失敗を隠すのではなく、故意に抽出ルールを更新してください。
スクリプトからプロダクションパイプラインへ
プロダクションスクレイパーは、スケジューリング、取得、解析、検証、ストレージ、および監視を分離します。各ステージには明確な入力と出力があります。これにより、フィールド検証を再記述することなく、ブラウザレンダリングで静的リクエストを置き換えたり、セレクタに触れずにストレージを変更したりすることが可能になります。
- スキーマと許可されたソース範囲を定義します。
- 代表的な応答をキャプチャし、それが意図されたページであることを確認します。
- セレクタとフィールドレベルのバリデーションを書く。
- ページ番号が機能した後にのみ、制限付きページネーションを追加します。
- すべてのレコードにプロヴェナンスと安定した識別子を保存してください。
- フィールドの欠落、セレクタ数、レスポンスタイプ、およびソースの変更を監視します。
- ワークフローがスケールするにつれて、アクセスポリシーとデータ保持を確認してください。
学ぶ際はサンプルを小さく保ちましょう。正確で追跡可能なレコードを十件生成するスクレイパーは、数千の検証されていない文字列を収集するものよりも優れた基盤です。
結論
Pythonを使用したWebスクレイピングは、観察可能な段階のシーケンスです:リクエスト、解析、選択、検証、保存です。許可された静的ページから始め、安定したセレクタを使用し、出所を保持し、生成するレコードをテストしてください。コンテンツがレンダリングやインタラクションを必要とする場合にのみブラウザを追加し、プロジェクトが成長するにつれてアクセス、プライバシー、作業負荷、メンテナンスの制約を明示的に保ってください。
静的HTMLを超えた準備はできていますか?
Pythonデータワークフローを管理されたブラウザレンダリングに接続して、動的な公開ページを作成します。
今日サインアップして、 $5の無料クレジット — クレジットカードは不要です.
$5のクレジットを取得する →FAQ
Pythonを使ったウェブスクレイピングは合法ですか?
ウェブスクレイピングは、1つの普遍的なルールに支配されていません。合法性は、管轄区域、データ、アクセス方法、契約条件、著作権、プライバシー、意図された使用に依存します。公共データを使用し、サイトの利用規約やロボット指令を確認し、適切な場合には公式APIを優先し、重要なプロジェクトについては資格のある法的助言を求めてください。
Beautiful SoupとRequestsはJavaScriptを実行しますか?
いいえ。RequestsはHTTPレスポンスを取得し、Beautiful Soupは受け取ったHTMLまたはXMLを解析します。どちらもページのJavaScriptを実行しません。必要なコンテンツがレンダリングや対話後にのみ表示される場合は、認可された構造化エンドポイントまたはブラウザに基づくワークフローを使用してください。
初心者は最初に何をスクレイピングすべきですか?
安定したデモページまたは明示的に意図された使用を許可するサイトから始めてください。1ページから1つまたは2つのフィールドを抽出し、それを検証し、小さなレコードを保存します。学習中はアカウントデータ、個人データ、大規模なクロールを避けてください。
セレクタが信頼できるかどうかはどのように知ることができますか?
信頼できるセレクタはフィールドの意味に対応し、代表的なページ全体で安定しています。意味のあるタグ、ラベル、文書化された属性、耐久性のあるURLパターンを優先してください。必要なフィールドとオプションのフィールドを保存された認可されたサンプルと照らし合わせてテストし、必要な要素が消えたときには明示的に失敗します。
Pythonスクレイパーはいつ管理されたブラウザを使用すべきですか?
ターゲットコンテンツがJavaScriptのレンダリング、スクロール、ナビゲーション、または直接のHTTPレスポンスでは提供できない対話を必要とする場合は、管理されたブラウザを使用してください。取得がブラウザサービスに移動しても、Pythonアプリケーション内でパース、検証、出所、アクセスポリシーを維持してください。