Help us understand the problem. What is going on with this article?

[Python] スクレイピング in AWS Lambda

More than 3 years have passed since last update.

Javascriptありのサイトに対応するため、下記のスタックでスクレイピングする環境を整える

  • Phantomjs
  • Selenium

必要ライブラリ
ローカル実行

pip install python-lambda-local

デプロイ

pip install lambda-uploader

サクッと試したい方は下記のリポジトリで
https://github.com/akichim21/python_scraping_in_lambda

実行スクリプト

selenium(driver: phantomjs)でjs実行済みのhtmlを生成して、タイトルを抜き出すということをやってます。最後にclose(), quit()してphantomjsをkillするだけのスクリプト。

lambda_function.py
#!/usr/bin/env python

import time # for sleep
import os   # for path
import signal
import selenium
from selenium import webdriver
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

def lambda_handler(event, context):
  # set user agent
  user_agent = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36")

  dcap = dict(DesiredCapabilities.PHANTOMJS)
  dcap["phantomjs.page.settings.userAgent"] = user_agent
  dcap["phantomjs.page.settings.javascriptEnabled"] = True

  browser = webdriver.PhantomJS(
              service_log_path=os.path.devnull,
              executable_path="./phantomjs",
              service_args=['--ignore-ssl-errors=true', '--load-images=no', '--ssl-protocol=any'],
              desired_capabilities=dcap
            )

  browser.get('http://google.com')
  title = browser.title
  browser.close()
  browser.quit()
  return title

引数に渡すjson

今回は使わないが、event["key1"]みたいに引数を渡す時には使用する

event.json
{
  "key3": "value3",
  "key2": "value2",
  "key1": "value1"
}

Lambdaの設定json

roleを作成&置換してください。
今回は50M以上ではないので、s3を使いませんが他のライブラリを使うとすぐ50MB以上になるので、s3必須です。s3_bucketを設定するとs3経由でファイルがアップロードされます。
+ "s3_bucket": "xxx-lambda"
+ "s3_key": "deploy/lambda_function.zip"

nameは実行時によく使うので本番では適切な名前を。
memory, timeoutなどもスクリプトに応じて適切に設定してください。

lambda.json
{
  "name": "python_scraping_test",
  "description": "python_scraping_test",
  "region": "ap-northeast-1",
  "runtime": "python2.7",
  "handler": "lambda_function.lambda_handler",
  "role": "arn:aws:iam::00000000:role/lambda_basic_execution",
  "timeout": 60,
  "memory": 128,
  "variables": {
    "production": "True"
  },
  "ignore": [
    "\\.git.*",
    "/.*\\.pyc$",
    "/.*\\.zip$"
  ]
}

依存関係

seleniumだけpipで入れる。phantomjsはバイナリで保存しておく。

requirements.txt
selenium

ローカル実行コマンド

python-lambda-localを使って実行fはファンクション名、tはタイムアウト(s)を指定して実行

python-lambda-local -f lambda_handler -l ./ -t 60 lambda_function.py event.json
結果
[root - INFO - 2017-03-19 08:16:05,271] Event: {u'test': u'test'}
[root - INFO - 2017-03-19 08:16:05,271] START RequestId: 4e881a1b-3f7a-4de8-9afb-aee6f6b5dac6
[root - INFO - 2017-03-19 08:16:06,766] END RequestId: 4e881a1b-3f7a-4de8-9afb-aee6f6b5dac6
[root - INFO - 2017-03-19 08:16:06,766] RESULT:
Google
[root - INFO - 2017-03-19 08:16:06,766] REPORT RequestId: 4e881a1b-3f7a-4de8-9afb-aee6f6b5dac6  Duration: 1494.06 ms

deployコマンド

~/.aws/credentialsを使うので、設定してない場合は設定を

aws-cliない場合はインストール

pip install awscli
aws configure

condaなどvirtualenvが特殊な場所にある時は場所を把握しておく。Location

pip show virtualenv
lambda-uploader

## virtualenvが特殊な場所の場合はLocationのディレクトリを引数に(vagrant、anaconda3、envがpy2だとこんな感じ
lambda-uploader --virtualenv=/home/vagrant/.pyenv/versions/anaconda3-4.1.0/envs/py2/lib/python2.7/site-packages
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away