【Python】Webスクレイピング
webスクレイピングとはwebページから情報を抽出することをいいます。
データ解析を主な目的とするデータサイエンスの分野では必須の技術です。
ただそうでなくともスクレイピングはやっていて楽しく、
効率的な抽出方法を編み出そうとすればプログラミングのいい勉強になると思います。
とはいえここで巨大で複雑なスクレイパーを作るのは正直つらいので、
今回は極めて簡単なwebスクレイパーを作成します。
webページの取得
まずはwebページを取得します。
Pythonにはurllibというライブラリーが備わっています。
このライブラリーは大抵の場合httpリクエストをする際に役立ちます。
Python2とPython3でこのライブラリーの関数の呼び出し方が異なります。
今回はPython3を使うことを前提に話を進めていきます。
単純にwebページを取得するだけのサンプルです。
import urllib.request
url = "http://books.toscrape.com/"
response = urllib.request.urlopen(url)
print(response.read().decode())
urlを指定してurllib.request.urlopenを呼び出します。
するとオブジェクトが返ってきます。
返ってきたオブジェクトのread関数を呼び出すことでwebページ(html)を取得することができます。
実行すると以下のようなhtmlを取得することができます。
<!DOCTYPE html>
<!--[if lt IE 7]> <html lang="en-us" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html lang="en-us" class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html lang="en-us" class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html lang="en-us" class="no-js"> <!--<![endif]-->
<head>
<title>
All products | Books to Scrape - Sandbox
</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="created" content="24th Jun 2016 09:29" />
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />
<meta name="robots" content="NOARCHIVE,NOCACHE" />
<!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link rel="shortcut icon" href="static/oscar/favicon.ico" />
<link rel="stylesheet" type="text/css" href="static/oscar/css/styles.css" />
<link rel="stylesheet" href="static/oscar/js/bootstrap-datetimepicker/bootstrap-datetimepicker.css" />
<link rel="stylesheet" type="text/css" href="static/oscar/css/datetimepicker.css" />
</head>
<body id="default" class="default">
<header class="header container-fluid">
<div class="page_inner">
<div class="row">
<div class="col-sm-8 h1"><a href="index.html">Books to Scrape</a><small> We love being scraped!</small>
</div>
</div>
</div>
</header>
...
解析
webページを取得できたらそのページを解析します。
目的によって方法は変わりますが、ここではページに含まれるanchorタグを抽出してみましょう。
ここでは正規表現を簡単に扱えるreというライブラリーを使用します。
import urllib.request
import re
url = "http://books.toscrape.com/"
response = urllib.request.urlopen(url)
html = response.read().decode()
ancs = re.findall(r'<a .*?</a>',html,re.DOTALL)
for anc in ancs:
print(anc)
re.fundallにパターン文字列、ページ、フラグ(必須ではない)を指定します。
パターン文字列はページによって工夫して決める必要があります。
re.DOTALLフラグは「.」を改行を含んだすべての文字にマッチさせるということ意味します。
これがない場合、文字列は改行にはマッチしなくなります。
r”というのは改行文字を通常の文字列として扱うことを意味しています。
https://docs.python.org/ja/3/library/re.html
これを実行するとページに含まれるanchorタグを抽出することができます。
<a href="index.html">Books to Scrape</a>
<a href="index.html">Home</a>
<a href="catalogue/category/books_1/index.html">Books</a>
<a href="catalogue/category/books/travel_2/index.html">Travel</a>
<a href="catalogue/category/books/mystery_3/index.html">Mystery</a>
<a href="catalogue/category/books/historical-fiction_4/index.html">
...
正規表現を使って目的の文字列を抽出しましたが、
BeautifulSoupを使うと同じことを簡単に行なえます。
BeautifulSoupはhtmlの解析作業を簡単にしてくれるライブラリーです。
pip install beautifulsoup4
サンプルソースです。
import urllib.request
from bs4 import BeautifulSoup
url = "http://books.toscrape.com/"
response = urllib.request.urlopen(url)
html = response.read().decode()
soup = BeautifulSoup(html, 'html.parser')
print(soup.find_all('a'))
先ほど正規表現を使ってanchorタグを抽出しましたが、
BeautifulSoupを使うとこれを一行で行うことができます。
他にもtitleの内容を取得したりといろいろできます。
ドキュメントにまとめられています。
https://www.crummy.com/software/BeautifulSoup/bs4/doc/
スクレイピングの練習におすすめのサイト
Books To Scrape
書籍データが一覧となって表示されています。
それぞれカテゴリー分けされているなど、
条件に従って情報を抽出する際の材料も用意されています。
Quotes to Scrape
偉人たちの言葉がまとめられています。
この二つのサイトはScrapinghubによって作成されたようです。
Hacker News
ご存知の方も多いと思います。
コンピュータ・サイエンス系のニュースがまとめられているサイトです。
APIが用意されているのでそちらを使いましょう。
練習に役立つサイトは他にもあると思います。
とはいえやり過ぎるとサーバーに負荷がかかりサービスにも影響が出てきます。
以前図書館だかのシステムをスクレイピングしてクラッシュさせた人が逮捕された事例もありますので、
サイトがスクレイピングが許容していることを確認し、
短いスパンでリクエストを送り続けることを避けるなど配慮したほうがいいかと思います。