Python スクレイピング

lxml によるスクレイピング

正規表現スクレイピングはいかがでしたか?
細かくスクレイピング条件を設定できるのはすばらしいのですが、 正規表現を書き下すのはなかなか難しいですね。
私のような初学者は、もっとやさしい方法がないか探してしまいます。
そんな人にお薦めなのが lxml です。
これをつかうと CSS を条件にスクレイピングすることができます。
CSS セレクタ-は CSS で装飾する要素を指定するための表記方法です。
例えば
body > h1
と表記すると
body 要素の直接の子である h1 要素を指定することができます。
html ファイルが下記のようになっていたとすると
<body>
<h1>
 abcd
</h1>
 ・・・・・
</body>

abcd
を指定する事が可能です。
もしbody のなかに h1 要素が1つしかないとすれば
body h1
とすることも可能です。
body 要素の任意の子要素を指定するなら
body > *
となります。

lxml インスト-ル

lxml と cssselect をインスト-ルします。
cssselect は CSS セレクタを利用するときに必要になります。
Ubuntu 20.04 LTS の場合は
lxml は
/usr/local/lib/python3.8/dist-packages
(4.6.1)
cssselect は
/usr/local/lib/python3.8/dist-packages
(1.1.0)
のなかにすでに入っていました。
インスト-ルされていないときは
yamada@ubuntu-20:~$ sudo pip3 install lxml cssselect
でインスト-ルします。
なお、lxlm は C 拡張モジュ-ルなのでインスト-ル時コンパイルに必要なパッケ-ジが必要なようです。
よって、インスト-ルできない場合は先に
yamada@ubuntu-20:~$ sudo apt install -y libxml2-dev libxslt1-dev libpython3.8-dev zlib1g-dev
を実行してください。

lxml スクレイピングファイル作成

正規表現スクレイピングファイルを作成したときと同じように lxml スクレイピングファイルを作成していきます。

  1. お決まりの作法

    Pyton がインスト-ルされている場所を示めします。
    #!/usr/bin/python3
    Pyton3 のインスト-ル場所がわからない場合は
    $ which python3
    で知ることができます。
    ファイルで使用する文字コ-ドを設定します。
    #coding: utf-8
    HTTP ヘッダーを出力
    print("Content-type: text/html; charset=UTF-8\n\n")
    これで Python から出力された文字は Web で見ることができるようになります。

  2. ライブラリを取り込み

    取り込む必要があるライブラリは1つです。
    import lxml.html

  3. HtmlElementTree オブジェクト作成

    Python スクレイピング概要 のなかで作成した sc_re_hd_enc.py を実行したときできた
    sc_dp.html ファイル
    を読み込み、parse()関数で
    HtmlElementTree オブジェクト tree
    を作成します。
    tree = lxml.html.parse('sc_dp.html')

  4. HtmlElementHtml オブジェクト作成

    getroot()メソッドで HtmlElement オブジェクト html を作成します。
    html = tree.getroot()

  5. href 属性を絶対 URL に変換

    make_links_absolute()メソッドを使用します。
    引数の URL を基準として、すべての a 要素の href 属性を絶対 URL に変換してくれます。

    html.make_links_absolute('https://gihyo.jp/')

  6. セレクター作成

    あらかじめ、抜粋したい部分のセレクター listb を作成します。
    id="listBook" である要素の子である li 要素の子である itemprop="url"
    という属性を持つ a 要素を指定したいので
    listb = '#listBook > li > a[itemprop="url"]'
    とします。
    要するに
    <div id="bookList">
    以下に<li> の項が沢山出現します。
    その中の<a itemprop="url" と書かれた項を </li> まで抜粋しなさい
    ということになります。

  7. 指定セレクターオブジェクト作成

    指定セレクター listb からなるオブジェクト htmlist を作成します。
    htmlist = html.cssselect(listb)

  8. for 文で書籍のURLとタイトルを取得

    セレクタ-で取得した htmlist には 沢山の a 要素の href 属性が入っていますのでここから 書籍の URL とタイトルを順次取得します。
    for ah htmlist:
     url = ah.get('href')
    get() メソッドで属性の値が取得できます。
    また、書籍のタイトルは itemprop="name" という属性を持つ p 要素から取得します。
      p = ah.cssselect('p[itemprop="name"]')[0]
    cssselect メソッドは配列指定が必要です。
    [0] がないとエラ-になります。
     title = p.text_content()
    wbr 要素などが含まれるので text ではなく text_content() メソッドを使います。

  9. 取得した書籍の URL とタイトルを保存

    あらかじめ
    books = []
    として設定しておいた配列 books に順次、
    取得した書籍の URL とタイトル title
    を保存します。
     books.append({'url': url, 'title': title})

  10. 保存したデ-タ確認

    print(books)
    として保存したデ-タを確認します。
    なお、抜粋デ-タを CSV あるいは JSON 形式で保存する方法は
    抜粋したデ-タをファイル保存
    を見てください。


以上をまとめると以下のようになります。


  #!/usr/bin/python3
  #coding: utf-8
  print("Content-type: text/html; charset=UTF-8\n\n")
  import lxml.html
  # HTMLファイル読込 getroot()メソッドで HtmlElement オブジェクト作成
  tree = lxml.html.parse('sc_dp.html')
  html = tree.getroot()
  # 引数の URL を基準として、すべての a 要素の href 属性を絶対 URL に変換
  html.make_links_absolute('https://gihyo.jp/')
  books = []
  # cssselect()メソッドで、セレクターに該当するa要素のリストを取得して
  # 個々の a 要素に対して処理を行う。
  # セレクターの意味:id="listBook"である要素 の子である
  # li要素 の子である itemprop="url"という属性を持つ a 要素
  listb = '#listBook > li > a[itemprop="url"]'
  htmlist = html.cssselect(listb)
  for ah in htmlist:
    # a要素のhref属性から書籍のURLを取得する。
    url = ah.get('href')
    # 書籍のタイトルは itemprop="name"
    # という属性を持つp要素から取得する。
    p = ah.cssselect('p[itemprop="name"]')[0]
    title = p.text_content()
    # wbr要素などが含まれるのでtextではなくtext_content()を使う。
    # 書籍のURLとタイトルを出力する。
    # print(url,"<br>", title,"<br>")
    books.append({'url': url, 'title': title})
  print(books)

本内容を TeraPad 等で作成したら、ファイル名を適当に
sc_rape_by_lxml.py
として保存します。
文字コ-ドは、UTF-8N
BOM なし
改行コ-ドは、LF
です。
for 文の中のインテンドには注意してください。
Tab 設定と半角空白設定を混在させると for 文がうまく動きませんよ。
私は for 文の中のインテンドは半角空白2文字設定で統一しています。
保存先はホスト Wimdows OS の 共有フォルダ c:\vb_public_html にして
ブラウザでアクセスできるようにします。
なお、
c:\vb_public_html
はゲスト OS Ubuntu のなかの
/home/yamada/public_html
とリンクしていて共有フォルダの関係にあります。
詳細は ユ-ザ-ごとの公開ディレクトリを用意する を読んでみてください。

ここまでで、lxml スクレイピングファイル sc_rape_by-lxml.py を作成する事ができました。
引き続き、このファイルの動作確認をします。


  • lxml スクレイピングファイル動作確認 に進む
  • 正規表現スクレイピング抜粋デ-タファイル確認 に戻る
  • 抜粋したデ-タをファイル保存 に戻る
  • 正規表現スクレイピングファイル作成 に戻る
  • Web ペ-ジから必要デ-タを抜粋 に戻る
  • Python スクレイピング概要 に戻る
  • 70VPS に戻る