バイセル Tech Blog

バイセル Tech Blogは株式会社BuySell Technologiesのエンジニア達が知見・発見を共有する技術ブログです。

バイセル Tech Blog

Smart Proxy Managerを用いたクローラー実行時のアクセス遮断への対策

こちらは バイセルテクノロジーズ Advent Calendar 2021 の 16日目の記事です。
前日の記事は 瀬尾さんの 「ディレクターが要件定義で気を付けていること」 でした。

こんにちは。開発部の赤川です。

バイセルには2021年7月に中途社員として入社しました。 今はリユースプラットフォームのPdM兼エンジニアとして立ち回っています。

入社してまだ半年も経っていませんが、プロダクトとエンジニア組織がメキメキと強く成長していくのを体感していて、 私のエンジニア人生においても今が一番面白いフェーズだなと感じています。

さて、私の話はここまでにして、本題に入っていきましょう。 「Smart Proxy Managerを用いた」とありますが、せっかくなので事業背景から説明させてください。

事業背景

バイセルではお客様から商品買取を行う際、多くの場合に 専門査定 が行われます。 その商品の取り扱いに特化した 専門査定員 が実施することで、主に 買取価格を決める プライシング と 買取商品が本物かどうかを見分ける 真贋 が行われます。 特に難しいのが プライシング で、商品によってはトレンドや外貨変動等の影響で結果が大きく変わることがあります。

お客様へ価格提示する際には、期待値との乖離がないことはもちろん、それが適正価格であるかどうかに気をつけなくてはいけません。

そのため専門査定員は、常に新しく販売された商品の情報を文献やWEBサイトをチェックする必要がありました。

DX、テクノロジーの介入

情報収集を行うクローラーの導入と、収集した情報を簡易表示する社内サイトを立ち上げました。

これまでは専門査定員一人一人が、手動で定期的に複数のWEBサイトをチェックしていましたが、 システムによってより簡単にトレンドが把握でき、専門査定に専念できる環境となりました。

クローラーについて

クローラーにはクローリング用フレームワークのScrapyを利用しています。 Scrapyがどういうものかについては、文献やWEBサイトでの掲載が多くあるのでこの場での紹介は割愛します。

クラウドサービスではZyteを選択しました。主に、下記3種を利用しています。

  • Scrapy Cloud
  • Splash
  • Smrt Proxy Manager

タイトルにあるSmart Proxy Managerとはこの Zyte の機能の1つとなります。

Smart Proxy Managerとは

設定ファイルを数行書くだけで、プロキシープロバイダを経由してクローラーが実行されます。

また、IPアドレスのプールから自動でローテーションします。

アクセス遮断されたリクエスト分はAPIの実行回数としてはカウントされないので、お財布にも優しい超便利機能です。

Smart Proxy Managerの設定

project
├── README.md
├── sample
│   ├── __init__.py
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── scripts
│   │   └── smart_proxy_manager.lua
│   └── settings.py
│       └── item.py
├── pip_requirements.txt
├── scrapinghub.yml
├── scrapy.cfg
└── setup.py

LUAスクリプトの作成

▶︎ scripts/smart_proxy_manager.lua

function use_crawlera(splash)
  -- Make sure you pass your Smart Proxy Manager API key in the 'crawlera_user' arg.
  -- Have a look at the file spiders/quotes-js.py to see how to do it.
  -- Find your Smart Proxy Manager credentials in https://app.zyte.com/
  local user = splash.args.crawlera_user
  local password = ''

  local host = 'proxy.crawlera.com'
  local port = 8010
  local session_header = 'X-Crawlera-Session'
  local session_id = 'create'

  splash:on_request(function (request)
      -- The commented code below can be used to speed up the crawling
      -- process. They filter requests to undesired domains and useless
      -- resources. Uncomment the ones that make sense to your use case
      -- and add your own rules.

      -- Discard requests to advertising and tracking domains.
      -- if string.find(request.url, 'doubleclick%.net') or
      --    string.find(request.url, 'analytics%.google%.com') then
      --     request.abort()
      --     return
      -- end

      -- Avoid using Smart Proxy Manager for subresources fetching to increase crawling
      -- speed. The example below avoids using Smart Proxy Manager for URLS starting
      -- with 'static.' and the ones ending with '.png'.
      -- if string.find(request.url, '://static%.') ~= nil or
      --    string.find(request.url, '%.png$') ~= nil then
      --     return
      -- end
      request:set_proxy(host, port, user, password)
      request:set_header('X-Crawlera-Profile', 'desktop')
      request:set_header('X-Crawlera-Cookies', 'disable')
      request:set_header('X-Crawlera-Timeout', 40000)
      request:set_header(session_header, session_id)
  end)

  splash:on_response_headers(function (response)
      if type(response.headers[session_header]) ~= nil then
          session_id = response.headers[session_header]
      end
  end)
end

function main(splash)
  use_crawlera(splash)
  splash:go(splash.args.url)
  splash:wait(1)
  return splash:html()
end

setup.pyにLUAスクリプトを追加

# Automatically created by: shub deploy

from setuptools import setup, find_packages

setup(
    name         = 'project',
    version      = '1.0',
    packages     = find_packages(),
    package_data = {'sample': ['scripts/*.lua',]},
    entry_points = {'scrapy': ['settings = sample.settings']},
)

Spiderの編集

  1. ItemSpiderの init にてluaスクリプトをload
    def __init__(self, *args, **kwargs):
        self.LUA_SOURCE = get_data('sample', 'scripts/smart_proxy_manager.lua').decode('utf-8')
        super(ItemSpider, self).__init__(*args, **kwargs)
  1. SplashRequest利用時にluaスクリプトを指定
yield SplashRequest(
            url,
            endpoint='execute',
            splash_headers={
                'Authorization': basic_auth_header(self.settings['SPLASH_USER'], ''),
            },
            args={
                'lua_source': self.LUA_SOURCE,
                'crawlera_user': self.settings['CRAWLERA_APIKEY'],
                'timeout': 60,
            },
            cache_args=['lua_source']
        )

※ CRAWLERA_APIKEYにはSmart Proxy ManagerのAPI keyをZyteのGUIから生成したものを渡します

クローラーの実行及び確認

通常のクローラーと同様にZyteのGUI上からScrapy CloudのJobを実行します。

Smart Proxy ManagerのGUI上ではproxyを経由した際のIPアドレスをClient IPとして確認できます。

また、APIの利用状況だけでなく、アクセス遮断件数も確認することができます。

最後に

今回はSmart Proxy Managerに注目した内容をご紹介しましたが、いかがでしたでしょうか。

他にも技術的なチャレンジや、事業のDXの事例が続々出てきていますので、今後のバイセルにご期待ください。


バイセルでは一緒に輝いていけるプロダクトマネージャーを募集しています。
herp.careers

明日の バイセルテクノロジーズ Advent Calendar 2021 は 藤本さんによる 「お店の空き時間をビット演算の論理和で算出する」 です。