
新着: TUI - 対話型ターミナルインターフェース(Textual搭載)でwxpath式をテストし、データをエクスポートできます。

Python 3.10以上が必要です。
pip install wxpath
# For TUI support:
pip install "wxpath[tui]"
# Immediately launch the TUI via uv:
uvx --from "wxpath[tui]" wxpath-tui
wxpathは、トラバーサルをXPathで直接表現する宣言的なWebクローラーです。命令型のクロールループを書く代わりに、wxpathは何を追跡し何を抽出するかを単一の式で記述できます。wxpathはその式を並行して実行し、幅優先的(breadth-first-ish)に結果を発見次第ストリーミングします。
この式はページを取得し、リンクを抽出し、それらを並行してストリーミングします - クロールループは不要です:
import wxpath
expr = "url('https://quotes.toscrape.com')//a/@href"
for link in wxpath.wxpath_async_blocking_iter(expr):
print(link)
url(...)演算子と///構文を導入することで、wxpathのエンジンは再帰的(またはページネーション)なWebクローリングと抽出を実行できます:
import wxpath
path_expr = """
url('https://quotes.toscrape.com')
///url(//a/@href)
//a/@href
"""
for item in wxpath.wxpath_async_blocking_iter(path_expr, max_depth=1):
print(item)
ほとんどのWebスクレイパーは、最初にクロールの制御フローを書き、その後に抽出を強制します。
wxpathはこれら2つのステップを1つに統合します:
グラフからクリーンで構造化されたJSON階層を直接抽出 - LLMにノイズではなくシグナルを供給します。詳細はLangChain統合を参照してください。
wxpathは決定論的です(つまり、LLMを利用していません)。ネットワークが安定していることを保証できませんが、トラバーサルが安定していることは保証できます。
ドキュメントはこちらから入手できます。
url(...) と ///url(...) の説明import wxpath
from wxpath.settings import CRAWLER_SETTINGS
# Custom headers for politeness; necessary for some sites (e.g., Wikipedia)
CRAWLER_SETTINGS.headers = {'User-Agent': 'my-app/0.4.0 (contact: [email protected])'}
# Crawl, extract fields, build a knowledge graph
path_expr = """
url('https://en.wikipedia.org/wiki/Expression_language')
///url(
//main//a/@href[
starts-with(., '/wiki/') and not(contains(., ':'))
]
)
/map{
'title': (//span[contains(@class, "mw-page-title-main")]/text())[1] ! string(.),
'url': string(base-uri(.)),
'short_description': //div[contains(@class, 'shortdescription')]/text() ! string(.),
'forward_links': //div[@id="mw-content-text"]//a/@href ! string(.)
}
"""
for item in wxpath.wxpath_async_blocking_iter(path_expr, max_depth=1):
print(item)
注意: Wikipediaを含む一部のサイトでは、適切なヘッダーがないリクエストをブロックする場合があります。カスタムUser-Agentを設定するには、上級:エンジン&クローラー設定を参照してください。
上記の式は次のことを行います:
https://en.wikipedia.org/wiki/Expression_language から開始します。<main>セクション内で、/wiki/で始まりコロン(:)を含まないリンクをフィルタリングします。url(...) と ///url(...) の説明url(...)は、ユーザー指定または内部で生成されたURLのコンテンツを取得し、lxml.html.HtmlElementとして返すカスタム演算子です。これにより、さらなるXPath処理が可能になります。///url(...)は深いクロールを示します。ランタイムエンジンに、指定されたmax_depthまでリンクをたどり続けるよう指示します。繰り返しurl()ホップを使用するのとは異なり、単一の式でより深いグラフ探索を記述できます。警告:トラバーサルの爆発を避けるために、max_depthやXPath述語による制約を慎重に使用してください。言語設計の詳細はDESIGN.mdを参照してください。核となる概念とゼロからの言語設計が示されています。
wxpathは式をトラバーサルと抽出のステップ(内部ではSegmentと呼ばれる)のリストとして評価します。
url(...)は、静的(固定URLによる)または動的(XPath式から派生したURLによる)にクロールタスクを作成します。URLは、深度ごとではなく、グローバルにベストエフォートで重複排除されます。
XPathセグメントは、取得されたドキュメント(直前のurl(...)操作で取得されたもの)に対して操作を行います。
///url(...)は深いクロールを示します - 幅優先的(breadth-first-ish)にmax_depthまで進みます。
結果は準備ができ次第、生成(yield)されます。
wxpathはasyncio/aiohttpを優先し、クローリングとデータ抽出のための非同期APIを提供します。
import asyncio
from wxpath import wxpath_async
items = []
async def main():
path_expr = "url('https://en.wikipedia.org/wiki/Expression_language')///url(//@href[starts-with(., '/wiki/')])//a/@href"
async for item in wxpath_async(path_expr, max_depth=1):
items.append(item)
asyncio.run(main())
wxpathは、同期的なコードのシンプルさを保ちながら複数ページを並行してクロールできる、asyncioインシンクAPIも提供します。これは、パフォーマンスが重要となる厳密に同期した実行環境(つまりasyncioイベントループの外部)でのクロールに特に役立ちます。
from wxpath import wxpath_async_blocking_iter
path_expr = "url('https://en.wikipedia.org/wiki/Expression_language')///url(//@href[starts-with(., '/wiki/')])//a/@href"
items = list(wxpath_async_blocking_iter(path_expr, max_depth=1))
wxpathはデフォルトでWXPathEngine(..., robotstxt=True)コンストラクタを介してrobots.txtを尊重します。
wxpath Python APIは構造化オブジェクトを生成します。
式によって、結果には以下が含まれる場合があります:
lxml.*およびlxml.html.*オブジェクトelementpath.datatypes.*オブジェクト(XPath 3.1機能用)WxStr(出典付き文字列値)CLIはこれらのオブジェクトを表示用にプレーンなJSONにフラット化します。 Python APIはデフォルトで構造を保持します。
wxpathはelementpathライブラリを使用してXPath 3.1をサポートし、マップ、配列などの高度なXPath機能を有効にします。これにより、より強力なXPathクエリを作成できます。
path_expr = """
url('https://en.wikipedia.org/wiki/Expression_language')
///url(//div[@id='mw-content-text']//a/@href)
/map{
'title':(//span[contains(@class, "mw-page-title-main")]/text())[1],
'short_description':(//div[contains(@class, "shortdescription")]/text())[1],
'url'://link[@rel='canonical']/@href[1]
}
"""
# [...
# {'title': 'Computer language',
# 'short_description': 'Formal language for communicating with a computer',
# 'url': 'https://en.wikipedia.org/wiki/Computer_language'},
# {'title': 'Machine-readable medium and data',
# 'short_description': 'Medium capable of storing data in a format readable by a machine',
# 'url': 'https://en.wikipedia.org/wiki/Machine-readable_medium_and_data'},
# {'title': 'Domain knowledge',
# 'short_description': 'Specialist knowledge within a specific field',
# 'url': 'https://en.wikipedia.org/wiki/Domain_knowledge'},
# ...]
wxpathはtqdmを介したプログレスバーを提供し、クロールの進行状況を追跡します。これは長時間のクロールに特に便利です。
engine.run(..., progress=True)を設定するか、wxpath_async*(...)関数のいずれかにprogress=Trueを渡して有効にします。
items = wxpath.wxpath_async_blocking("...", progress=True)
> 100%|██████████████████████████████████████████████████████████▎| 469/471 [00:05<00:00, 72.00it/s, depth=2, yielded=457]
wxpathはコマンドラインインターフェース(CLI)を提供し、ターミナルから直接wxpath式をすばやく試して実行できます。
次の例は、"Expression language"ページからWikipediaをクロールし、他のwikiページへのリンクを抽出し、各リンク先ページから特定のフィールドを取得する方法を示しています。
注意:Webコンテンツの性質上、出力は時間とともに変化する可能性があります。
> wxpath --depth 1 \
--header "User-Agent: my-app/0.1 (contact: [email protected])" \
"url('https://en.wikipedia.org/wiki/Expression_language') \
///url(//div[@id='mw-content-text']//a/@href[starts-with(., '/wiki/') \
and not(matches(@href, '^(?:/wiki/)?(?:Wikipedia|File|Template|Special|Template_talk|Help):'))]) \
/map{ \
'title':(//span[contains(@class, 'mw-page-title-main')]/text())[1], \
'short_description':(//div[contains(@class, 'shortdescription')]/text())[1], \
'url':string(base-uri(.)), \
'backlink':wx:backlink(.), \
'depth':wx:depth(.) \
}"
{"title": "Computer language", "short_description": "Formal language for communicating with a computer", "url": "https://en.wikipedia.org/wiki/Computer_language", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Machine-readable medium and data", "short_description": "Medium capable of storing data in a format readable by a machine", "url": "https://en.wikipedia.org/wiki/Machine_readable", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Domain knowledge", "short_description": "Specialist knowledge within a specific field", "url": "https://en.wikipedia.org/wiki/Domain_knowledge", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Advanced Boolean Expression Language", "short_description": "Hardware description language and software", "url": "https://en.wikipedia.org/wiki/Advanced_Boolean_Expression_Language", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Data Analysis Expressions", "short_description": "Formula and data query language", "url": "https://en.wikipedia.org/wiki/Data_Analysis_Expressions", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Jakarta Expression Language", "short_description": "Computer programming language", "url": "https://en.wikipedia.org/wiki/Jakarta_Expression_Language", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Rights Expression Language", "short_description": [], "url": "https://en.wikipedia.org/wiki/Rights_Expression_Language", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
{"title": "Computer science", "short_description": "Study of computation", "url": "https://en.wikipedia.org/wiki/Computer_science", "backlink": "https://en.wikipedia.org/wiki/Expression_language", "depth": 1.0}
Command line options:
--depth <depth> Max crawl depth
--verbose [true|false] Provides superficial CLI information
--debug [true|false] Provides verbose runtime output and information
--concurrency <concurrency> Number of concurrent fetches
--concurrency-per-host <concurrency> Number of concurrent fetches per host
--header "Key:Value" Add a custom header (e.g., 'Key:Value'). Can be used multiple times.
--respect-robots [true|false] (Default: True) Respects robots.txt
--cache [true|false] (Default: False) Persist crawl results to a local database
wxpathは対話的な式テストとデータ抽出のための端末インターフェース(TUI)を提供します。
詳細はTUIクイックスタートを参照してください。
wxpathはオプションでクロール結果をローカルデータベースに永続化します。これは、多数のURLをクロールし、クロールを一時停止したり、抽出式を変更したり、クロールを再起動する必要がある場合に特に便利です。
wxpathは2つのバックエンドをサポートしています:sqliteとredis。SQLiteは単一ワーカー(つまりengine.crawler.concurrency == 1)の小規模クロールに最適です。Redisは複数ワーカーの大規模クロールに最適です。sqliteバックエンドを使用する場合、min(engine.crawler.concurrency, engine.crawler.per_host) > 1のときに警告が表示されます。
使用するには、適切なオプション依存関係をインストールする必要があります:
pip install wxpath[cache-sqlite]
pip install wxpath[cache-redis]
依存関係がインストールされたら、キャッシュを有効にする必要があります:
from wxpath.settings import SETTINGS
# To enable caching; sqlite is the default
SETTINGS.http.client.cache.enabled = True
# For redis backend
SETTINGS.http.client.cache.enabled = True
SETTINGS.http.client.cache.backend = "redis"
SETTINGS.http.client.cache.redis.address = "redis://localhost:6379/0"
# Run wxpath as usual
items = list(wxpath_async_blocking_iter('...', max_depth=1, engine=engine))
設定の詳細はsettings.pyを参照してください。
wxpathはプラグイン可能なフックシステムをサポートしており、クローリングと抽出の動作を変更できます。URLの前処理、HTMLの後処理、抽出値のフィルタリングなどのフックを登録できます。フックは登録された順に実行されます。フックはパフォーマンスに影響を与える可能性があります。
from wxpath import hooks
@hooks.register
class OnlyEnglish:
def post_parse(self, ctx, elem):
lang = elem.xpath('string(/html/@lang)').lower()[:2]
return elem if lang in ("en", "") else None
注意:フックは同期的でも非同期的でも構いませんが、プロジェクト内のすべてのフックは同じスタイルに従う必要があります。同期フックと非同期フックの混在はサポートされておらず、予期しない動作を引き起こす可能性があります。
from wxpath import hooks
@hooks.register
class OnlyEnglish:
async def post_parse(self, ctx, elem):
lang = elem.xpath('string(/html/@lang)').lower()[:2]
return elem if lang in ("en", "") else None
JSONLWriter(別名NDJSONWriter)は、抽出されたデータを改行区切りのJSONファイルに書き込む組み込みフックです。結果を後で簡単に処理できる構造化形式で保存するのに便利です。
from wxpath import hooks
hooks.register(hooks.JSONLWriter)
Python 3.10以上が必要です。
pip install wxpath
永続化/キャッシュの場合、wxpathは以下のバックエンドをサポートします:
pip install wxpath[cache-sqlite]
pip install wxpath[cache-redis]
その他の使用例はEXAMPLES.mdを参照してください。
他のWebスクレイピングツールとの比較はCOMPARISONS.mdを参照してください。
エンジンとクローラーの動作は次のように変更できます:
from wxpath import wxpath_async_blocking_iter
from wxpath.core.runtime import WXPathEngine
from wxpath.http.client.crawler import Crawler
crawler = Crawler(
concurrency=8,
per_host=2,
timeout=10,
respect_robots=False,
headers={
"User-Agent": "my-app/0.1.0 (contact: [email protected])", # Sites like Wikipedia will appreciate this
},
)
# If `crawler` is not specified, a default Crawler will be created with
# the provided concurrency, per_host, and respect_robots values, or with defaults.
engine = WXPathEngine(
# concurrency: int = 16,
# per_host: int = 8,
# respect_robots: bool = True,
# allowed_response_codes: set[int] = {200},
# allow_redirects: bool = True,
crawler=crawler,
)
path_expr = "url('https://en.wikipedia.org/wiki/Expression_language')//url(//main//a/@href)"
items = list(wxpath_async_blocking_iter(path_expr, max_depth=1, engine=engine))
wxpath_async*)オプションmax_depth: int = 1progress: bool = Falseengine: WXPathEngine | None = Noneyield_errors: bool = Falseキャッシュ、スロットリング、並行処理などを有効にするには、settings.pyも使用できます。
max_depthに達すると終了するように設計されています。以下の機能はまだサポートされていません:
このプロジェクトは初期開発段階にあります。コアコンセプトは安定していますが、APIや機能は変更される可能性があります。問題が発生した場合(特にデッドロックしたクロールや予期しない動作)や、実装を希望する機能があれば報告してください(実装を保証するものではありません)。
///)では、無制限の拡張(トラバーサル爆発)を避けるためにユーザーの規律が必要です。max_depth、XPath述語やフィルターを使用してクロール範囲を制限することを検討してください。wxpathを使用したクローラー/データフィードの構築や運用(抽出、スケジューリング、監視、破損修正)やその他のWebスクレイピングのニーズについて支援が必要な場合は、[email protected]までご連絡ください。
wxpathを気に入り、開発を支援したい場合は、寄付をご検討ください。
wxpathはsemverに従います:<MAJOR>.<MINOR>.<PATCH>。
ただし、1.0.0より前は0.<MAJOR>.<MINOR|PATCH>に従います。
AGPL-3.0