新型Raspberry Pi 4 modelBが発表&発売されました! 第一報はこちら

ラズパイでWEBスクレイピングーjupyter notebook

webscraping Python
この記事は約9分で読めます。

省電力なラズパイは簡単なデータ収集とデータ分析させるのにも適しています。WEBサイトから情報を持ってくるクローリング&スクレイピングをjupyter notebookを使って試してみました。

既に先人がたくさんの情報をWEBにアップしてくれているので、特別な書籍などは無くてもそれなりにできます。もちろん基本は知っていた方が良いので、興味が沸いたら有名な書籍を購入した方が良いと思います。

スポンサーリンク

今回の環境

今回もRaspberry Pi ノーマル3Bを使います。プラス(+)が付かない旧型です。多少のWEBスクレイピングならスペック的にもそれなりですし、取得するデータもテキストベースですからスペースも必要ありません。更にLinux(Raspbian)環境なら必要なライブラリ、アプリケーションは手に入ります。

今回の環境
  • 2019-04-08-raspbian-stretch
  • pandas
  • selenium
  • jupyter notebook
  • chromium-chromedriver

Raspbian StretchはliteでなければPython3やpip3は入っています。一部アップグレードして今回のプロジェクトで必要な他のライブラリをインストールしていきます。

事前にノーマル3BにRaspbianのセットアップは済ませてください。

インストールと設定

apt-getでインストールするのはpandasです。

sudo apt-get install python3-pandas

pipからインストールするものは以下です。pipはアップグレードしておきます。

sudo pip3 install --upgrade pip
sudo pip3 install jupyter
sudo pip3 install selenium

スクレイピングするjupyter notebookはLinuxもChromeも対応しています。しかし、RaspbianではChromiumドライバであるchromium-chromedriverをダウンロードしてインストールします。

古い情報にバージョン65ではムリとありましたが、記事執筆時点では問題ありませんでした。

http://launchpadlibrarian.net/361669488/chromium-chromedriver_65.0.3325.181-0ubuntu0.14.04.1_armhf.deb

wgetでダウンロードします。

wget http://launchpadlibrarian.net/361669488/chromium-chromedriver_65.0.3325.181-0ubuntu0.14.04.1_armhf.deb

debパッケージの展開とインストール

sudo dpkg -i chromium-chromedriver_65.0.3325.181-0ubuntu0.14.04.1_armhf.deb

以下のcommandでchromedriverがきちんとインストールできたか確認する

ls -l /usr/lib/chromium-browser/chromedriver

スクレイピング用ディレクトリの新規作成

mkdir ~/notebooks

権限を与えます。こうしないと恐らくデータが書き込めない??

cd ~/notebooks
sudo chmod -R 777 ./

jupyter notebookの設定

jupyter notebook --generate-config

これで、home/pi/.jupyter/jupyter_notebook_config.pyに設定ファイルが出来上がります。

設定ファイルは3箇所を修正する

c.NotebookApp.ip = '0.0.0.0'
c.NotebookApp.notebook_dir = '/home/pi/notebooks'
c.NotebookApp.port = 8888

パスワードの設定

jupyter notebook password

このパスワードはChromiumブラウザからログインする際に使用します。

実行手順

ここからが本番です。

jupyter notebookを立ち上げます。

jupyter notebook

先程設定したパスワードを入れます。
以下のような画面から新しくnotebookを作ります。
New→Python3

実際の画面は以下です。

この枠内にあるボックスへコードを記述していきます。そしてRunボタンで実行させます。

終了するときは、左上のメニュー File → close and halt から行います。(ブラウザを閉じない)

WEBスクレイピングしたコード

たくさんのサイトで紹介されています。いつものごとく「オラに力を分けてくれ!」の先人達のコードを片っ端から読んで寄せ集め・・・いや、なんとか理解しつつまとめてみました。(無駄なコードは適時直してください)

今回、hatenaで任意の文字列(今回はRaspberry Pi )で検索し、その中で100以上ブックマークされている記事で絞り込んでいます。

検索された記事のタイトル名、ブックマーク数、投稿日付、リンクURLをcsvとして書き出しています。

-- coding:utf-8 --
from selenium import webdriver
import pandas as pd
from bs4 import BeautifulSoup
import time

#hatenaへアクセス
url = "http://b.hatena.ne.jp/search/text?safe=on&q=Raspberry+Pi+python&users=100"
URL_HEAD=url.split('/search')[0]
p_url = 'https://b.hatena.ne.jp'

browser = webdriver.Chrome(executable_path="/usr/lib/chromium-browser/chromedriver")
browser.get(url)
 
data = browser.page_source.encode('utf-8')
soup = BeautifulSoup(data,'lxml')
outputData = pd.DataFrame(index=[],columns=['title', 'bookmarks', 'created', 'link'])
page = 1

while True:
     if not soup.find(class_='centerarticle-pager-next') is None:
         #Pageのclass centerarticle-entry-data内
         posts = soup.find_all('ul', class_='centerarticle-entry-data')
         print('Starting to get posts… page: {}'.format(page))

         for post in posts:
           title = post.find(class_='centerarticle-users').find('a').get('title')
           print(title)
           bookmarks = post.find(class_='centerarticle-users').find('a').text
           print(bookmarks)
           created = post.find(class_='entry-contents-date').text
           print(created)
           link_s = post.find(class_='centerarticle-users').find('a').get('href')
           link = p_url + link_s
           print(link)
           series = pd.Series([title, bookmarks, created, link], index=outputData.columns)
           
           #データ蓄積
           outputData = outputData.append(series, ignore_index=True)
           print(outputData)
           print('title: {}'.format(title))

        clickNextPageBtn = URL_HEAD + soup.find(class_='centerarticle-pager-next').a ['href']
        browser.get(clickNextPageBtn)
        page += 1
        browser.implicitly_wait(5)
        data = browser.page_source.encode('utf-8')
        soup = BeautifulSoup(data, 'lxml')

        print("--- Moving to next page ---")
        print('page={}'.format(page))
        time.sleep(5)
     else:
        print("no pager exist anymore")
        break

#ファイル出力
outputData.to_csv('/home/pi/notebooks/hatena.csv')
print(outputData)
print("DONE")
#終了処理
browser.quit()

結果はこの通り。ソートはしていません。

CSVの結果画面

ハマったところ

詰まったところは沢山あって全ては表現しきれません。非エンジニアとして基本の基本はある程度理解したかなーと思っても、少しの応用で躓く・・・。

中でも一番ハマったのがこれ。

AttributeError: ‘NoneType’ object has no attribute ‘text’
AttributeError: ‘list’ object has no attribute ‘text’

これは本当に参りました。上のNoneTypeは絞り込めずに値を取れなかった場合が多いです。そもそもそんな値が取れないヘンテコな場所だったりした当てが外れたパターンもありました。

もう一つのlistのエラーは一意(ユニーク)にならず複数の値があったりした場合です。

やはり文法は勉強しないとダメですね・・・。書き方のミスも多かったです。それに似たようなメソッドも違いを覚えないとなりません。find_all、find、selectなど。

今回は時間をかけてハマった?!ので、だいぶ身につきました。HTMLの要素を理解するのは大前提なものの、HTML、CSS、Python、Beautiful Soupでかなり実用的なことができるなーという印象です。

※最後に、WEBスクレイピングは逮捕者も出ています(不起訴だった)。扱いによっては、サーバーに負荷を掛けすぎるという危険なこともあり責任重大です。cornなどで自動にする際には気をつけないとなりません。本格的に運用するなら、そういうセキュリティ面も考慮してください。

参考にした主なサイト:Beautiful Soup 4.2.0 Doc. 日本語訳 (2013-11-19最終更新) 

コメント