おい,のび太scrapingやろうぜ
my pageに戻る ※参考:Pythonによるスクレイピング&機械学習[開発テクニック],クジラ飛行机

本ページの目的

 どうもジャイアンです.本ページではのび太でもわかるようにwebスクレイピングについて書いていきます書かけたらいいな.

 本ページでは,webスクレイピングについて学び,自分がほしい情報を定期的に収集するクローラを構築したいと思います.

使用言語:python

対象OS:mac, linux ※クローリング以外はwindowsでもできます

基本情報

スクレイピングとは

 スクレイピング(scraping)とは,Webサイトから任意の情報を抽出する技術のことです. Webページの構造解析のほかに,場合によってはログインが必要なページにアクセスする技術も必要になります.

クローラとは

 プログラムがWebサイトを定期的に巡回して情報を収集する技術のことです. 天気や株,為替など短い周期で変化する場合には最新の情報が欲しいことが多いと思います. そのような情報を集めるときに用いられます. スクレイピングのプログラムを周期的に動作させるというふうに考えていただければ大丈夫です.
 本ページではmac/linuxにて使用できるcronを用いてクローリングする方法を紹介します. また,クローリングする際にはサーバに負担をかけないなどのマナーについても気をつけましょう.
因みに,こんな事件もあります... 岡崎市立中央図書館事件

pythonライブラリや使用例

urllib

pythonのネットワークライブラリ

import urllib.request

使用例①:直接ファイルを保存
urllib.request.urlretrieve('url', 'savefile_name')

使用例②:一度メモリに格納してから保存
mem = urllib.request.urlopen(k'url').read()
with open(savefile_name, mode='wb') as f:
	f.write(mem)

BeautifulSoup

解析ライブラリ(html, xmlなど)

from bs4 import BeautifulSoup

html = """
<html>
  <body>
    <ul>
      <li><a href='http://dorayaki.com'>ドラえもん</a></li>
      <li><a href='http://jaiko.com'>剛田商店</a></li>
    </ul>
    <ken>東京都</ken>
  </body>
</html>
"""
# HTMLを解析
soup = BeautifulSoup(html, 'html.parser')

# find_allメソッドで取り出す
links = soup.find_all('a') # <a>タグをすべて抽出

# 任意のデータ抽出
ken = soup.find('ken').string

for a in links:
	href = a.attrs['href']
	text = a.string
	print(text, '>', href)

print(ken)

出力

ドラえもん > http://dorayaki.com
剛田商店 > http://jaiko.com
東京都

CSSセレクタを使おう

soup.select_one : CSSセレクタで要素を1つ取り出す
soup.select : CSSセレクタで複数要素を取り出しリスト型で返す

sample code

from bs4 import BeautifulSoup

# 解析対象となるHTML
html = """
<html>
  <body>
    <div id="meigen">
      <h1>ジャイアンの名言</h1>
      <ul class="items">
        <li>お前のコードは俺のもの,俺のコードも俺のもの</li>
        <li>永久に借りておくだけだぞ</li>
        <li>野上さんには勝てないぜ</li>
      </ul>
    </div>
  </body>
</html>
"""

# HTMLを解析
soup = BeautifulSoup(html, 'html.parser')

# 必要な部分をCSSクエリで取り出す
# タイトル部分
h1 = soup.select_one("div#meigen > h1").string
print(h1)

# リスト部分
li_list = soup.select("div#meigen > ul.items > li")
count = 1
for li in li_list:
	print("その" + str(count), li.string)
	count += 1

出力

ジャイアンの名言
その1 お前のコードは俺のもの,俺のコードも俺のもの
その2 永久に借りておくだけだぞ
その3 野上さんには勝てないぜ

実際にyahoo!ファイナンスから為替情報取得してみる

追記:現在yahooファイナンスはサイト内のスクレイピングを禁止しているため,やってはいけないです.
公開も停止しました.

天気の情報を取得してみる

代わりに今日の東京の天気を取得してみましょう.対象サイトはtenki.jpです.

新宿区の一時間ごとの気象情報を取得するサンプルコードです.
https://tenki.jp/forecast/3/16/4410/13104/1hour.html


sample code

from bs4 import BeautifulSoup
import urllib.request as req

# 解析対象となるHTML
url = "https://tenki.jp/forecast/3/16/4410/13104/1hour.html"
res = req.urlopen(url)

# HTMLを解析
soup = BeautifulSoup(res, 'html.parser')

# 必要な部分をCSSクエリで取り出す

# リスト部分
weather_list = soup.select("tr.weather > td > p")
temp_list = soup.select("tr.temperature > td > span")
rainy_percent_list = soup.select("tr.prob-precip > td > span")
wind_speed_list = soup.select("tr.wind-speed > td > span")

count = 1
for weather, temp, rainy_percent, wind_speed in zip(weather_list, temp_list, rainy_percent_list, wind_speed_list):
print(str(count) + ":00", weather.string, temp.string+"℃ ", rainy_percent.string+"% ", wind_speed.string+"m/s")
count += 1
if count == 25: break

出力

1:00 曇り 7.0℃  ---%  4m/s
2:00 曇り 7.0℃  ---%  3m/s
3:00 曇り 6.5℃  ---%  2m/s
4:00 みぞれ 6.5℃  ---%  2m/s
5:00 みぞれ 6.5℃  ---%  2m/s
6:00 みぞれ 6.0℃  ---%  1m/s
7:00 みぞれ 6.0℃  ---%  1m/s
8:00 みぞれ 5.5℃  ---%  1m/s
9:00 みぞれ 5.0℃  ---%  1m/s
10:00 小雨 5.5℃  ---%  1m/s
11:00 小雨 5.5℃  ---%  3m/s
12:00 小雨 6.0℃  ---%  1m/s
13:00 小雨 6.0℃  ---%  3m/s
14:00 小雨 5.5℃  ---%  2m/s
15:00 曇り 5.5℃  ---%  2m/s
16:00 曇り 5.5℃  ---%  1m/s
17:00 曇り 5.4℃  ---%  1m/s
18:00 曇り 5.3℃  20%  1m/s
19:00 曇り 5.2℃  20%  1m/s
20:00 曇り 5.2℃  20%  1m/s
21:00 曇り 5.1℃  20%  1m/s
22:00 曇り 5.0℃  20%  2m/s
23:00 晴れ 4.9℃  10%  2m/s
24:00 晴れ 4.8℃  10%  2m/s

CSSセレクタの書き方(書式)については各自で調べてね

正規表現と組み合わせる

sample code

from bs4 import BeautifulSoup
import re

html = """
<ul>
  <li><a href="hoge.html">hoge</li>
  <li><a href="https://dorayaki.com">ドラえもん</li>
  <li><a href="https://jaiko.com">剛田商店</li>
</ul>
"""
soup = BeautifulSoup(html, "html.parser")

# 正規表現でhrefからhttpsのものを抽出
li = soup.find_all(href=re.compile(r"^https://"))
for i in li:
	print(i.attrs['href'])

出力

https://dorayaki.com
https://jaiko.com

再帰的処理

また今度

スクレイピング応用編

気が向いたら書きます

ログインページのスクレイピング

ブラウザを使ったスクレイピング

Web APIの利用

cronを用いたクローリング

気が向いたら書きます