lxmlでスクレイピングするときのコツ

lxmlでスクレイピングするときのコツ
目次

PythonでスクレイピングをしようとするとBeautifulSoup4lxmlを使った例が多くあります。今回はlxmlでスクレイピングするときのコツをいくつか紹介します。

lxmlはpip install lxmlでインストールできます。

parse()にはURLを直接渡せる

urllibなどを使ってレスポンスをロードしてからlxmlに渡している例が多くありますが、parse()にURLを渡すとそのURLにアクセスして解析してくれます。

>>> import lxml.html
>>> tree = lxml.html.parse('http://example.com/')

base_urlオプションがURLをもとにセットされるので、相対リンクを絶対リンクに書き換えるでbase_urlを明示的に渡す必要がなくなります。

XPathをコンパイルして再利用する

同じXPathで複数回検索する場合はコンパイルしておくとパフォーマンスが上がります。変数を使うこともできます。

>>> count_elements = lxml.etree.XPath('count(//*[local-name() = $name])')
>>> count_elements(tree, name='h1')
1.0
>>> count_elements(tree, name='p')
2.0

文字コードを指定する

lxmlは文字コードをある程度自動で検出してデコードしてくれますが、検出がうまくいかないときは文字コードを指定すればlxml側でデコードも含めてやってくれます。

>>> parser = lxml.html.HTMLParser(encoding='utf-8')
>>> tree = lxml.html.parse('http://example.com/', parser)

ログインが必要なページを取得する

ブラウザのCookieをPythonから利用する」でブラウザのCookieを読み込んでログイン中のセッションをPythonで使う方法を書きました。

サンプル

上記のテクニックを使ったサンプルです。

# -*- coding: utf-8 -*-
import lxml.html
URLFORMAT = 'http://www.discas.net/netdvd/cd/goodsDetail.do?titleID=%010d'
# XPathをコンパイルして再利用する
find_title = lxml.etree.XPath(
'string(//head/meta[@property="og:title"]/@content)')
is_available = lxml.etree.XPath(
'boolean(id("sectionGoods")//form[@name="UpdateWishListForm"])')
def getinfo(titleid):
url = URLFORMAT % titleid
# libxml2がWindows-31Jを認識してくれないのでCP932を渡す
parser = lxml.html.HTMLParser(encoding='cp932')
tree = lxml.html.parse(url, parser)
# タイトルを取得
title = find_title(tree)
# 「単品リストに追加」フォームを探す
available = is_available(tree)
return title, available
if __name__ == '__main__':
wishlist = [683928, 1209833, 1795844]
for titleid in wishlist:
title, available = getinfo(titleid)
print ('x', 'o')[available], title
view raw discas.py hosted with ❤ by GitHub
指定したCDがDISCASで単品レンタル可能か取得します。