teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

5

Fix code

2020/08/10 06:03

投稿

y_shinoda
y_shinoda

スコア3272

answer CHANGED
@@ -304,15 +304,15 @@
304
304
  'https://www.google.co.jp/mail/help/intl/ja/about.html?vm=r', # GMail
305
305
  ]
306
306
 
307
- list_response = ParallelHtmlScraper.execute(f'{host_google}', path_and_content, AnalyzerForTest())
307
+ list_response = ParallelHtmlScraper.execute(host_google, path_and_content, AnalyzerForTest())
308
308
  print(list_response)
309
309
  ```
310
310
 
311
311
  実行結果:
312
312
 
313
313
  ```python
314
- $ python test.py
314
+ $ pipenv run python test.py
315
- ['Google', 'Google 画像検索', 'Google ショピング', 'コレクション', 'Google マップ', '\n Google ドライブ\n ', '\n Gmail - Google のメール\n ']
315
+ ['Google 画像検索', ' Google ', '\n Gmail - Google のメール\n ', 'Google ショッピ', 'Google', '\n Google ドライブ\n ', 'コレクション']
316
316
  ```
317
317
 
318
318
  このパッケージを実装していたときは、

4

Fix code

2020/08/10 06:02

投稿

y_shinoda
y_shinoda

スコア3272

answer CHANGED
@@ -304,7 +304,7 @@
304
304
  'https://www.google.co.jp/mail/help/intl/ja/about.html?vm=r', # GMail
305
305
  ]
306
306
 
307
- list_response = ParallelHtmlScraper.execute(f'{host_google}', path_and_content.keys(), AnalyzerForTest())
307
+ list_response = ParallelHtmlScraper.execute(f'{host_google}', path_and_content, AnalyzerForTest())
308
308
  print(list_response)
309
309
  ```
310
310
 

3

Fix link to Stack Overflow

2020/08/08 03:09

投稿

y_shinoda
y_shinoda

スコア3272

answer CHANGED
@@ -48,7 +48,7 @@
48
48
  asyncio.run(asynchronous_process(urls))
49
49
  ```
50
50
 
51
- 参考: [Answer: How could I use requests in asyncio? ](https://stackoverflow.com/a/47572164/12721873)
51
+ 参考: [Answer: How could I use requests in asyncio? ](https://stackoverflow.com/a/22414756/12721873)
52
52
 
53
53
  ## 検証
54
54
 

2

Fix answer that mistook intention of question

2020/07/01 21:46

投稿

y_shinoda
y_shinoda

スコア3272

answer CHANGED
@@ -30,11 +30,32 @@
30
30
  time.sleep(1)
31
31
  ```
32
32
 
33
+ ## スレッドから非同期への変更
34
+
35
+ 次の箇所を変更します:
36
+
37
+ ```python
38
+ with ThreadPoolExecutor(max_workers=2) as pool:
39
+ threads = [res for res in pool.map(check_url, urls)]
40
+ ```
41
+
42
+
43
+ ```python
44
+ async def asynchronous_process(urls):
45
+ loop = asyncio.get_event_loop()
46
+ futures = [loop.run_in_executor(None, check_url, url) for url in urls]
47
+ await asyncio.gather(*futures)
48
+ asyncio.run(asynchronous_process(urls))
49
+ ```
50
+
51
+ 参考: [Answer: How could I use requests in asyncio? ](https://stackoverflow.com/a/47572164/12721873)
52
+
33
53
  ## 検証
34
54
 
35
55
  次のように行いました:
36
56
 
37
57
  ```python
58
+ import asyncio
38
59
  import requests
39
60
  import json
40
61
  import time
@@ -42,7 +63,7 @@
42
63
  import os
43
64
  import sys
44
65
  from bs4 import BeautifulSoup
45
- from concurrent.futures import ThreadPoolExecutor
66
+ # from concurrent.futures import ThreadPoolExecutor
46
67
 
47
68
  if os.path.exists("list.txt"):
48
69
  pass
@@ -79,19 +100,18 @@
79
100
  start = time.time()
80
101
 
81
102
  def check_url(target_url, headers=headers, proxies=proxies, retry=3):
82
-
83
103
  for i in range(retry):
84
104
 
85
105
  try:
86
106
  start = time.time()
87
107
 
88
108
  #ここ↓のリクエストが時間がかかるので非同期処理をさせたい
89
-
90
109
  req = requests.get(
91
110
  target_url, headers=headers, proxies=proxies, allow_redirects=False
92
111
  )
93
112
  logs.append(str(req.status_code) + "\t" + target_url)
94
113
  target_urlll = re.sub("(.*)(?=/)|/|(?=?)(.*)", "", target_url)
114
+ print(target_url)
95
115
  print(str(req.status_code) + "\t" + target_urlll)
96
116
 
97
117
  # if req.status_code == 404:
@@ -171,7 +191,7 @@
171
191
 
172
192
  # break
173
193
 
174
- # return
194
+ return
175
195
  except requests.exceptions.ConnectTimeout:
176
196
  logs.append("TIMEOUT" + "\t" + target_url)
177
197
  time.sleep(10)
@@ -187,10 +207,15 @@
187
207
  with open("list.txt") as f:
188
208
  urls = f.read().splitlines()
189
209
 
190
- threads = []
210
+ # threads = []
191
211
 
192
- with ThreadPoolExecutor(max_workers=2) as pool:
212
+ # with ThreadPoolExecutor(max_workers=()) as pool:
193
- threads = [res for res in pool.map(check_url, urls)]
213
+ # threads = [res for res in pool.map(check_url, urls)]
214
+ async def asynchronous_process(urls):
215
+ loop = asyncio.get_event_loop()
216
+ futures = [loop.run_in_executor(None, check_url, url) for url in urls]
217
+ await asyncio.gather(*futures)
218
+ asyncio.run(asynchronous_process(urls))
194
219
 
195
220
  with open("log.txt", "w") as f:
196
221
  f.write("\n".join(logs))
@@ -219,15 +244,15 @@
219
244
  実行結果:
220
245
 
221
246
  ```console
222
- $ pipenv run python test2.py
247
+ $ pipenv run python test.py
223
248
  https://www.yahoo.co.jp/
224
249
  200
250
+ https://www.facebook.com/
251
+ 302
225
252
  https://www.google.com/
226
253
  200
227
254
  https://www.bing.com/
228
255
  200
229
- https://www.facebook.com/
230
- 302
231
256
  https://www.instagram.com/
232
257
  200
233
258
  https://twitter.com/
@@ -235,24 +260,26 @@
235
260
  https://www.amazon.co.jp/
236
261
  200
237
262
 
238
- elapsed_time:1.1018426418304443[sec]
263
+ elapsed_time:0.526411771774292[sec]
239
264
 
240
265
  1回目
241
266
  ```
242
267
 
268
+ レスポンスの早さの違いによって
243
- レスポンスの早さによって結果が入れ替わっているのがわかります
269
+ 実行結果の出力順 `list.txt` の順序と入れ替わっているのがわかります
244
270
 
245
271
  ## aiohttp を使った方法
246
272
 
247
- 以前にほぼ同様のことを実現するためのライブラリーを作成しました
273
+ 以前にほぼ同様のことを実現するためのパッケを作成しました
248
274
 
249
275
  [yukihiko-shinoda/parallel-html-scraper](https://github.com/yukihiko-shinoda/parallel-html-scraper)
250
276
  [parallelhtmlscraper · PyPI](https://pypi.org/project/parallelhtmlscraper/)
251
277
 
252
278
  (README.md を記述していなくて恐縮です)
253
279
 
254
- ライブラリーとして使えば再発明の必要がなくなりますし、
280
+ パッケとして使えば再発明の必要がなくなりますし、
281
+ パッケージのコードの中身を読んでいただくと、
255
- コードの中身を読んでいただくと、どのように実装すべきかが理解いただけると思います
282
+ どのように実装すべきかが理解いただけると思います
256
283
 
257
284
  ライブラリーの利用例:
258
285
 
@@ -271,9 +298,9 @@
271
298
  '/webhp?tab=rw', # Google 検索
272
299
  '/imghp?hl=ja&tab=wi&ogbl', # Google 画像検索
273
300
  '/shopping?hl=ja&source=og&tab=wf', # Google ショッピング
274
- '/save', # Google Collection
301
+ '/save', # コレクション
275
- 'https://www.google.co.jp/maps', # Google Maps
302
+ 'https://www.google.co.jp/maps', # Google マップ
276
- 'https://www.google.co.jp/drive/apps.html', # Google Drive
303
+ 'https://www.google.co.jp/drive/apps.html', # Google ドライブ
277
304
  'https://www.google.co.jp/mail/help/intl/ja/about.html?vm=r', # GMail
278
305
  ]
279
306
 
@@ -286,4 +313,9 @@
286
313
  ```python
287
314
  $ python test.py
288
315
  ['Google', 'Google 画像検索', 'Google ショッピング', 'コレクション', 'Google マップ', '\n Google ドライブ\n ', '\n Gmail - Google のメール\n ']
289
- ```
316
+ ```
317
+
318
+ このパッケージを実装していたときは、
319
+ とにかく公式ドキュメントばかりを読んでいた記憶があります
320
+
321
+ [コルーチンと Task — Python 3.8.4rc1 ドキュメント](https://docs.python.org/ja/3.8/library/asyncio-task.html)

1

Update description

2020/07/01 21:40

投稿

y_shinoda
y_shinoda

スコア3272

answer CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 修正が必要な箇所
4
4
 
5
- 1.
5
+ 1
6
6
  `ThreadPoolExecutor()` の引数 `max_workers` に int 型の値を設定します:
7
7
 
8
8
  ```python
@@ -16,7 +16,7 @@
16
16
  with ThreadPoolExecutor(max_workers=2) as pool:
17
17
  ```
18
18
 
19
- 2.
19
+ 2
20
20
  少なくとも、同じリソースへの繰り返しアクセスは 1 秒以上間隔を空けた方が良いでしょう:
21
21
 
22
22
  ```python
@@ -252,8 +252,10 @@
252
252
  (README.md を記述していなくて恐縮です)
253
253
 
254
254
  ライブラリーとして使えば再発明の必要がなくなりますし、
255
- コードを読んでいただくと、どのように実装すべきかが理解いただけると思います
255
+ コードの中身を読んでいただくと、どのように実装すべきかが理解いただけると思います
256
256
 
257
+ ライブラリーの利用例:
258
+
257
259
  ```python
258
260
  from bs4 import BeautifulSoup
259
261