PyQueryは、Pythonで書かれた軽量なjQueryライクなライブラリで、HTMLやXMLドキュメントのパース、操作、検索を非常に直感的に行うことができます。BeautifulSoupがPythonicなAPIを提供しているのに対し、PyQueryはWeb開発者が慣れ親しんだjQueryのCSSセレクタ構文をPythonでほぼそのまま利用できる点が最大の特徴です。
PyQueryライブラリ
ウェブスクレイピングにおいて、RequestsでHTMLを取得した後、PyQueryで必要な要素を簡単に抽出・操作するのに適しています。特に、jQueryを使い慣れている開発者にとっては、学習コストが低く、迅速にスクレイピングコードを書ける強力なツールとなります。
1. PyQueryのインストール
PyQueryはPythonの標準ライブラリではないため、pipを使用してインストールする必要があります。
pip install pyquery
PyQueryは内部でHTMLパーサーとしてlxmlを使用しています。lxmlは高速で堅牢なパーサーであり、PyQueryをインストールする際に自動的に依存関係としてインストールされます。
2. PyQueryの基本的な使い方とオブジェクトの作成
PyQueryオブジェクトを作成する方法はいくつかあります。
- 文字列からの作成:
HTML/XMLの文字列を直接渡します。
Pythonfrom pyquery import PyQuery as pq html_doc = """ <html> <head><title>My Page</title></head> <body> <div id="container"> <h1 class="main-title">Welcome</h1> <ul id="menu"> <li class="item"><a href="/home">Home</a></li> <li class="item active"><a href="/about">About</a></li> <li class="item"><a href="/contact">Contact</a></li> </ul> <p>This is a paragraph.</p> </div> </body> </html> """ d = pq(html_doc) print(d('title').text()) # My Page - ファイルからの作成:
HTMLファイルやXMLファイルを直接読み込みます。
Python# 例えば 'mypage.html' というファイルがある場合 # d = pq(filename='mypage.html') # print(d('h1').text()) - URLからの作成:
URLを指定すると、Requestsライブラリ(または同様のHTTPクライアント)を使用してHTMLを取得し、自動的にパースします。
Python# from pyquery import PyQuery as pq # d = pq(url='https://www.google.com') # print(d('title').text()) # Googleこれは手軽ですが、詳細なリクエスト制御(ヘッダー、プロキシ、認証など)が必要な場合は、
RequestsでHTMLを取得してから文字列としてPyQueryに渡す方が柔軟です。
3. 要素の選択(jQueryライクなCSSセレクタ)
PyQueryの核心は、jQueryとほぼ同じ感覚でCSSセレクタを使って要素を選択できる点にあります。
PyQueryオブジェクト d に対して、セレクタ文字列を関数のように呼び出すことで、マッチする要素の集合(これも PyQuery オブジェクト)を取得できます。
# 上記のhtml_docを使用
# タグ名で選択
h1_element = d('h1')
print(h1_element.text()) # Welcome
# IDで選択
container = d('#container')
print(container.attr('id')) # container
# クラスで選択
items = d('.item')
print(f"アイテム数: {len(items)}") # アイテム数: 3
# 複数のクラスで選択
active_item = d('.item.active')
print(active_item.text()) # About
# 階層構造で選択 (子孫セレクタ)
list_links = d('#menu a')
for link in list_links.items(): # .items() で個々のPyQueryオブジェクトをイテレート
print(link.text(), link.attr('href'))
# Home /home
# About /about
# Contact /contact
# 属性セレクタ
contact_link = d('a[href="/contact"]')
print(contact_link.text()) # Contact
# 疑似クラスセレクタ (一部サポート)
# first-child, last-child, eq(index) など
first_item = d('.item:first')
print(first_item.text()) # Home
セレクタのチェイン (Chaining):
jQueryと同様に、セレクタをチェインさせて絞り込むことができます。
# #menuの中の.activeクラスを持つ要素の中のaタグ
about_link_chained = d('#menu').find('.active').find('a')
print(about_link_chained.text()) # About
4. 抽出した要素からの情報取得
選択したPyQueryオブジェクトから、様々な情報を取得できます。
4-1. テキストコンテンツの取得
- element.text():
選択した要素群のすべてのテキストコンテンツを結合して返します(子孫要素のテキストも含む)。
Pythoncontainer_text = d('#container').text() print(container_text) # Welcome # Home About Contact # This is a paragraph.
4-2. HTMLコンテンツの取得
- element.html():
選択した要素群の最初の要素の内部HTMLを返します。
Pythonmenu_html = d('#menu').html() print(menu_html) # <li class="item"><a href="/home">Home</a></li> # <li class="item active"><a href="/about">About</a></li> # <li class="item"><a href="/contact">Contact</a></li>
4-3. 属性値の取得
- element.attr(‘属性名’):
選択した要素群の最初の要素の指定した属性値を返します。
Pythonhome_link_href = d('a:first').attr('href') print(home_link_href) # /home - element.attr(‘属性名’, ‘新しい値’):
属性値を設定することも可能です。
Pythond('a:first').attr('href', 'http://new-home.com') print(d('a:first').attr('href')) # http://new-home.com
4-4. その他の情報取得
element.val():<input>,<select>,<textarea>などのvalue属性を取得。element.is_('セレクタ'): 指定したセレクタにマッチするかどうか(True/False)。element.hasClass('クラス名'): 指定したクラスを持っているか。
5. HTML要素の操作と変更
PyQueryは、スクレイピングで取得したHTMLを編集する際にも非常に便利です。
5-1. 要素の追加・削除
element.append('追加するHTML'): 要素の最後にHTMLを追加。element.prepend('追加するHTML'): 要素の先頭にHTMLを追加。element.before('追加するHTML'): 要素の前に兄弟要素としてHTMLを追加。element.after('追加するHTML'): 要素の後に兄弟要素としてHTMLを追加。element.remove('セレクタ'): 指定したセレクタにマッチする要素を削除。element.empty(): 要素の子孫をすべて削除し、要素自体は残す。Pythond('#menu').append('<li class="item">New Item</li>') d('.active').remove() # activeなアイテムを削除 print(d('#menu').html()) # <li class="item"><a href="/home">Home</a></li> # <li class="item"><a href="/contact">Contact</a></li> # <li class="item">New Item</li>
5-2. クラスの操作
element.addClass('クラス名'): クラスを追加。element.removeClass('クラス名'): クラスを削除。element.toggleClass('クラス名'): クラスの追加・削除を切り替え。
5-3. テキスト/HTMLの置き換え
element.text('新しいテキスト'): 要素内のテキストを置き換え。element.html('新しいHTML'): 要素内のHTMLを置き換え。
5-4. その他の操作
element.wrap('HTMLタグ'): 要素を指定したHTMLタグで囲む。element.wrapAll('HTMLタグ'): 選択した要素群全体を指定したHTMLタグで囲む。element.clone(): 要素のコピーを作成。
6. HTMLツリーの移動(Traversing the Tree)
jQueryと同様に、親、子、兄弟関係をたどって要素を移動できます。
element.parent(): 親要素element.parents('セレクタ'): 条件にマッチするすべての祖先要素element.children('セレクタ'): 直下の子要素element.find('セレクタ'): 子孫要素を検索element.siblings('セレクタ'): 兄弟要素element.next('セレクタ'): 次の兄弟要素element.prev('セレクタ'): 前の兄弟要素element.closest('セレクタ'): 最も近い祖先要素
# Aboutリンクの親要素(li.item.active)を取得し、その次の兄弟要素(li.item)を取得
next_sibling_item = d('a[href="/about"]').parent().next()
print(next_sibling_item.text()) # Contact
7. PyQueryの利点とBeautifulSoupとの比較
| 特徴 | PyQuery | BeautifulSoup |
| APIスタイル | jQueryライク (CSSセレクタが中心) | Pythonic (メソッドチェーン、オブジェクト指向) |
| 検索構文 | CSSセレクタ (非常に強力) | CSSセレクタ (select, select_one)、タグ名、属性、正規表現など |
| 学習曲線 | jQuery経験者には低い | Pythonユーザーには自然 |
| HTML変更 | 豊富な変更・操作メソッドが直感的 | HTMLツリーのノード操作 (Tagオブジェクト) |
| 内部パーサー | lxml (高速) |
lxml, html.parser, html5lib を選択可能 |
| 用途 | スクレイピング、HTML生成/変換、簡単なDOM操作 | スクレイピング、HTML解析、データ抽出 |
| コードの簡潔さ | 短く簡潔なコードになりやすい | 構造化されたコードになりやすい |
使い分けのポイント:
- jQueryに慣れていて、CSSセレクタをガンガン使いたい:
PyQueryが強力な武器になります。 - Python標準のオブジェクト指向的な操作に慣れていて、DOMツリーを深く探査・操作したい:
BeautifulSoupの方が馴染みやすいかもしれません。 - 柔軟なパーサー選択や、非常に複雑なテキスト処理が必要:
BeautifulSoupが有利な場合があります。
実際には、両者を組み合わせて使うことも可能です。例えば、PyQueryで大まかな要素を取得し、その中の特定の部分をBeautifulSoupでさらに細かく解析する、といった使い方もできます。
8. まとめ
PyQueryは、PythonでHTML/XMLコンテンツを解析・操作するための、非常に強力で直感的なライブラリです。特に、Web開発の経験がありjQueryのCSSセレクタ構文に慣れている方にとっては、ウェブスクレイピングの効率を大幅に向上させるツールとなるでしょう。
簡潔なコードで複雑な要素選択や操作を実現できるため、プロトタイピングや小規模なスクレイピングプロジェクトにおいてその真価を発揮します。ただし、大規模なプロジェクトでパフォーマンスが最優先される場合や、より低レベルでのHTMLツリー操作が必要な場合は、BeautifulSoupやlxmlのネイティブ機能との連携も視野に入れると良いでしょう。
ウェブスクレイピングを行う際は、必ず対象サイトの利用規約を確認し、robots.txtに従い、サーバーに過度な負荷をかけないよう倫理的な行動を心がけてください。
