スクレイピング

pythonによるスクレイピング

第一章

pythonのライブラリ、urllibでurlopenをダウンロードする

pipはpythonのパッケージマネージャ

beautifulsoupをインストール

第五章

メディアファイルの格納方法

①URLの参照
② ファイルそのもののダウンロード

URLの参照の特徴

  • ファイルをダウンロードする必要がないので、スクレイパーがずっと高速で帯域幅もずっと少なくてすむ
  • URLだけを格納するので容量をとらない
  • URLを格納し、追加のファイルダウンロードがないので簡単にコードが書ける。
  • 大きなファイルダウンロードが無いのでホストサーバ

BSのfindAll()

引数

findAll(tag, attributes, recursive, text, limit, keywords)

tag

タグの文字列名やリストを渡せる。
.findAll("h1")
次のコードはヘッダタグ全てのリストを返す
.findAll({"h1", "h2", "h3", "h4", "h5", "h6"})

attributes

指定した属性のいずれかを含むタグを返す
.findAll("span", {"class", :{"green", "red"}})

recursive

htmlツリーの階層をどこまで深く探すか。
デフォルトはTrue。引数に指定したタグを求めて子、孫とレイヤーを下りる。
Falseならhtmlのトップレベルしか見ない。
発音はrɪkə́ːrsɪv。

text

この引数に指定したテキストが「一致するかどうか」だけを調べる。
例えば、「the prince」が何回タグに囲まれていたかを見つけたいなら
以下のコードを記述する。出力は7。

nameList = bsObj.findAll(text="the prince")
print(len(nameList))

引数limitはfindAllだけで使われる。
find関数は、limitが1のfindAll関数と同じ。
ページの最初から数えてn個の要素だけを取り出したいならこの引数を使う。

子孫について

基本的に指定したタグの子孫をオブジェクトとしている。
例えばbsObj.body.h1は、bodyタグの子孫である最初のh1タグを取り出します。
bodyの外にあるタグを見つけようとはしません。

同様にbsObj.div.findAll("img")は、文書中の最初のdivタグを見つけ、
そのdivタグの子孫である全てのimgタグのリストを取り出します。

子である子孫だけを見つけたいなら、「.childrenタグ」を使うことができます。

兄弟について

まずポピュラーなnext_siblings関数とprevious_siblings関数から紹介します。
以下のコードを見てください。

for sibling in bsObj.find("table", {"id" : "giftList"}).tr.next_siblings:
print(sibling)

このコードはテーブルで作られた表から表題行を除いたすべての行をprintします。
「idにgiftListと指定されたテーブルタグ」の中で、
「一番最初に出てくるtr(table row)タグ」を探し、
【その次から出てくる兄弟タグのリスト】を返します。

previous_siblingsと指定することで前に出てくるタグのリストを取得することもできます。
next_sibling、previous_siblingとすると「タグのリスト」ではなく、
「次のタグ1つだけ、前のタグ1つだけ」を返してしまうので注意してください。

親について

BSの親を見つける関数は.parent、もしくは.parents関数です。

print(bsObj.find("img", {"src":"../img/gifts/img1.jpg"}).parent.previous_sibling.get_text())

このコードは、../img/gifts/img1.jpgにある画像が表すオブジェクトの価格を印刷します。
処理手順は以下のようになります。

<tr>
    <td>
    <td>
    <td id="price">(3)
        -テキストだよ$15.00テキストだよ(4)
    <td id="img1">(2)
        -<img src="../img/gifts/img1.jpg">(1)

1.まず src="../img/gifts/img1.jpg"の画像タグが選ばれる
2.そのタグの親を選ぶ(この場合は<td id="img1">)
3.そのtdタグのprevious_siblingを選ぶ(この場合は<td id="price">
4.そのタグのテキスト「テキストだよ$15.00テキストだよ」を選ぶ

属性へのアクセス

任意の属性を持つタグに直接アクセスすることもできます。
これは特に対象のURLがhref属性に囲まれているaタグや、目的画像がsrc属性に膨れまれているimgタグで活用できます。
Pythonのdictionaryオブジェクトが返されるので、属性の取り出しや操作が簡単になります。

pythonでは以下のようにして、属性リストにアクセスできます。

myImgTag.attrs["src"]

ラムダ式について

ラムダ式とは「他の関数の引数として渡される関数」
bsObj.findAll(lamda tag: len(tag.attrs) == 2)

上記のコードでは2つの属性を持つタグをすべて取り出すことができます。
(「len」関数はリストに含まれる要素数を取得します。
リストの他に文字列やタプル、辞書などの要素数を取得できます。)
つまり、次のようなタグが見つかります。

<div class="body" id="content"></div>
<span style="color:red" class="title"></span>