Python スクレイピング

Web ペ-ジから必要デ-タを抜粋

ここまでで、Requests で Web ペ-ジを取得する事ができました。
引き続き、Python 標準ライブラリの re モジュ-ルを利用して正規表現を用いて Web ペ-ジから必要なデ-タを抜粋していきます。
正規表現ってなかなか難しいですよね。
私も嫌いです。
でも正規表現スクレイプはオ-ルマイティなので CSS セレクタを利用したスクレイプより細かな設定が可能です。
理解しておいて損はないと思います。
Python スクレイピング概要 で取得した
Gihyo Digital Publishing 技術評論社の電子書籍サイト
のHTML ファイル sc_dp.html から正規表現を利用して書籍の URL と書籍のタイトルを抜き出します。

正規表現のパタ-ンをすっきり書く

正規表現にはバックラッシュ 「 \ 」 が頻出するので、通常の文字列を使うとエスケ-プが面倒です。
raw 文字列と呼ばれる
r'・・・・' または
r"・・・・"
という文字列リテラルを使うとバックラッシュがエスケ-プ文字として解釈されないので、 正規表現のパタ-ンをすっきり書くことができます。

sc_dp.html の構成を知る

Web ペ-ジから必要なデ-タを抜粋するにはその HTML ファイルの構成を知ることが大切です。
sc_dp.html を内容を見ると沢山の書籍の URL とタイトルが
<a itemprop="url" ・・・・
~~~~~
</a></li>
のなかにある事がわかります。
この記述は、書籍1冊分ですが、全体をみると 書籍の数分だけ存在しています。
そして、このなかに書籍の URL は
<a itemprop="url" href="・・・・・">
という形で存在します。
また書籍のタイトルは
<p itemprop="name" ・・・・・</p>
と書かれた部分に存在します。
下記に書籍1冊分の HTML の内容を示します。


  <li class="new" id="978-4-297-11679-8">
  <a itemprop="url"
   href="/dp/ebook/2020/978-4-297-11679-8">
  <img itemprop="image"
   src="//image.gihyo.co.jp/dummy.png"
   width="100" height="166"
   data-image="//image.gihyo.co.jp/2020/thumb/11679-8.jpg"
   alt="カバー画像"/>
  <p itemprop="name" class="title">
   要点確認これだけ! 応用情報技術者
  </p>
  <p itemprop="author" class="author">近藤孝之 著</p>
  <p itemprop="offers" itemscope="itemscope"
    itemtype="http://schema.org/Offer" class="price">
    <span itemprop="price">1,480円
    <meta itemprop="priceCurrency" content="JPY"/>
  </p>
  <ul class="format">
    <li class="pdf">PDF</li>
  </ul>
  <ul class="date">
  <li class="notice">
    <time datetime="2020-11-07"
     itemprop="datePublished" class="published">
     2020年11月7日
  </li>
  </ul>
  </a></li>

書籍の URL とタイトル抜粋

まず最初に、書籍の URL とタイトルを大きく抜粋します。
<a itemprop="url" ・・・・
~~~~~
</a></li>
を抜き取ればよいので
その正規表現は
r'<a itemprop="url".*?</ul>\s*</a></li>'
となるのですが、なんでこうなるの?
難しい質問ですね。
まずは、正規表現の基本を理解しましょう。
基本的な正規表現一覧 に行くと基本的な正規表現について詳しく書かれています。
まずはこれを読んでください。
基本的には以下の内容を理解します。
. :任意の1文字 にマッチ。
*:直前の文字が 0回以上 繰り返す場合にマッチ。
  最長一致。
  条件に合う最長の部分に一致。
?:直前の文字が 0個か1個 の場合にマッチ。
  最長一致。
  条件に合う最長の部分に一致。
これが理解できたら次はこれを2個組み合わせると
*?:直前の文字が 0回以上 繰り返す場合にマッチ。
   最短一致。
  条件に合う最短の部分に一致。
そしてこれらを3個組み合わせると
.*?:最左最短マッチ
となります。
さらには
\:直後の正規表現記号を エスケープ。
\s:垂直タブ以外のすべての空白文字 [\t\f\r\n]
\s*:空白文字(スペース、タブ、改行)に0回以上マッチ
となります。
ちなみに
r'<p>.*?</p>'
と記述すると、p タグで囲まれた部分の正規表現となります。
ここまでで、正規表現により必要部分を抜き取る準備ができました。

re.findall() 関数を使う

re モジュ-ルのなかの
re.findall() 関数
を使うと正規表現にマッチするすべての箇所を取得できます。
ref = r'<a itemprop="url".*?</ul>\s*</a></li>'
par0 = re.findall(ref, html, re.DOTALL)
ちなみに、html は sc_dp.html の中身です。
そして、re.DOTALL フラグ指定をすることで改行にもマッチさせます。
このフラグがあると、
'.' は、改行を含むあらゆる文字にマッチします。
このフラグがなければ、
'.' は、改行以外のあらゆる文字とマッチします。

re.search() 関数を使う

re モジュ-ルのなかの re.search() 関数を使うと正規表現にマッチする箇所を取得できます。
例えば、par が re.findall() 関数で見つけた内容の場合、
ref1 = r'<a itemprop="url" href="(.*?)">'
url = re.search(ref1, par).group(1)
とすると
group(1) と指定すると par においてマッチした( )内の .*? の内容が取得されます。
部分マッチです。
今回は URL がその内容になります。
ちなみにマッチした全部の内容を取得したいときは( ) をなくし
ref1 = r'<a itemprop="url" href=".*?">'
url = re.search(ref1, par).group(0)
とします。
なお、group ( )内の引数が1ならば結果は1つの文字列です。
複数の引数があれば、結果は引数ごとに1項目のタプルになります。
ここまでで、正規表現スクレイピングファイルを作成する準備が整いました。
引き続き、具体化してファイルを作成いきます。

ここまでで、Web ペ-ジから必要デ-タを抜粋して必要部分を取得する準備ができました。
引き続き、正規表現スクレイピングファイルを作成していきます。


  • 正規表現スクレイピングファイル作成 に進む
  • Python スクレイピング概要 に戻る
  • 70VPS に戻る