それでは、さっそく見ていこう。
Ubuntu 16.04LTSの場合の準備
Ubuntu 16.04では、python3系がデフォルトになった。そして、このpyqueryパッケージが標準のリポジトリに入ったので、次のコマンドでインストールが完了する。
suto apt-get install python3-pyquery
Ubuntu 14.04LTSの場合の準備
まずはPythonパッケージ管理ソフトのpipをインストールする。UbuntuではPython2系とPython3系ではアプリケーションが異なるので注意する。ここでは、Python3系のpipをインストールする。
sudo apt-get install python3-pip
次にpyqueryを使うために必要なライブラリをインストールする。
sudo apt-get install libxml2-dev
sudo apt-get install libxslt1-dev
sudo apt-get install zlib1g-dev
最後に、pip3を用いてpyqueryをインストールする。pyqueryはlxmlを使用しているので、lxmlをインストールした後、pyqueryをインストールする。
sudo pip3 install lxml
sudo pip3 install pyquery
これで、pyqueryを使用する準備が整った。
ちなみに、このpip3コマンドでインストールしたパッケージは「/usr/local/lib/python3.4/dist-packages/」ディレクトリに配置される。
pyqueryを用いてウェブスクレイピング
さて、ここからは実際にpyqueryを用いてウェブスクレイピングを行う。
ここでは例として、CRANパッケージのサイト「Table of available packages, sorted by date of publication 」から公開日、パッケージ名、URL、タイトルを抽出してみる。取得する情報は<table>で囲まれているので、各<tr>を抽出した後に<td>を見ていけばよい。
import urllib.request
from pyquery import PyQuery as pq
if __name__ == '__main__' :
# Htmlファイル取得
opener = urllib.request.build_opener()
request = urllib.request.Request('https://cran.r-project.org/web/packages/available_packages_by_date.html')
html = opener.open(request).read()
for tr_node in pq(html).find('tr'):
# tdノード取得
td_nodes = pq(tr_node)('tr').find('td')
# 公開日取得
published = td_nodes.eq(0).text()
# パッケージ名取得
name = td_nodes.eq(1).text()
# URL取得
url = td_nodes.eq(1).find('a').eq(0).attr('href')
# タイトル取得
title = td_nodes.eq(2).text()
# 表示
if published and name and url and title:
print(published + '\t' + name + '\t' + url + '\t' + title)
上記のコードを「test.py」として保存してPython3.4で実行してみる。
python3.4 test.py
結果は以下のように表示される。
2014-09-17 EntropyEstimation ../../web/packages/EntropyEstimation/index.html Estimation of Entropy and Related Quantities
2014-09-17 fCopulae ../../web/packages/fCopulae/index.html Rmetrics - Bivariate Dependence Structures with Copulae
2014-09-17 gamlss.dist ../../web/packages/gamlss.dist/index.html Distributions to be used for GAMLSS modelling
2014-09-17 geostatsp ../../web/packages/geostatsp/index.html Geostatistics using SpatialPoints and rasters
2014-09-17 simsalapar ../../web/packages/simsalapar/index.html Tools for Simulation Studies in Parallel with R
2014-09-17 yuima ../../web/packages/yuima/index.html The YUIMA Project package for SDEs
2014-09-16 berryFunctions ../../web/packages/berryFunctions/index.html function collection related to hydrology, zooming and shapefiles
2014-09-16 compute.es ../../web/packages/compute.es/index.html Compute Effect Sizes
簡単に解説すると、「pq(html).find(‘tr’)」の部分で、htmlファイルの中から<tr>の一覧を作成して、「pq(tr_node)(‘tr’).find(‘td’)」の部分で、取り出した一つの<tr>内の<td>の一覧を取得して、「td_nodes.eq(0).text()」の部分で、<td>の最初のノードのテキストを取得している。
find関数の引数は文字列でcssのように指定して抽出する。例えば、<a>のみを抽出したければ、「find(‘a’)」とすればよいし、<div class=”test”>内の<p>を抽出したければ、「find(‘div.test p’)」とすればよい。
ウェブスクレイピングの注意点
ここで、ウェブスクレイピングの注意点を述べておきたい。上記の例では一つのサイトのhtmlファイルを取得したのみだが、取得したURLを元に次々とhtmlファイルを取得することも容易だ。その際に、一時停止処理を組み込むことを忘れてはいけない。
もし、一時停止処理を組み込まなければ、1秒間に何十回もアクセスすることになり、相手サーバに多大な負荷を掛けてしまう。htmlファイルを取得したら、次のhtmlファイルを取得するまでに、最低でも1秒以上の間隔を設けるようにした方がよい。もちろん、間隔は長ければ長い方がよい。
一時停止処理はわずか2行で済む。Pythonファイルの最初に「import time」を追加して、一時停止したい箇所に「time.sleep(1)」を追加するだけだ。time.sleep(1)は1秒間の一時停止、time.sleep(60)は1分間の一時停止、一時停止したい秒数をtime.sleep関数の引数に指定する。
最後に
pyqueryを用いれば、ウェブスクレイピングを簡単に行うことができることがお分かりいただけたと思う。節度を守りつつ、効率よくウェブ上のデータを取得する手助けとなれば幸いだ。