Slide 1

Slide 1 text

Python で作るWeb クロー ラ入門 真嘉比 愛(Ai Makabi) 2016-09-21 @PyConJP 2016 Room 203 #pyconjp_203

Slide 2

Slide 2 text

真嘉比愛(Ai Makabi) DATUM STUDIO 株式会社 PyLadies Tokyo 各種アカウント Slack: @amacbee Twitter: @a_macbee Facebook: ai.makabi Python ライブラリ厳選レシピ( 共著)

Slide 3

Slide 3 text

Web クロー ラとは? ~ 利用事例や注意点を添えて ~

Slide 4

Slide 4 text

Web クロー ラ Wikipedia より抜粋 混同されがちな言葉 クロー リング: Web ペー ジのリンクを辿りながら保存する作業 スクレイピング: 保存したペー ジから特定の情報を抽出する作業 クロー ラ(Crawler) とは、 ウェブ上の文書や画 像などを周期的に取得し、 自動的にデー タベー ス 化するプログラムである。 “ “

Slide 5

Slide 5 text

クロー ラの利用事例 クロー ラで情報を収集して分析… という流れは多い 類似映画検索システム EC サイトのトレンド分析システム 株価トレンド分析システム Twitter センチメント抽出システム etc.

Slide 6

Slide 6 text

クロー ラの利用事例 クロー ラで情報を収集して分析… という流れは多い 類似映画検索システム EC サイトのトレンド分析システム 株価トレンド分析システム Twitter センチメント抽出システム etc.

Slide 7

Slide 7 text

事例1: 類似映画検索 数十万件/3 ヶ月.Azure 上で動作

Slide 8

Slide 8 text

事例2: EC サイトのトレンド分析 約100 万件/ 日(10 数台で7~8 時間).GCP 上で動作

Slide 9

Slide 9 text

クロー ラを利用してデー タを 収集することで デー タ分析の幅が圧倒的に広がる

Slide 10

Slide 10 text

本セッションの内容 Python を利用したクロー ラ作成・ 運用方法を一通り 知ることを目標とする 1. Web クロー ラを利用する上での注意点 2. Python 製クロー ラフレー ムワー ク「Scrapy」 Scrapy を利用してPyJobBoard クロー ラを作成 クロー ラ作成のTips 作成したクロー ラの管理 3. その他クロー ラ構築に有用なPython ライブラリ

Slide 11

Slide 11 text

時間の都合上省略 BeautifulSoup4 を中心とした各種スクレイピング ライブラリについて JavaScript を解釈するクロー ラの話(scrapy- splash, Selenium) 上記の内容を聞きにきて頂いた方がいましたら申し訳 ありませんm(_ _;)m またの機会に話したいです

Slide 12

Slide 12 text

クロー ラを作成する上での注意点

Slide 13

Slide 13 text

岡崎市立中央図書館事件 事件概要: 図書館の蔵書検索システムを日常的にクロー ルしてい た男性が, 高頻度のリクエストを故意に送りつけシス テムに接続障害を与えたとして偽計業務妨害容疑で逮 捕された( 別名:LibraHack 事件) --> 収集したデー タの使用目的やスクレイピング方法 によっては, 法に触れることもある ※ 事件自体は違法性はなかったと考えられている

Slide 14

Slide 14 text

クロー リングの際に遵守したいこと デー タの収集/ 公開は著作権法に配慮して行う robots.txt に記載されたアクセス制限を守る API が容易されている場合はそちらを利用する サー バへアクセスする間隔は最低でも1 秒以上あけ るようにする 会員のみが閲覧できるペー ジは利用規約を守る 参考:Web スクレイピングの注意事項一覧

Slide 15

Slide 15 text

Python でお手軽に クロー ラを書きたい!

Slide 16

Slide 16 text

クロー ラフレー ムワー ク

Slide 17

Slide 17 text

Scrapy - latest: 1.1.2 Python 製のクロー ラフレー ムワー ク クロー ラ界におけるDjango のような存在 クロー ラ作成時に考慮しなければならない機能を オプションを指定するだけで簡単に実現可能 e.g. サイトクロー リング間隔,robots.txt の解釈 スケジュー リング, ジョブ管理,etc. 機能を内包 2016 年5 月にリリー スされたScrapy 1.1 より Python 3 に対応

Slide 18

Slide 18 text

Scrapy Architecture 各機能はコンポー ネントに分かれている

Slide 19

Slide 19 text

Scrapy 利用環境の構築 pip を使って簡単に導入できます $ pip install scrapy ※Windows 環境の場合, 別途設定が必要 ※Ubuntu 環境ではapt-get も利用可能 $ sudo apt-get install python-scrapy

Slide 20

Slide 20 text

Scrapy を利用して PyJobBoard クロー ラを作成 (Hello Scrapy!)

Slide 21

Slide 21 text

www.python.org/jobs 複数の企業のジョブオファー が列挙されている 募集内容・ 勤務地・ 企業名の情報が記載されている 下部に次のペー ジへ行くためのリンクがある

Slide 22

Slide 22 text

Scrapy を用いたクロー リングの流れ www.python.org のサイトにあるJob Board をクロー ルするクロー ラを作成する 以下の手順を踏みます 1. プロジェクトを作成 2. クロー ル対象を定義 3. クロー ラを作成 4. クロー リング& 結果の保存

Slide 23

Slide 23 text

1. プロジェクトを作成 $ cd 任意のフォルダ $ scrapy startproject プロジェクト名 e.g. pyjob プロジェクト ├ ─ ─ pyjob │ ├ ─ ─ __init__.py │ ├ ─ ─ __pycache__ │ ├ ─ ─ items.py # クロー ル対象について記載 │ ├ ─ ─ pipelines.py │ ├ ─ ─ settings.py # クロー ルオプション │ └ ─ ─ spiders # クロー ラ本体(spider) を格納 │ ├ ─ ─ __init__.py │ └ ─ ─ __pycache__ └ ─ ─ scrapy.cfg # デプロイ設定

Slide 24

Slide 24 text

2. クロー ル対象を定義 scrapy.Field() を利用して, 取得したい情報を item.py に追記( 今回は募集タイトル・ 社名・ 勤務場 所) import scrapy class PyjobItem(scrapy.Item): title = scrapy.Field() # タイトル company = scrapy.Field() # 社名 location = scrapy.Field() # 勤務場所

Slide 25

Slide 25 text

3. クロー ラを作成(1/7) scrapy genspider コマンドで雛形となるクロー ラ (spider) を自動的に作成 $ scrapy genspider クロー ラ名 クロー ル対象ドメイン 例えば, python.org ドメインをクロー ルするクロー ラ の雛形を作成するには以下の通り実行 $ cd pyjob $ scrapy genspider pyjob_spider python.org ※ 作成されたクロー ラはpyjob/spiders 以下にある

Slide 26

Slide 26 text

3. クロー ラを作成(2/7) 作成したクロー ラの雛形の中身 自動作成された変数 name: クロー ラ名 allowed_domain: クロー ル対象ドメイン start_urls: クロー ル開始ペー ジのURL リスト 自動作成されたメソッド parse: クロー ルしたペー ジのパー ス ※ 後述

Slide 27

Slide 27 text

3. クロー ラを作成(3/7) e.g. python.org ドメイン中の python.org/jobs ペー ジ を起点にクロー リング from ..items import PyjobItem import scrapy class PyjobSpiderSpider(scrapy.Spider): name = "pyjob_spider" allowed_domains = ["python.org"] start_urls = ( 'https://www.python.org/jobs/', ) def parse(self, response): # 後述 ※ 複数のドメイン・URL を指定可能

Slide 28

Slide 28 text

3. クロー ラを作成(4/7) parse メソッドでは主に2 つの処理を行う 1. ペー ジからクロー ル対象の要素を抽出して返す Item クラスに必要な情報を格納 ※Item クラスの定義はitem.py で定義 2. 次のクロー ル対象ペー ジのURL を返す scrapy.Request(url) で返されたURL は新たなクロ ー リング対象となる(callback 引数にparse メソ ッドを指定すると, 再帰的にクロー ルを実行)

Slide 29

Slide 29 text

3. クロー ラを作成(5/7) def parse(self, response): # ペー ジ中のジョブオファー 情報を全て取得 for res in response.xpath("//h2[@class='list..."): job = PyjobItem() job['title'] = res.xpath(".//span[@cla...")... job['company'] = res.xpath(".//span[@cla...")... job['location'] = res.xpath(".//a[start...")... yield job # 「Next」 のリンクを取得してクロー ルする next_page = response.xpath("//li[@cla...").extract() if next_page: url = response.urljoin(next_page[0]) yield scrapy.Request(url, callback=self.parse) タグ要素の取得にはXPath やCSS のセレクタを利用

Slide 30

Slide 30 text

3. クロー ラを作成(6/7) settings.py でクロー リングのオプションを設定 絶対に設定して欲しい項目は以下 パラメー タ 意味 DOWNLOAD_DELAY クロー ル間隔( 秒) robots.txt に従うか否かを設定する ROBOTSTXT_OBEY は デフォルトで True (Scrapy 1.1+)

Slide 31

Slide 31 text

3. クロー ラを作成(7/7) e.g. pyjob のクロー リングオプション設定 BOT_NAME = 'pyjob' SPIDER_MODULES = ['pyjob.spiders'] NEWSPIDER_MODULE = 'pyjob.spiders' ROBOTSTXT_OBEY = True # robots.txt に従う DOWNLOAD_DELAY = 3 # 同一サイトへのアクセス間隔は3 秒

Slide 32

Slide 32 text

4. クロー リング& 結果の保存 $ scrapy crawl 作成したクロー ラ名 -o 出力先ファイル名 e.g. pyjob クロー ラを実行して, 結果をCSV 形式で保 存( クロー リングの実行ログも残す) $ scrapy crawl pyjob_spider -o result.json \ --logfile pyjob.log ※ 拡張子からファイルタイプを自動判定 ※DB 等へデー タを保存する処理は, pipeline.py を編 集することで追加できるが, ここでは省略

Slide 33

Slide 33 text

クロー リング結果を確認 result.json [ { "title": "Lead Python API and Automation Developers", "location": "Remote, USA", "company": "FICO" }, { "title": "Python Developer", "location": "London, UK", "company": "BMLL Technologies" }, ...

Slide 34

Slide 34 text

クロー リングログを確認 pyjob_spider.log 2016-09-21 01:20:30 [scrapy] INFO: Scrapy 1.1.2 started (bot: pyjob) 2016-09-21 01:20:30 [scrapy] INFO: Overridden settings: {'NEWSPIDER_MODULE': 'pyjob.spiders', 'LOG_FILE': 'pyjob_spider.log', 'BOT_NAME': 'pyjob', 'SPIDER_MODULES': ['pyjob.spiders'], 'FEED_URI': 'result.json', 'ROBOTSTXT_OBEY': True, 'DOWNLOAD_DELAY': 3, 'FEED_FORMAT': 'json'} 2016-09-21 01:20:30 [scrapy] INFO: Enabled extensions: ['scrapy.extensions.corestats.CoreStats', ...

Slide 35

Slide 35 text

クロー ラ作成のTips(1/3) Google Chrome の「 デベロッパー ツー ル」 を使う と3 ステップでスクレイピング箇所を特定出来る

Slide 36

Slide 36 text

クロー ラ作成のTips(2/3) scrapy shell を利用してスクレイピング結果をイン タラクティブに確認 $ scrapy shell 'https://www.python.org/jobs/' ... >>> response.css('title') [] >>> response.xpath('//title') [] ※ requests + BeautifulSoup4 でも代替出来る

Slide 37

Slide 37 text

クロー ラ作成のTips(3/3) クロー リング過程とスクレイピング過程を分ける サイト構造の変更によるスクレイピングの失敗 は珍しくない => 失敗してもクロー リングを再実行しない => クロー リング/ スクレイピング共に失敗して いないか監視する 対象サイトにJavaScript が含まれているか確認する JavaScript が含まれるか含まれないかで難易度が 大きく変わるため,JavaScript が含まれる場合は 別サイトの利用も検討する

Slide 38

Slide 38 text

[ まとめ] クロー ラ作成 with Scrapy 以下の手順を踏むことで, 特定サイトから欲しいデー タをクロー ル出来た 1. プロジェクトを作成 2. クロー ル対象を定義 3. クロー ラを作成 4. クロー リング& 結果の保存

Slide 39

Slide 39 text

作成したクロー ラを 管理するにはどうするのか?

Slide 40

Slide 40 text

クロー ラ管理 Scrapy 専用の管理ツー ルを2 つ紹介 Scrapy Cloud scrapyd

Slide 41

Slide 41 text

Scrapy Cloud クロー ラ管理用クラウドサー ビス「scrapinghub」 上で動くScrapy 環境 https://scrapinghub.com/scrapy-cloud/ Scrapy Clound の便利なポイント ツー ルの導入が簡単( pip install shub ) API キー を使って簡単deploy( shhub login --> shub deploy ) 簡易かつリッチなUI スケジュー リングも容易( Periodic Jobs )

Slide 42

Slide 42 text

Scrapy Cloud の課金体系 クロー ル範囲が1 サイト以下の場合は 無料 クレジットカー ドの登録も必要なし デー タ保存期間は1 週間 新しくクロー ル先を追加するたびに +9$ / month https://scrapinghub.com/pricing/

Slide 43

Slide 43 text

scrapyd Scrapy のデー モン 作成したクロー ラのジョブ管理が行える インストー ルが容易 ( pip install scrapyd scrapyd-client ) シンプルなAPI を利用した操作 ※ Python 3 に対応していない

Slide 44

Slide 44 text

クロー ラをscrapyd にdeploy 1. scrapy.cfg の [deploy] にあるurl をコメントアウト [deploy] url = http://localhost:6800/ project = pyjob 2. scrapyd を起動 $ scrapyd 3. 作成したクロー ラをscrapyd にdeploy $ scrapyd-deploy -p pyjob

Slide 45

Slide 45 text

API を利用したジョブの登録 schedule.json: ジョブを登録 $ curl http://localhost:6800/schedule.json \ ß-d project=pyjob -d spider=pyjob_spider cancel.json: ジョブの中止 $ curl http://localhost:6800/cancel.json \ -d project=pyjob -d job= ジョブID その他のAPI: https://scrapyd.readthedocs.io/en/stable/api.html

Slide 46

Slide 46 text

クロー ラ作成に最適な Python ライブラリの紹介

Slide 47

Slide 47 text

クロー ラ向けライブラリ(1/2) 1. requests 人間が利用することを意識して書かれた非常にシ ンプルなHTTP ライブラリ ( その限りではないが) 使い捨てのコー ドを書く のに最適 >>> import requests >>> res = requests.get('http://www.python.org/jobs/') >>> res.status_code 200 >>> with open('pyjob.html') as fout: ... fout.write(res.content)

Slide 48

Slide 48 text

クロー ラ向けライブラリ(2/2) 2. aiohttp Python 3.4 から追加されたasyncio を利用した非同期 HTTP Server/Client 1 プロセス内で複数のリクエス トを同時に実行(=IO 多重化) => 待ち時間を有効に活用して 高速に動作 公式サイト: http://aiohttp.readthedocs.io

Slide 49

Slide 49 text

e.g. aiohttp を利用したシンプルなクロー ラ from aiohttp import request, wait import asyncio @asyncio.coroutine def get(*args, **kwargs): res = yield from request('GET', *args, **kwargs) return (yield from res.read_and_close()) @asyncio.coroutine def print(): page = yeild from get(url) print(page) urls = ['****', '****', '****'] f = wait([print(url) for url in urls]) loop = asyncio.get_event_loop() loop.run_untile_complete(f)

Slide 50

Slide 50 text

本日のまとめ

Slide 51

Slide 51 text

話したこと Web クロー ラについて説明 クロー ラの利用事例を紹介 クロー リング時の注意点について説明 Scrapy を利用したクロー ラ構築方法を一通り説明 クロー ラ構築方法について最低限の流れを説明 クロー ラ構築時のTips について共有 クロー ラの管理に便利なツー ルを紹介 ありがとうございました!