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 スクレイピングファイルを作成していきます。
- お決まりの作法  
Pyton がインスト-ルされている場所を示めします。
#!/usr/bin/python3
Pyton3 のインスト-ル場所がわからない場合は
$ which python3
で知ることができます。
ファイルで使用する文字コ-ドを設定します。
#coding: utf-8
HTTP ヘッダーを出力
print("Content-type: text/html; charset=UTF-8\n\n")
これで Python から出力された文字は Web で見ることができるようになります。 - ライブラリを取り込み
取り込む必要があるライブラリは1つです。
import lxml.html
 - HtmlElementTree オブジェクト作成
Python スクレイピング概要 のなかで作成した sc_re_hd_enc.py を実行したときできた
sc_dp.html ファイル
を読み込み、parse()関数で
HtmlElementTree オブジェクト tree
を作成します。
tree = lxml.html.parse('sc_dp.html') - HtmlElementHtml オブジェクト作成
getroot()メソッドで HtmlElement オブジェクト html を作成します。
html = tree.getroot() - href 属性を絶対 URL に変換
make_links_absolute()メソッドを使用します。
引数の URL を基準として、すべての a 要素の href 属性を絶対 URL に変換してくれます。html.make_links_absolute('https://gihyo.jp/')
 - セレクター作成
あらかじめ、抜粋したい部分のセレクター listb を作成します。
id="listBook" である要素の子である li 要素の子である itemprop="url"
という属性を持つ a 要素を指定したいので
listb = '#listBook > li > a[itemprop="url"]'
とします。
要するに
<div id="bookList">
以下に<li> の項が沢山出現します。
その中の<a itemprop="url" と書かれた項を </li> まで抜粋しなさい
ということになります。 - 指定セレクターオブジェクト作成
指定セレクター listb からなるオブジェクト htmlist を作成します。
htmlist = html.cssselect(listb) - 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() メソッドを使います。 - 取得した書籍の URL とタイトルを保存
あらかじめ
books = []
として設定しておいた配列 books に順次、
取得した書籍の URL とタイトル title
を保存します。
books.append({'url': url, 'title': title})
 - 保存したデ-タ確認
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 を作成する事ができました。
   引き続き、このファイルの動作確認をします。