Pythonで作るWebクローラ入門

B3194c223c17ec4a804de281046f45b5?s=47 amacbee
September 21, 2016

 Pythonで作るWebクローラ入門

Pythonで作るWebクローラ入門の発表資料
https://pycon.jp/2016/ja/schedule/presentation/32/

B3194c223c17ec4a804de281046f45b5?s=128

amacbee

September 21, 2016
Tweet

Transcript

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

    Room 203 #pyconjp_203
  2. 真嘉比愛(Ai Makabi) DATUM STUDIO 株式会社 PyLadies Tokyo 各種アカウント Slack: @amacbee

    Twitter: @a_macbee Facebook: ai.makabi Python ライブラリ厳選レシピ( 共著)
  3. Web クロー ラとは? ~ 利用事例や注意点を添えて ~

  4. Web クロー ラ Wikipedia より抜粋 混同されがちな言葉 クロー リング: Web ペー

    ジのリンクを辿りながら保存する作業 スクレイピング: 保存したペー ジから特定の情報を抽出する作業 クロー ラ(Crawler) とは、 ウェブ上の文書や画 像などを周期的に取得し、 自動的にデー タベー ス 化するプログラムである。 “ “
  5. クロー ラの利用事例 クロー ラで情報を収集して分析… という流れは多い 類似映画検索システム EC サイトのトレンド分析システム 株価トレンド分析システム Twitter

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

    センチメント抽出システム etc.
  7. 事例1: 類似映画検索 数十万件/3 ヶ月.Azure 上で動作

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

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

  10. 本セッションの内容 Python を利用したクロー ラ作成・ 運用方法を一通り 知ることを目標とする 1. Web クロー ラを利用する上での注意点

    2. Python 製クロー ラフレー ムワー ク「Scrapy」 Scrapy を利用してPyJobBoard クロー ラを作成 クロー ラ作成のTips 作成したクロー ラの管理 3. その他クロー ラ構築に有用なPython ライブラリ
  11. 時間の都合上省略 BeautifulSoup4 を中心とした各種スクレイピング ライブラリについて JavaScript を解釈するクロー ラの話(scrapy- splash, Selenium) 上記の内容を聞きにきて頂いた方がいましたら申し訳

    ありませんm(_ _;)m またの機会に話したいです
  12. クロー ラを作成する上での注意点

  13. 岡崎市立中央図書館事件 事件概要: 図書館の蔵書検索システムを日常的にクロー ルしてい た男性が, 高頻度のリクエストを故意に送りつけシス テムに接続障害を与えたとして偽計業務妨害容疑で逮 捕された( 別名:LibraHack 事件)

    --> 収集したデー タの使用目的やスクレイピング方法 によっては, 法に触れることもある ※ 事件自体は違法性はなかったと考えられている
  14. クロー リングの際に遵守したいこと デー タの収集/ 公開は著作権法に配慮して行う robots.txt に記載されたアクセス制限を守る API が容易されている場合はそちらを利用する サー

    バへアクセスする間隔は最低でも1 秒以上あけ るようにする 会員のみが閲覧できるペー ジは利用規約を守る 参考:Web スクレイピングの注意事項一覧
  15. Python でお手軽に クロー ラを書きたい!

  16. クロー ラフレー ムワー ク

  17. Scrapy - latest: 1.1.2 Python 製のクロー ラフレー ムワー ク クロー

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

  19. Scrapy 利用環境の構築 pip を使って簡単に導入できます $ pip install scrapy ※Windows 環境の場合,

    別途設定が必要 ※Ubuntu 環境ではapt-get も利用可能 $ sudo apt-get install python-scrapy
  20. Scrapy を利用して PyJobBoard クロー ラを作成 (Hello Scrapy!)

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

  22. Scrapy を用いたクロー リングの流れ www.python.org のサイトにあるJob Board をクロー ルするクロー ラを作成する 以下の手順を踏みます

    1. プロジェクトを作成 2. クロー ル対象を定義 3. クロー ラを作成 4. クロー リング& 結果の保存
  23. 1. プロジェクトを作成 $ cd 任意のフォルダ $ scrapy startproject プロジェクト名 e.g.

    pyjob プロジェクト ├ ─ ─ pyjob │ ├ ─ ─ __init__.py │ ├ ─ ─ __pycache__ │ ├ ─ ─ items.py # クロー ル対象について記載 │ ├ ─ ─ pipelines.py │ ├ ─ ─ settings.py # クロー ルオプション │ └ ─ ─ spiders # クロー ラ本体(spider) を格納 │ ├ ─ ─ __init__.py │ └ ─ ─ __pycache__ └ ─ ─ scrapy.cfg # デプロイ設定
  24. 2. クロー ル対象を定義 scrapy.Field() を利用して, 取得したい情報を item.py に追記( 今回は募集タイトル・ 社名・

    勤務場 所) import scrapy class PyjobItem(scrapy.Item): title = scrapy.Field() # タイトル company = scrapy.Field() # 社名 location = scrapy.Field() # 勤務場所
  25. 3. クロー ラを作成(1/7) scrapy genspider コマンドで雛形となるクロー ラ (spider) を自動的に作成 $

    scrapy genspider クロー ラ名 クロー ル対象ドメイン 例えば, python.org ドメインをクロー ルするクロー ラ の雛形を作成するには以下の通り実行 $ cd pyjob $ scrapy genspider pyjob_spider python.org ※ 作成されたクロー ラはpyjob/spiders 以下にある
  26. 3. クロー ラを作成(2/7) 作成したクロー ラの雛形の中身 自動作成された変数 name: クロー ラ名 allowed_domain:

    クロー ル対象ドメイン start_urls: クロー ル開始ペー ジのURL リスト 自動作成されたメソッド parse: クロー ルしたペー ジのパー ス ※ 後述
  27. 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 を指定可能
  28. 3. クロー ラを作成(4/7) parse メソッドでは主に2 つの処理を行う 1. ペー ジからクロー ル対象の要素を抽出して返す

    Item クラスに必要な情報を格納 ※Item クラスの定義はitem.py で定義 2. 次のクロー ル対象ペー ジのURL を返す scrapy.Request(url) で返されたURL は新たなクロ ー リング対象となる(callback 引数にparse メソ ッドを指定すると, 再帰的にクロー ルを実行)
  29. 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 のセレクタを利用
  30. 3. クロー ラを作成(6/7) settings.py でクロー リングのオプションを設定 絶対に設定して欲しい項目は以下 パラメー タ 意味

    DOWNLOAD_DELAY クロー ル間隔( 秒) robots.txt に従うか否かを設定する ROBOTSTXT_OBEY は デフォルトで True (Scrapy 1.1+)
  31. 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 秒
  32. 4. クロー リング& 結果の保存 $ scrapy crawl 作成したクロー ラ名 -o

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

    Automation Developers", "location": "Remote, USA", "company": "FICO" }, { "title": "Python Developer", "location": "London, UK", "company": "BMLL Technologies" }, ...
  34. クロー リングログを確認 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', ...
  35. クロー ラ作成のTips(1/3) Google Chrome の「 デベロッパー ツー ル」 を使う と3

    ステップでスクレイピング箇所を特定出来る
  36. クロー ラ作成のTips(2/3) scrapy shell を利用してスクレイピング結果をイン タラクティブに確認 $ scrapy shell 'https://www.python.org/jobs/'

    ... >>> response.css('title') [<Selector xpath='descendant-or-self::title' data='<title>Python Job Board | Python.org</ti'>] >>> response.xpath('//title') [<Selector xpath='//title' data='<title>Python Job Board | Python.org</ti'>] ※ requests + BeautifulSoup4 でも代替出来る
  37. クロー ラ作成のTips(3/3) クロー リング過程とスクレイピング過程を分ける サイト構造の変更によるスクレイピングの失敗 は珍しくない => 失敗してもクロー リングを再実行しない =>

    クロー リング/ スクレイピング共に失敗して いないか監視する 対象サイトにJavaScript が含まれているか確認する JavaScript が含まれるか含まれないかで難易度が 大きく変わるため,JavaScript が含まれる場合は 別サイトの利用も検討する
  38. [ まとめ] クロー ラ作成 with Scrapy 以下の手順を踏むことで, 特定サイトから欲しいデー タをクロー ル出来た

    1. プロジェクトを作成 2. クロー ル対象を定義 3. クロー ラを作成 4. クロー リング& 結果の保存
  39. 作成したクロー ラを 管理するにはどうするのか?

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

  41. Scrapy Cloud クロー ラ管理用クラウドサー ビス「scrapinghub」 上で動くScrapy 環境 https://scrapinghub.com/scrapy-cloud/ Scrapy Clound

    の便利なポイント ツー ルの導入が簡単( pip install shub ) API キー を使って簡単deploy( shhub login --> shub deploy ) 簡易かつリッチなUI スケジュー リングも容易( Periodic Jobs )
  42. Scrapy Cloud の課金体系 クロー ル範囲が1 サイト以下の場合は 無料 クレジットカー ドの登録も必要なし デー

    タ保存期間は1 週間 新しくクロー ル先を追加するたびに +9$ / month https://scrapinghub.com/pricing/
  43. scrapyd Scrapy のデー モン 作成したクロー ラのジョブ管理が行える インストー ルが容易 ( pip

    install scrapyd scrapyd-client ) シンプルなAPI を利用した操作 ※ Python 3 に対応していない
  44. クロー ラをscrapyd にdeploy 1. scrapy.cfg の [deploy] にあるurl をコメントアウト [deploy]

    url = http://localhost:6800/ project = pyjob 2. scrapyd を起動 $ scrapyd 3. 作成したクロー ラをscrapyd にdeploy $ scrapyd-deploy -p pyjob
  45. 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
  46. クロー ラ作成に最適な Python ライブラリの紹介

  47. クロー ラ向けライブラリ(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)
  48. クロー ラ向けライブラリ(2/2) 2. aiohttp Python 3.4 から追加されたasyncio を利用した非同期 HTTP Server/Client

    1 プロセス内で複数のリクエス トを同時に実行(=IO 多重化) => 待ち時間を有効に活用して 高速に動作 公式サイト: http://aiohttp.readthedocs.io
  49. 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)
  50. 本日のまとめ

  51. 話したこと Web クロー ラについて説明 クロー ラの利用事例を紹介 クロー リング時の注意点について説明 Scrapy を利用したクロー

    ラ構築方法を一通り説明 クロー ラ構築方法について最低限の流れを説明 クロー ラ構築時のTips について共有 クロー ラの管理に便利なツー ルを紹介 ありがとうございました!