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