質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

HerokuでSeleniumを使った処理がタイムアウトする<python3、Django>

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 819

Piyohiko

score 4

 前提・実現したいこと

実装したい機能について、アプローチの仕方についてアドバイスをもらいたいです。

現在、タイヤのECサイトから情報を取得してWEBに返すサービスを開発しています。
<サイト:https://www.reifen.de/>

サービスの構成は、以下のようになっており、

①ホーム画面に検索機能を搭載。検索したいタイヤのサイズを入力
②Seleniumを起動し、入力された情報をHTTPレスポンスとして受け取り、その条件をもとに検索。
③検索した情報を、結果画面に表示する。

Localでは時間がかかりながらも、なんとか実現したい事を達成できました。

Herokuに作成したアプリをDeployして、heroku側でもSeleniumを起動する所まで成功しました。
ただし、現在の構成だとView関数の中でSeleniumを起動して情報を収集する機能を含めており、
時間がかかりすぎて、Timeoutでアプリが閉まってしまいます。

View関数のSeleniumパートを非同期処理にしたいと考えているのですが、
一向にやり方が分からなくて困っています。

考えられる方法教えていただけないでしょうか。

どうぞ、よろしくお願いいたします。

 発生している問題・エラーメッセージ

プログラム実施中に、「Application Error」のページが開き画面に以下のメッセージが表示されます。

「Application error
An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details. You can do this from the Heroku CLI with the command
heroku logs --tail」

エラーメッセージの通り、「heroku logs --tail」でlogを確認すると以下のようになっていました。

2018-11-03T14:12:59.156146+00:00 heroku[router]: at=info method=GET path="/search/" host=mysiter.herokuapp.com request_id=658b4dc8-3432-4064-bf84-e7f55b6089b8 fwd="114.160.109.65" dyno=web.1 connect=0ms service=7ms status=200 bytes=1239 protocol=https
2018-11-03T14:12:59.152367+00:00 app[web.1]: 10.9.193.73 - - [03/Nov/2018:23:12:59 +0900] "GET /search/ HTTP/1.1" 200 868 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
2018-11-03T14:13:34.996457+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=POST path="/search/results/" host=mysiter.herokuapp.com request_id=f93bc643-5073-4cf6-bd0f-679c76972981 fwd="114.160.109.65" dyno=web.1 connect=0ms service=30001ms status=503 bytes=0 protocol=https
2018-11-03T14:13:35.250500+00:00 app[web.1]: Internal Server Error: /search/results/
2018-11-03T14:13:35.250514+00:00 app[web.1]: Traceback (most recent call last):
2018-11-03T14:13:35.250535+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
2018-11-03T14:13:35.250537+00:00 app[web.1]: response = get_response(request)
2018-11-03T14:13:35.250540+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/django/core/handlers/base.py", line 126, in _get_response
2018-11-03T14:13:35.250543+00:00 app[web.1]: response = self.process_exception_by_middleware(e, request)
2018-11-03T14:13:35.250545+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/django/core/handlers/base.py", line 124, in _get_response
2018-11-03T14:13:35.250547+00:00 app[web.1]: response = wrapped_callback(request, *callback_args, **callback_kwargs)
2018-11-03T14:13:35.250549+00:00 app[web.1]: File "/app/search/views.py", line 19, in Results
2018-11-03T14:13:35.250551+00:00 app[web.1]: driver = webdriver.Chrome("/app/.apt/usr/bin/google-chrome")  # Chromeを動かすドライバを読み込み
2018-11-03T14:13:35.250553+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/selenium/webdriver/chrome/webdriver.py", line 68, in init
2018-11-03T14:13:35.250554+00:00 app[web.1]: self.service.start()
2018-11-03T14:13:35.250556+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.7/site-packages/selenium/webdriver/common/service.py", line 104, in start
2018-11-03T14:13:35.250558+00:00 app[web.1]: raise WebDriverException("Can not connect to the Service %s" % self.path)
2018-11-03T14:13:35.250559+00:00 app[web.1]: selenium.common.exceptions.WebDriverException: Message: Can not connect to the Service /app/.apt/usr/bin/google-chrome

 該当のソースコード

以下がview関数の詳細で、Results(request)の際にエラーを起こしており、
これがSeleniumを実行中に時間がかかりすぎて、Timeoutになっているのではないかと考えています。

rom django.shortcuts import render
from django.http import HttpResponse
from django.urls import reverse
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect

#検索するようにimportしたモジュール
import requests
from bs4 import BeautifulSoup
import csv
from selenium import webdriver #Selenium Webdriverをインポートして
from selenium.webdriver.support.select import Select
from selenium.webdriver.common.keys import Keys

def Index(request):
    return render(request , 'search/index.html')

def Results(request):
    driver = webdriver.Chrome("/app/.apt/usr/bin/google-chrome")  # Chromeを動かすドライバを読み込み
    #driver = webdriver.Chrome("/usr/local/bin/chromedriver")  # Chromeを動かすドライバを読み込み
    driver.get("https://www.reifen.de")  # サイトを開く!

    # 検索する項目を取得
    elem_search_cate = driver.find_element_by_xpath(
        '//*[@id="tires-configurator-form"]/div[2]/div[1]/div[2]/div/select')  # タイヤカテゴリ選択部分を取得
    elem_search_section = driver.find_element_by_xpath('//*[@id="tire-width"]')  # タイヤsection選択部分を取得
    elem_search_ratio = driver.find_element_by_xpath('//*[@id="tire-height"]')  # タイヤratio選択部分を取得
    elem_search_inch = driver.find_element_by_xpath('//*[@id="tire-diameter"]')  # タイヤinch選択部分を取得
    elem_search_btn = driver.find_element_by_xpath('//*[@id="tires-configurator-form"]/div[3]/div/button')  # 検索ボタンを取得

    #categoryを選択するパート
    #110=夏タイヤ / 120=冬タイヤ / 130=オールシーズン

    cate = request.POST.get('category')

    categories= {"summer":110, "winter":120, "allseason":130}

    text_cate = str(categories[cate])

    select = Select(elem_search_cate)
    select.select_by_value(text_cate)

    #sectionを選択するパート

    text_section = request.POST.get('section')
    select = Select(elem_search_section)
    select.select_by_value(text_section)

    #ratioを選択するパート

    text_ratio =  request.POST.get('ratio')
    select = Select(elem_search_ratio)
    select.select_by_value(text_ratio)

    #inchを選択するパート

    text_inch =  request.POST.get('inch')
    select = Select(elem_search_inch)
    select.select_by_value(text_inch)

    elem_search_btn.send_keys(Keys.ENTER)

    #ここで次のページに移動

    html_a = driver.current_url
    seleniumrequest = requests.get(html_a)
    content = seleniumrequest.content

    soup = BeautifulSoup(content, "html.parser")

    elements_a = soup.find_all(class_="product-list-item product-list-item-top standby-status")

    result = [['name', 'price', 'RRC labeling', 'WET labeling', 'noise labeling']]
    for element in elements_a:
        product_name = element.find(class_="search-result-name").text
        product_price = element.find(class_="search-result-price-lower").text
        product = [product_name.lstrip(), product_price.lstrip().replace('\n', '')]

        result.append(product)
        driver.close()

        return render(request, 'search/results.html', {'result': result, 'section':text_section, 'ratio':text_ratio, 'category':cate, 'inch':text_inch} )

 試したこと

ここに問題に対して試したことを記載してください。

 補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • mrkmyki

    2018/11/04 03:33

    非同期処理にするうえで、何が分からなく困っているのかをもう少し具体的に書かないと回答が付かないと思います。試してみたけど失敗した方法や、動かしているコードを貼るなど。

    キャンセル

  • Piyohiko

    2018/11/04 10:18

    アドバイスありがとうございます。自分なりに、エラーメッセージ、ログ、view関数のコードを載せてみました。もし回答可能であればご対応いただけると助かります。

    キャンセル

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる