【Python入門】Webスクレイピングとは?サンプルコード付きでご紹介



【Python入門】Webスクレイピングとは?サンプルコード付きでご紹介

マーケティングにデータ解析、情報追求にあると便利な「Webスクレイピング」という技術。
すぐに必要なくても知っておくだけで随分可能性が広がると思います。
今回はそんなWebスクレイピングを 5通りのやり方でご紹介。
それぞれに特徴がありますので、Webやデータが好きな方、是非一読してみて下さい。

目次
  1. 【Python入門】Webスクレイピングとは?サンプルコード付きでご紹介
  2. Beautiful Soup を使ってスクレイピング
  3. Selenium を使ってスクレイピング
  4. Pandas を使ってスクレイピング
  5. Scrapyを使ってスクレイピング
  6. 正規表現を使ってスクレイピング
  7. Beautiful Soup と Pandas の合わせ技でスクレイピング
  8. 注意点
  9. まとめ

【Python入門】Webスクレイピングとは?サンプルコード付きでご紹介

Beautiful Soup を使ってスクレイピング

image

PythonのWebスクレイピング定番ライブラリ『Beautiful Soup』。 HTMLコードを切り抜いたり、欲しいデータを抽出したりと、多くの場面でデータマイニングの欲求を満たしてくれます。

【インストール】

pip install beautifulsoup4

【インストールの確認】

pip show beautifulsoup4

image

【サンプルコード】

試しに CrowdWorks の自分の実績数を抽出してみます。

import requests, bs4
res = requests.get('https://crowdworks.jp/public/employees/14218')
res.raise_for_status()
soup = bs4.BeautifulSoup(res.text, "html.parser")
elems = soup.select('span.score.contracts')
print(elems)

<< 実行結果 >>

image

実績結果を示す 10 に関連する HTML コードまでも表示されています。 数字だけ表示したい場合は、 getText() を使うといいですね。

import requests, bs4
res = requests.get('https://crowdworks.jp/public/employees/14218')
res.raise_for_status()
soup = bs4.BeautifulSoup(res.text, "html.parser")
elems = soup.select('span.score.contracts')

for elem in elems:
    out = elem.getText()
    print(out)

<< 実行結果 >>

image

この技術を応用すれば、プロフィール・ページなどで使えそうですね。

ただし、Webページによってはスクレイピング防止なのかどうか理由は分かりませんが、取得した要素(データ)を特定できない、特定しにくいサイトもあります。それからスクレイピング防止のコードを埋め込んでいるサイトもあります。 そうした WebサイトではBeautiful Soupも無力になってしまいます。 尚、この問題は「正規表現」を使うとクリアできる場合がありますね。

Selenium を使ってスクレイピング

image

PythonでWebスクレイピングができるツールは、Beautiful Soup4 以外に Selenium というモジュールもあります。 Seleniumは、Beautiful Soup4 に比べて多機能でいくつかの自動化にも役立ちますが、その反面ブラウザを起動させますので”遅い”というデメリットも。

Selenium 未体験の方も多いと思いますので、「Pythonでこんなこともできるんだな」という参考として是非サンプルプログラムを実行してみて下さい。

【インストール】

pip install selenium

【確認】

pip show selenium

【サンプル】

フリーランス・サイトに自動ログイン、ただし下記コードの ログイン名、パスワードはご自身のものに変更して下さい。下記コードのパスワードは変更されています。

from selenium import webdriver
browser = webdriver.Firefox()

browser.get('https://www.lancers.jp/user/login')
email_elem = browser.find_element_by_id('UserEmail')
email_elem.send_keys('oshimamasara@gmail.com')
password_elem = browser.find_element_by_id('UserPassword')
password_elem.send_keys('oshima12345')
password_elem.submit()

<< 実行結果 >>

実際に Selenium のコードを走らせてみると分かるのですが、ちょっと不気味です。 ブラウザには、URL表記の左にボットマークが現れて、自分は何もクリックしないのに画面が切り替わります。 これを応用すると、2,3ある仕事用のページを一括表示できたり、複数のオークションサイトを一括で開いて手続きを確認できますね。 これって、結構時間の節約になると思います。 もちろんコードを変えれば、Chrome や Safari などでも動かせますので、Python、使いこなしたいですね。

-- 実行時に体験したエラー --

実行環境によりエラーもいろいろと思いますが、私の場合は以下のエラーに遭遇。

使用OS:Ubuntu 16.04

>> Selenium の install 時 <<

pandas 0.23.1 requires python-dateutil>=2.5.0, which is not installed.
matplotlib 2.2.2 requires python-dateutil>=2.1, which is not installed.

selenium インストール時、Pandasから python-dateutil version 2.5 以上が要求される。 https://github.com/dateutil/dateutil/releases より 2.7 をインストール。selenium インストールできた。

>> ファイル実行時 <<

FileNotFoundError: [Errno 2] No such file or directory: 'geckodriver': 'geckodriver'

GitHubより使用ブラウザにあったソフトをインストール。 今回は、FireFoxのため「Geckodriver」をインストール。

Pandas を使ってスクレイピング

image

データ解析用ライブラリのPandasを使ってWebスクレイピングすることも可能。 特に表データの抽出に優れています。

尚、こちらのライブラリは他の lxml や Beautiful Soup とも干渉することから、テキストエディタやIDEでは動かない場合も。 PythonシェルもしくはJupyter Notebook の使用をオススメします。

【インストール】

pip install pandas

【確認】

pip show pandas

【サンプルコード】
Jupyter Notebook使用

import pandas as pd
url = 'https://info.finance.yahoo.co.jp/ranking/?kd=3&mk=3&tm=d&vl=a'
dfs = pd.read_html(url)
print(dfs[0])

欲しいデータだけに絞る場合は、

dfs[0].columns = ['順位', 'コード', '市場', '名称', '取引値', '前日比', '出来高', '掲示板','Unnamed: 8','Unnamed: 9']
print(dfs[0][['名称', '前日比', '出来高']])

<< 実行結果 >>

image

今までのスクレイピングに比べてコードが短いです。 pd.read_html でHTML内の <table> データを拾ってきてくれるのですから、非常に助かりますね。

尚、こちらの Pandas は、HTML以外にCSVやExcelなどのファイルもスクレイピング可能です。

-- 実行時に体験したエラー --

AttributeError: module 'pandas' has no attribute 'read_html'

複数の原因因子が存在。 詳しい情報は、https://pandas.pydata.org/pandas-docs/stable/io.html#io-html-gotchas に記載されています。 エラー回避策としては、実行環境をPythonシェルスクリプトやJupyter Notebookに変えてみる。 私はこれで解決。

また Jupyter Notebook も利用するディレクトリによって動く場合と動かない場合がありました。 エラーが出る場合は、一つ上のディレクトリで実行してみるとうまく行く場合があります。

Scrapyを使ってスクレイピング

image

こちらは Beautiful Soupe や Selenium、Pandas と違ってフレームワーク構成、つまり今までのライブラリよりパワフルです。 スクレイピングに加えて「クローリング」できる特徴がありますね。

ただし、プログラムの実行は Python ●●.py ではなく

scrapy runspider scraper.py

と scrapy を呼ぶ出す形態。そのため、ターミナルもしくはコマンドプロンプトで実行する必要がありますね。

【インストール】

pip install scrapy

【確認】

pip show scrapy

【サンプルコード】

少し難易度が高いため、DigitalOceanさんのチュートリアルを参考にさせて頂きました。 レゴのチュートリアルサイトからタイトル、ピース数、フィギア数、画像を抽出してみましょう。 全部で30ページ以上ある情報も、Scrapyのクローリングテクニックを使うと、1分もかかりませんね。

import scrapy

class BrickSetSpider(scrapy.Spider):
    name = 'brick_spider'
    start_urls = ['http://brickset.com/sets/year-2017']

    def parse(self, response):
        SET_SELECTOR = '.set'
        for brickset in response.css(SET_SELECTOR):

            NAME_SELECTOR = 'h1 a ::text'
            PIECES_SELECTOR = './/dl[dt/text() = "Pieces"]/dd/a/text()'
            MINIFIGS_SELECTOR = './/dl[dt/text() = "Minifigs"]/dd[2]/a/text()'
            IMAGE_SELECTOR = 'img ::attr(src)'
            yield {
                'name': brickset.css(NAME_SELECTOR).extract_first(),
                'pieces': brickset.xpath(PIECES_SELECTOR).extract_first(),
                'minifigs': brickset.xpath(MINIFIGS_SELECTOR).extract_first(),
                'image': brickset.css(IMAGE_SELECTOR).extract_first(),
            }

        NEXT_PAGE_SELECTOR = '.next a ::attr(href)'
        next_page = response.css(NEXT_PAGE_SELECTOR).extract_first()
        if next_page:
            yield scrapy.Request(
                response.urljoin(next_page),
                callback=self.parse
            )

<< 実行結果 >>

実行用入力コマンド
scrapy runspider scraper.py

image

34ページ分すべての商品タイトル等決められた情報を抜き出しています。すごい。用途によっては、CSVなどに出力するとマーケティングツールとして使えますね。

正規表現を使ってスクレイピング

コード内で扱う文字の取り扱いについて定めた「正規表現」の機能の一つに「文字や数字の検出」があります。 CSSでスクレイピング対象物を特定できない場合などに役立つ手法ですね、

【インストール】

Pythonに標準装備

【サンプル】

トリップアドバイザー内の「京都」のトップページ内口コミ件数を抽出してみます。

import re
import urllib.request
from re import findall
from pprint import pprint

url = "https://www.tripadvisor.jp/Hotels-g298564-Kyoto_Kyoto_Prefecture_Kinki-Hotels.html"
response = urllib.request.urlopen(url)
html1 = response.read()
htmlStr1 = html1.decode()
r1 = re.findall(r'\d,\d+件の口コミ', htmlStr1)
pprint(r1)

<< 実行結果 >>

image

ターミナルやエディタから実行すると多数エラーが発生しましたが、Jupyter Notebook ではスムーズにクチコミ件数を抽出できています。マーケティングなどに活かせそうですね。

Beautiful Soup と Pandas の合わせ技でスクレイピング

これまでは基本的に一つのライブラリに頼って、スクレイピングしてきましたが、こちらでは Beautiful Soupと Pandas の合わせ技をご紹介。 NYTimesがデータ収集している「トランプさん、それウソじゃね?」というページのデータ整形に役立ちます。

参考:Data School

【サンプルコード】

import requests  
r = requests.get('https://www.nytimes.com/interactive/2017/06/23/opinion/trumps-lies.html')

from bs4 import BeautifulSoup  
soup = BeautifulSoup(r.text, 'html.parser')  
results = soup.find_all('span', attrs={'class':'short-desc'})

records = []  
for result in results:  
    date = result.find('strong').text[0:-1] + ', 2017'
    lie = result.contents[1][1:-2]
    explanation = result.find('a').text[1:-1]
    url = result.find('a')['href']
    records.append((date, lie, explanation, url))

import pandas as pd  
df = pd.DataFrame(records, columns=['date', 'lie', 'explanation', 'url'])  
df['date'] = pd.to_datetime(df['date'])  
df.to_csv('trump_lies.csv', index=False, encoding='utf-8')  

<< 実行結果 >>

抽出データを何段階かに分けて整理して、結果的に CSV にキレイに出力しています。 Beautiful Soup と Pandas それぞれの機能をうまく使えている事例と思いますね。

注意点

image

著作権

Webスクレイピングは、他サイトのデータを抽出する、抜き取る技術です。 場合によっては「著作権侵害」で訴えられる可能性もあります。 相手先のWebサイトが明らかにスクレイピングをブロックしているのに、それをかいくぐってデータを抜き取ったりしていると迷惑をかけるかもしれません。一つの判断材料としては「営利目的」があります。 codementor の情報を参考にしてみましょう。


Webスクレイピングはあるコンテキストでは合法であり、別のコンテキストでは違法です。
例えば、抽出されたデータが個人用の電話帳と電話帳で構成されている場合は合法です。
ただし、抽出されたデータが営利目的で使用されている場合、所有者の同意なしには、これは違法となります。
したがって、ウェブサイトからデータを抽出する際には注意が必要であり、常に法律に留意する必要があります。

https://www.codementor.io/python/tutorial/python-web-scraping-beautiful-soup


スクレイピングできない

Webサイトによっては、スクレイピングを拒否するように設定しているところもあります。 正規表現を使えばクリアできる場合もあるようですが、事前に著作権の確認が必要かもしれませんね。

API

今からスクレイピングで手に入れようとしているデータ、APIで公開されていたりしませんか? スクレイピングより、APIの方が早くて安全です。

まとめ

PythonでWebスクレイピングというと Beautiful Soupと正規表現ぐらいしか知りませんでしたが、本稿作成にあたって「Selenium」や「Pandas」などいろいろなやり方があることを発見。 これを日常生活で例えると「万能包丁以外に出刃包丁や果物ナイフが手に入ったようなもの」とイメージできるでしょう。 つまりできることが増え、そして加工に合わせた道具を使えるのでスムーズに結果を手に入れられます。

このデータ欲しいな、と思った時にすぐデータ収集できるかどうかは、今後のビジネスにおいて大きな影響をあたえるでしょう。 「Python、ちょっと始めてみようかな」と少しでも思われた方、CodeCampのオンライン&マンツーマンレッスンはいかがでしょうか? 忙しくても、時間がなくても、Pythonスキル習得への道のりに役立つと思いますよ。

オシママサラ
この記事を書いた人
オシママサラ
\ 無料体験開催中!/自分のペースで確実に習得!
オンライン・プログラミングレッスンNo.1のCodeCamp