質問編集履歴

1

2022/01/12 07:49

投稿

kashmir
kashmir

スコア10

test CHANGED
File without changes
test CHANGED
@@ -1,189 +1,260 @@
1
1
  ### 前提・実現したいこと
2
2
 
3
-
4
-
5
3
  Python・flaskで作ったwebアプリをherokuでデプロイし成功したものの、URLに飛ぶとApplication errorとなってしまう。
6
4
 
7
-
8
-
9
5
  プログラミング初心者です。分かりづらい点があるかと思います、ご容赦ください。
10
6
 
11
-
12
-
13
7
  ### 発生している問題・エラーメッセージ
14
-
15
8
  エラーコードはH10。問題箇所と思われるメッセージはこちらです。
16
-
17
- ```
9
+ ```
18
-
19
10
  Failed to find attribute 'application' in 'app'.
20
-
21
- ```
11
+ ```
22
-
23
-
24
12
 
25
13
  ### 該当のソースコード
26
-
27
14
  該当ファイルの構成は以下です。
28
15
 
29
-
30
-
31
16
  アプリのファイル
32
-
33
17
  |ーーapp.py
34
-
35
18
  |ーーProcfile
36
-
37
19
  |ーーrequirements.txt
38
-
39
20
  |ーーruntime.txt
40
-
41
21
  |ーー__pycache__
42
-
43
22
  |ーーtemplates
44
-
45
23
  |ーーvenv
46
-
24
+ |ーー.env
47
-
25
+ |ーー.env.sample
48
26
 
49
27
  □「heroku logs --tail --app 自分のアプリ名」の実行結果
50
28
 
51
-
52
-
53
- ```
29
+ ```
54
-
55
30
  2022-01-11T11:06:47.556703+00:00 heroku[web.1]: State changed from crashed to starting
56
-
57
31
  2022-01-11T11:06:52.498156+00:00 heroku[web.1]: Starting process with command `gunicorn app : app --log-file -`
58
-
59
32
  2022-01-11T11:06:53.838531+00:00 app[web.1]: [2022-01-11 11:06:53 +0000] [4] [INFO] Starting gunicorn 20.1.0
60
-
61
33
  2022-01-11T11:06:53.838940+00:00 app[web.1]: [2022-01-11 11:06:53 +0000] [4] [INFO] Listening at: http://0.0.0.0:24665 (4)
62
-
63
34
  2022-01-11T11:06:53.838980+00:00 app[web.1]: [2022-01-11 11:06:53 +0000] [4] [INFO] Using worker: sync
64
-
65
35
  2022-01-11T11:06:53.842165+00:00 app[web.1]: [2022-01-11 11:06:53 +0000] [9] [INFO] Booting worker with pid: 9
66
-
67
36
  2022-01-11T11:06:53.853462+00:00 app[web.1]: [2022-01-11 11:06:53 +0000] [10] [INFO] Booting worker with pid: 10
68
-
69
37
  2022-01-11T11:06:54.366422+00:00 heroku[web.1]: State changed from starting to up
70
-
71
38
  2022-01-11T11:06:55.711302+00:00 app[web.1]: Failed to find attribute 'application' in 'app'.
72
-
73
39
  2022-01-11T11:06:55.711529+00:00 app[web.1]: [2022-01-11 11:06:55 +0000] [9] [INFO] Worker exiting (pid: 9)
74
-
75
40
  2022-01-11T11:06:55.711605+00:00 app[web.1]: Failed to find attribute 'application' in 'app'.
76
-
77
41
  2022-01-11T11:06:55.711847+00:00 app[web.1]: [2022-01-11 11:06:55 +0000] [10] [INFO] Worker exiting (pid: 10)
78
-
79
42
  2022-01-11T11:06:56.299718+00:00 app[web.1]: [2022-01-11 11:06:56 +0000] [4] [WARNING] Worker with pid 10 was terminated due to signal 15
80
-
81
43
  2022-01-11T11:06:56.395344+00:00 app[web.1]: [2022-01-11 11:06:56 +0000] [4] [INFO] Shutting down: Master
82
-
83
44
  2022-01-11T11:06:56.395413+00:00 app[web.1]: [2022-01-11 11:06:56 +0000] [4] [INFO] Reason: App failed to load.
84
-
85
45
  2022-01-11T11:06:56.557625+00:00 heroku[web.1]: Process exited with status 4
86
-
87
46
  2022-01-11T11:06:56.610039+00:00 heroku[web.1]: State changed from up to crashed
88
-
89
47
  2022-01-11T11:06:58.000000+00:00 app[api]: Build succeeded
90
-
91
48
  2022-01-11T11:07:02.198343+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=foodbook135.herokuapp.com request_id=fc34bf91-5ec2-44a0-ac3d-fc6e828ba59c fwd="106.154.137.195" dyno= connect= service= status=503 bytes= protocol=https
92
-
93
49
  2022-01-11T11:07:02.822734+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=foodbook135.herokuapp.com request_id=fe1c5296-7855-4f26-b958-f03f77e4fc6d fwd="106.154.137.195" dyno= connect= service= status=503 bytes= protocol=https
94
-
95
- ```
50
+ ```
96
-
97
-
98
51
 
99
52
  ```Procfile
100
-
101
53
  web: gunicorn app : app --log-file -
102
-
103
- ```
54
+ ```
104
-
105
-
106
55
 
107
56
  ```requirements
108
-
109
57
  beautifulsoup4==4.10.0
110
-
111
58
  cachetools==4.2.4
112
-
113
59
  certifi==2021.10.8
114
-
115
60
  charset-normalizer==2.0.9
116
-
117
61
  click==8.0.3
118
-
119
62
  Flask==2.0.2
120
-
121
63
  google-api-core==2.3.2
122
-
123
64
  google-api-python-client==2.33.0
124
-
125
65
  google-auth==2.3.3
126
-
127
66
  google-auth-httplib2==0.1.0
128
-
129
67
  googleapis-common-protos==1.54.0
130
-
131
68
  gunicorn==20.1.0
132
-
133
69
  httplib2==0.20.2
134
-
135
70
  idna==3.3
136
-
137
71
  itsdangerous==2.0.1
138
-
139
72
  Jinja2==3.0.3
140
-
141
73
  MarkupSafe==2.0.1
142
-
143
74
  protobuf==3.19.1
144
-
145
75
  pyasn1==0.4.8
146
-
147
76
  pyasn1-modules==0.2.8
148
-
149
77
  pyparsing==3.0.6
150
-
151
78
  requests==2.26.0
152
-
153
79
  rsa==4.8
154
-
155
80
  six==1.16.0
156
-
157
81
  soupsieve==2.3.1
158
-
159
82
  uritemplate==4.1.1
160
-
161
83
  urllib3==1.26.7
162
-
163
84
  Werkzeug==2.0.2
164
85
 
165
-
166
-
167
- ```
86
+ ```
87
+
168
-
88
+ ```app.py
169
-
89
+ # -*- coding: utf-8 -*-
90
+ from bs4 import BeautifulSoup
91
+ import re
92
+ from flask import Flask, render_template, request, session
93
+ import requests
94
+ import settings
95
+ from requests.exceptions import Timeout
96
+ # 返却された検索結果の読み取りにつかう
97
+ from googleapiclient.discovery import build
98
+
99
+ # =================================
100
+ app = Flask(__name__)
101
+
102
+ # カスタム検索エンジンID
103
+ CUSTOM_SEARCH_ENGINE_ID = "87dabc623cf5e8624"
104
+ # API キー
105
+ API_KEY = settings.AP
106
+
107
+ # APIにアクセスして結果をもらってくるメソッド
108
+ def get_search_results(query):
109
+
110
+ # APIでやりとりするためのリソースを構築
111
+ search = build(
112
+ "customsearch",
113
+ "v1",
114
+ developerKey = API_KEY
115
+ )
116
+
117
+ # Google Custom Search から結果を取得
118
+ result = search.cse().list(
119
+ q = query,
120
+ cx = CUSTOM_SEARCH_ENGINE_ID,
121
+ lr = 'lang_ja',
122
+ num = 5,
123
+ start = 1
124
+ ).execute()
125
+
126
+ # 受け取ったjsonをそのまま返却
127
+ return result
128
+
129
+ # 検索結果の情報をSearchResultに格納してリストで返す
130
+ def summarize_search_results(result):
131
+
132
+ # 結果のjsonから検索結果の部分を取り出しておく
133
+ result_items_part = result['items']
134
+
135
+ # 抽出した検索結果の情報はこのリストにまとめる
136
+ result_items = []
137
+
138
+ # 今回は (start =) 1 個目の結果から (num =) 10 個の結果を取得した
139
+ for i in range(0, 5):
140
+ # i番目の検索結果の部分
141
+ result_item = result_items_part[i]
142
+ # i番目の検索結果からそれぞれの属性の情報をResultクラスに格納して
143
+ # result_items リストに追加する
144
+ s_r = SearchResult(
145
+ title = result_item['title'],
146
+ url = result_item['link'],
147
+ snippet = result_item['snippet']
148
+ )
149
+
150
+ result_items.append(s_r.Making_d())
151
+
152
+ # 結果を格納したリストを返却
153
+ return result_items
154
+
155
+ # 検索結果の情報を格納するクラス
156
+ class SearchResult:
157
+ def __init__(self, title, url, snippet):
158
+ self.title = title
159
+ self.url = url
160
+ self.snippet = snippet
161
+
162
+ def __str__(self):
163
+ # コマンドライン上での表示形式はご自由にどうぞ
164
+ return "[title] " + self.title + "\n\t[detail] " + self.snippet + "\n\t[url]" + self.url
165
+
166
+ def Making_d(self):
167
+ d_info = dict(title=self.title, url=self.url, detail=self.snippet)
168
+ return d_info
169
+
170
+ # htmlとやり取りするパート
171
+ app = Flask(__name__)
172
+
173
+ app.secret_key = 'abcdefghijklmn'
174
+
175
+ @app.route('/', methods=['GET'])
176
+ def get():
177
+ return render_template('index.html')
178
+
179
+ # フォームを読み込んで検索結果を出す =page2
180
+ @app.route('/templates/page2', methods=['POST'])
181
+ def post():
182
+ name = request.form.get('name')
183
+ prefecture = request.form.get('prefectures')
184
+ query = name
185
+ query2 = prefecture
186
+ query3 = '"食べログ"'
187
+ the_word = query + " " + query2 + " " + query3
188
+
189
+ # APIから検索結果を取得
190
+ result = get_search_results(the_word)
191
+ # result には 返却されたjsonが入る
192
+
193
+ # 検索結果情報からタイトル, URL, スニペット, 検索結果の順位を抽出してまとめる
194
+ result_items_list = summarize_search_results(result)
195
+ # result_items_list には SearchResult のリストが入る
196
+
197
+ # 他のページへ渡せるようにsessionを使う
198
+ session['result_items_list'] = result_items_list
199
+
200
+ # コマンドラインに検索結果の情報を1個分だけ表示
201
+ print(result_items_list[0])
202
+ # print(query2)
203
+ # 第2引数で、htmlファイル上の変数にここで用いたリストを代入している
204
+ return render_template('page2.html', rst_info=result_items_list)
205
+
206
+ # 1つ目の情報が誤っていたときに2つ目の検索結果を表示する=page3
207
+ @app.route('/templates/page3', methods=["get"])
208
+ def page3():
209
+ # indexからpage2への移動時に作成された検索結果のリストをsessionを使って呼び出す
210
+ searched_list = session.get('result_items_list', None)
211
+
212
+ print(searched_list[1])
213
+ return render_template('page3.html', rst_info=searched_list)
214
+
215
+ # page2での情報でOKだったときに、その店の詳細を表示させる=goal
216
+ @app.route('/templates/goal', methods=["get"])
217
+ def goal():
218
+
219
+ searched_list = session.get('result_items_list', None)
220
+ #↓OKが出た店の食べログURLでスクレイピング
221
+ url_t = searched_list[0]['url']
222
+ r = requests.get(url_t)
223
+ soup = BeautifulSoup(r.text, 'html.parser')
224
+ name_rst = soup.find('div', class_='rstinfo-table__name-wrap').text
225
+ station_rst = soup.find('span', class_='linktree__parent-target-text').text
226
+ tel_rst = soup.find('p', class_='rstdtl-side-yoyaku__tel-number').text
227
+
228
+ return render_template('goal.html', searched_list=searched_list, name_rst=name_rst, \
229
+ station_rst=station_rst, tel_rst=tel_rst)
230
+
231
+ # 情報2件が両方とも不適切だった場合、はじめに戻る=fail
232
+ @app.route('/templates/fail', methods=["get"])
233
+ def fail():
234
+ return render_template('fail.html')
235
+
236
+ # xxxxxxxxxxxxxxxxxxxxxxxxxx
237
+ if __name__ == '__main__':
238
+ # app.run(debug=True)
239
+ app.debug = True
240
+ app.run()
241
+ # xxxxxxxxxxxxxxxxxxxxxxxxxx
242
+
243
+
244
+
245
+
246
+
247
+
248
+
249
+ ```
170
250
 
171
251
  ### 試したこと
172
252
 
173
-
174
-
175
253
  調べる中でProcfileが特にあやしいと感じ、いろいろと英語のサイトなどにも当たりましたが原因がわかりませんでした。
176
254
 
177
-
178
-
179
255
  ### 特に参考にしたページ
180
256
 
181
-
182
-
183
257
  https://toukei-lab.com/heroku-python
184
-
185
258
  https://creepfablic.site/2019/06/15/heroku-procfile-matome/
186
259
 
187
-
188
-
189
260
  よろしくお願いいたします。