selectolax ウェブスクレイピング:Pythonにおける高速HTMLパース
Senior Web Scraping Engineer
TL;DR:
- **selectolaxはCSSセレクタを用いてHTMLを高速に解析します。**これは、純粋なPythonの解析ではなく、CベースのLexborエンジンをラップしているためです。
- selectolaxは取得を行いません。 HTTPクライアントはなく、JavaScriptをレンダリングもせず、バイトを渡すとそれを解析するだけです。
- そのギャップは1つのスクリプトに現れます。 JavaScriptでレンダリングされたデモページに対する素のGETリクエストはselectolaxに0のクオートノードを返しますが、Scrapeless Universal Scraping APIを通じて
js_renderで取得した同じURLはすべて10を返します。 - このガイドでの解析は実際のものです。 ライブ実行は、
cssとcss_firstを使用して、レンダリングされたHTMLからすべての10のクオートを著者とタグ配列を保持したまま引き出しました。 - 2つのレイヤーは明確に分かれています。 Scrapelessが取得とレンダリングを行い、selectolaxがバイトをレコードに変換します。どちらも相手の仕事に手を出すことはありません。
- 取得側のスタートが自由です。 app.scrapeless.comでScrapeless APIキーを作成してください。
selectolaxが何か、そして何でないか
selectolaxは速度のために構築されたPython HTMLパーサーです。これはLexborエンジンにバインドされており、これはHTML標準を実装したCライブラリです。そのため、ドキュメントを解析しCSSセレクタを実行することは、インタープリターではなくコンパイルされたコードで行われます。高ボリュームの抽出、すなわち何千ものページやタイトなループの場合、その違いが人々がより重いパーサーではなくこれを選ぶ理由です。
これはパーサーであり、パーサーのみです。selectolaxにはHTTPクライアントがなく、セッションを保持せず、JavaScriptを実行しません。文字列やバイトを与えれば、それをクエリできるツリーを構築しますが、URLを取得するように頼んでも、そのためのメソッドはありません。したがって、すべての「selectolaxウェブスクレイピング」設定は2層で構成されます。忠実なHTMLを取得するものと、それをデータに変換するselectolaxです。このガイドでは、最初の層のためにScrapeless Universal Scraping APIを使用します。なぜなら、素のHTTPクライアントはJavaScriptでコンテンツを構築するページで間違ったバイトを返すからです。Python側のより広範なツアーについては、Pythonウェブスクレイピングチュートリアルがこの周辺のエコシステムをカバーしています。
インストール
selectolaxとrequestsが全ツールチェーンです。このガイドが書かれた時のバージョンはselectolax 0.4.11です:
bash
pip install "selectolax==0.4.11" requests
キーを環境に保管し、ソースには決して含めないでください:
bash
export SCRAPELESS_API_KEY="sk_your_scrapeless_key"
解析に値するHTMLを取得
解析の質は取得の忠実さに制約されるため、そこから始めます。JavaScriptでレンダリングされたページでは、素のHTTPクライアントが受け取るドキュメントは、読者が見るドキュメントとは異なります:コンテンツは、スクリプトがDOMを構築した後にしか到着せず、このライフサイクルはHTMLスクリプティング仕様によって定義されます。1つのスクリプトはselectolax自体を通じてその違いを測定します:
python
# fidelity.py — selectolaxが見るもの:素のGET対サーバーサイドレンダリング
import os
import requests
from selectolax.lexbor import LexborHTMLParser
URL = "https://quotes.toscrape.com/js/"
plain = requests.get(URL, timeout=60).text
print("plain GET chars:", len(plain), "| quote nodes:", len(LexborHTMLParser(plain).css("div.quote")))
resp = requests.post(
"https://api.scrapeless.com/api/v2/unlocker/request",
headers={"Content-Type": "application/json", "x-api-token": os.environ["SCRAPELESS_API_KEY"]},
json={"actor": "unlocker.webunlocker", "input": {"url": URL, "js_render": True}},
timeout=120,
)
resp.raise_for_status()
rendered = resp.json().get("data", "")
print("rendered chars:", len(rendered), "| quote nodes:", len(LexborHTMLParser(rendered).css("div.quote")))
この実行は、素の取得に対して0のクオートノードを、レンダリングされたものに対して10を出力します:
text
plain GET chars: 5806 | quote nodes: 0
rendered chars: 8940 | quote nodes: 10
レンダリング、アンロック、プロキシルーティングはすべてその1つのPOST内でサーバーサイドで行われます — Universal Scraping APIが取得層で、レンダリングされたバイトがselectolaxが解析すべきものです。
selectolaxで解析する
実際のHTMLを手に入れれば、selectolaxは抽出を行います。cssはセレクタにマッチするすべてのノードを返し、css_firstは最初のノードを返すので、各レコードからフィールドを引き出すことができます。セレクタはW3Cセレクタ仕様に従い、すでにCSSで使用しているのと同じ構文です:
python
# extract.py — レンダリングされたページを取得し、selectolaxでレコードを抽出
import os
import requests
from selectolax.lexbor import LexborHTMLParser
resp = requests.post(
"https://api.scrapeless.com/api/v2/unlocker/request",
ヘッダー={"Content-Type": "application/json", "x-api-token": os.environ["SCRAPELESS_API_KEY"]},
json={"actor": "unlocker.webunlocker", "input": {"url": "https://quotes.toscrape.com/js/", "js_render": True}},
タイムアウト=120,
)
resp.raise_for_status()
tree = LexborHTMLParser(resp.json().get("data", ""))
レコード = []
for quote in tree.css("div.quote"):
レコード.append({
"text": quote.css_first("span.text").text(),
"author": quote.css_first("small.author").text(),
"tags": [tag.text() for tag in quote.css("a.tag")],
})
print("レコード:", len(レコード))
print("最初の著者:", レコード[0]["author"])
print("最初のタグ:", レコード[0]["tags"])
ライブ実行では、最初の著者とタグの配列がそのままの状態で10件のレコードが返されました:
```text
レコード: 10
最初の著者: アルバート・アインシュタイン
最初のタグ: ['変化', '深い考え', '思考', '世界']
これが全体のスクレイパーです: 取得とレンダリングのための1つのPOST、クエリのための1つのツリー。 text()はノードのテキストコンテンツを返し、レコードごとに辞書のリストを構築するのが、ページ上の任意の繰り返しブロックに適用できるパターンです。
無料プランでAPIキーを取得: app.scrapeless.com
高度なパターン
- 速度のために
LexborHTMLParserを使用し、控えめなバックエンドにはHTMLParserを使用する。 selectolaxは、同じAPIの背後に両方のエンジンを出荷しています; Lexborは新しく、より高速で、大量処理には適したデフォルトです。 default付きのcss_firstを優先する。node.css_first("span.text", default=None)は、フィールドが欠けているときにエラーを出す代わりにNoneを返し、異なるレコードのループでクラッシュしないようにします。.attributesで属性を読み取る。 リンクや画像の場合、node.attributes.get("href")はノードから属性を引き出します — セレクターが要素を見つけ、.attributesがそのデータを読み取ります。- ツリーが必要ない場合はMarkdownを取得する。 読みやすいテキストだけが必要な場合、Scrapeless APIはレンダリングされたコンテンツを直接返すことができ、構造化されたフィールドに対してセレクターレベルの制御が必要な場合にselectolaxを使います。
トラブルシューティング
- ブラウザで表示できるページからゼロノード。 コンテンツがJavaScriptでレンダリングされていて、取得したのがプリレンダリングHTMLでした。最初のスクリプトが行うように、既知のセレクターを数えてください; ほとんど空のツリーは取得の問題で、
js_renderで修正されます。セレクターの問題ではありません。 AttributeError: 'NoneType' object has no attribute 'text'。css_firstが何も見つけず、Noneに.text()を呼び出しました。default=Noneを渡してから読み取る前に確認するか、セレクターがレンダリングされたマークアップに一致することを確認してください。- テキストに余分な空白がある。
text()は生のノードテキストを返します;.strip()を呼び出すか、ノードが子を持つ場合にそのテキストを結合したいときは、deep=Trueまたはseparatorオプションを渡してください。 - エンコーディングが間違っているように見える。 誤ってデコードされた文字列ではなく、レスポンスバイトを渡してください; selectolaxは、バイトを渡すとドキュメントの宣言されたエンコーディングを読み取ります。
結論
selectolaxはネットワークに触れないパースレイヤーとしてその地位を確立しています: 忠実なHTMLを渡すと、記録を迅速に返し、あなたがすでに知っているCSSセレクターで操作します。そのすべてが可能かどうかを決定するのは取得であり、最初のスクリプトの0対10の数がそれを決定し、1つのサーバーレンダリングされたPOSTがギャップを埋めます。これら2つをワイヤ接続すれば、デモページの10件の引用がクリーンな辞書として到着し、タグも含まれます。
無料のScrapelessアカウントを作成してAPIキーを取得し、開発者ドキュメントがunlocker.webunlockerのパラメータをカバーしています。定期的なジョブを計画する際は、Scrapelessの料金を確認してください。
FAQ
Q: selectolaxは自力でウェブサイトをスクレイプできますか?
いいえ。selectolaxは、すでに持っているHTMLを解析します; HTTPクライアントはなく、JavaScriptもレンダリングしません。取得レイヤーと組み合わせてください — ここではScrapeless Universal Scraping API、サーバー側でページをレンダリングします — そしてselectolaxが返されたバイトから抽出を処理します。
Q: BeautifulSoupの代わりにselectolaxを使う理由は?
速度です。selectolaxはCベースのLexborエンジンをラップしているため、解析およびセレクタークエリはコンパイルされたコードで実行され、高ページボリューム時に重要です。トレードオフは、機能の表面が小さいことです; 多くのページでのセレクターに基づいた抽出には、通常それが正しいトレードとなります。
Q: cssとcss_firstの違いは何ですか?
cssは、セレクタに一致するすべてのノードのリストを返します。css_firstは、最初の一致のみ(または指定したdefault)を返します。cssを使用して検索結果のような繰り返しのブロックをループ処理し、css_firstを使用して各ブロックから単一のフィールドを取得します。
Q: SelectolaxはJavaScriptでレンダリングされたページを扱えますか?
単独では扱えません — スクリプトを実行しません。初期のHTMLの後にコンテンツが読み込まれる場合、通常のfetchではselectolaxに空のツリーを渡します。最初にjs_renderを使用してScrapeless API経由でページを取得し、その後レンダリングされたHTMLを解析します。このガイドに従ってください。
Q: Selectolaxを使用したスクレイピングは合法ですか?
パーサーは収集ルールを変更しません。公開ページのみを取得し、サイトの利用規約とロボット排除プロトコルに標準化されたロボットの指示を尊重し、量を制限し、適用される法律に従って個人データを扱ってください。
Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。



