回答編集履歴
5
Fix code
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(
|
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
|
315
|
+
['Google 画像検索', ' Google マップ ', '\n Gmail - Google のメール\n ', 'Google ショッピング', 'Google', '\n Google ドライブ\n ', 'コレクション']
|
316
316
|
```
|
317
317
|
|
318
318
|
このパッケージを実装していたときは、
|
4
Fix code
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
|
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
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/
|
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
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
|
-
|
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=
|
212
|
+
# with ThreadPoolExecutor(max_workers=()) as pool:
|
193
|
-
|
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
|
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:
|
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', #
|
301
|
+
'/save', # コレクション
|
275
|
-
'https://www.google.co.jp/maps', # Google
|
302
|
+
'https://www.google.co.jp/maps', # Google マップ
|
276
|
-
'https://www.google.co.jp/drive/apps.html', # Google
|
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
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
|
|