回答編集履歴
3
サンプルコードの掲載
test
CHANGED
@@ -51,3 +51,301 @@
|
|
51
51
|
print('Done!')
|
52
52
|
|
53
53
|
```
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
### 追記
|
60
|
+
|
61
|
+
思っている通りの動作になっているかはわかりかねますが
|
62
|
+
|
63
|
+
以下で、正常にpickle化・非pickle化しコードを正常に運転いただけるかと思います。
|
64
|
+
|
65
|
+
コマンドライン引数にinitで初回はpickleの読み込みをしない仕様になっております。
|
66
|
+
|
67
|
+
次回以降は引数を与えない事で、初めに非pickle化され、データが追記されていきます。
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
```python
|
72
|
+
|
73
|
+
from selenium import webdriver
|
74
|
+
|
75
|
+
import time
|
76
|
+
|
77
|
+
import csv
|
78
|
+
|
79
|
+
import re
|
80
|
+
|
81
|
+
from datetime import datetime, date, timedelta
|
82
|
+
|
83
|
+
from selenium.webdriver.common.keys import Keys
|
84
|
+
|
85
|
+
from selenium.webdriver.chrome.options import Options
|
86
|
+
|
87
|
+
import sys
|
88
|
+
|
89
|
+
import pickle
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
def main(is_init):
|
98
|
+
|
99
|
+
if not is_init:
|
100
|
+
|
101
|
+
last_update_dict = pickle_read()
|
102
|
+
|
103
|
+
else:
|
104
|
+
|
105
|
+
last_update_dict = {}
|
106
|
+
|
107
|
+
print(last_update_dict)
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
csv_file_name = "satofuru" + ".csv"
|
112
|
+
|
113
|
+
f = open(csv_file_name, 'a',encoding='cp932', errors='ignore')
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
#ファイルへの書き込み
|
118
|
+
|
119
|
+
writer = csv.writer(f, lineterminator='\n')
|
120
|
+
|
121
|
+
csv_header = ["商品名", "投稿日","評価", "レビュー"]
|
122
|
+
|
123
|
+
writer.writerow(csv_header)
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
# 中略 ここに行いたい処理
|
128
|
+
|
129
|
+
for i in range(3, 4):
|
130
|
+
|
131
|
+
page_scraping(i, is_init, last_update_dict, writer)
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
f.close()
|
136
|
+
|
137
|
+
browser.close()
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
# 最後に今回抽出&上書きしたデータをdumpする。
|
142
|
+
|
143
|
+
pickle_save(last_update_dict)
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
def page_scraping(page, is_init, last_update_dict, writer):
|
148
|
+
|
149
|
+
url = "https://www.satofull.jp/products/list.php?s4=%E5%8C%97%E6%B5%B7%E9%81%93&s3=%E7%B4%8B%E5%88%A5%E5%B8%82&sort=rev_cnt&cnt=60&p={}".format(page)
|
150
|
+
|
151
|
+
browser.get(url)
|
152
|
+
|
153
|
+
time.sleep(1.0)
|
154
|
+
|
155
|
+
elems = browser.find_elements_by_class_name('ItemList__link')
|
156
|
+
|
157
|
+
contain_review_links = []
|
158
|
+
|
159
|
+
review_links = []
|
160
|
+
|
161
|
+
# date_list = []
|
162
|
+
|
163
|
+
date_src_list = []
|
164
|
+
|
165
|
+
for elem in elems:
|
166
|
+
|
167
|
+
#各elemからimgタグのsrcを一覧で出す
|
168
|
+
|
169
|
+
review_score_src = elem.find_element_by_class_name('ItemList__review').find_element_by_tag_name('img').get_attribute('src')
|
170
|
+
|
171
|
+
if review_score_src == 'https://www.satofull.jp/static/master/packages/default/images/pic_star0.png':
|
172
|
+
|
173
|
+
pass
|
174
|
+
|
175
|
+
else:
|
176
|
+
|
177
|
+
# リンクを一覧で取得
|
178
|
+
|
179
|
+
contain_review_links.append(elem.get_attribute('href'))
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
for contain_review_link in contain_review_links:
|
184
|
+
|
185
|
+
time.sleep(1.0)
|
186
|
+
|
187
|
+
browser.get(contain_review_link)
|
188
|
+
|
189
|
+
# 商品ページからレビュー一覧へ
|
190
|
+
|
191
|
+
review_list_src = browser.find_element_by_css_selector('.V1808-dReview__head__btn a').get_attribute('href')
|
192
|
+
|
193
|
+
browser.get(review_list_src)
|
194
|
+
|
195
|
+
time.sleep(2.0)
|
196
|
+
|
197
|
+
|
198
|
+
|
199
|
+
pr_name = browser.find_element_by_css_selector('.product-name a').text
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
# '.table_style_01' = レビュー一覧ページ内のレビューリストの大枠
|
204
|
+
|
205
|
+
review_table = browser.find_elements_by_css_selector('.table_style_01')[2]
|
206
|
+
|
207
|
+
# review_lists = レビューリストの2番目からfor文を回す(1番目は項目のtr)
|
208
|
+
|
209
|
+
review_lists = review_table.find_elements_by_css_selector('tr')[1:]
|
210
|
+
|
211
|
+
for i, review_list in enumerate(review_lists):
|
212
|
+
|
213
|
+
# review_listで投稿日が昨日であれば、「続きを読む」のリンクを取得してcsvに抽出する
|
214
|
+
|
215
|
+
review_lists_date = review_list.find_elements_by_css_selector('td')[0].text
|
216
|
+
|
217
|
+
date_src_list.append(review_lists_date)
|
218
|
+
|
219
|
+
for date_src in date_src_list:
|
220
|
+
|
221
|
+
elem_date = str2date(date_src)
|
222
|
+
|
223
|
+
if is_init:
|
224
|
+
|
225
|
+
if i == 0:
|
226
|
+
|
227
|
+
last_update_dict[pr_name] = elem_date
|
228
|
+
|
229
|
+
review_link_list = review_list.find_element_by_css_selector('a').get_attribute('href')
|
230
|
+
|
231
|
+
review_links.append(review_link_list)
|
232
|
+
|
233
|
+
elif is_bf_yesterday(elem_date, last_update_dict[pr_name]):
|
234
|
+
|
235
|
+
# 昨日の日付の場合はhrefリンクを取得し、リストにする(review_links)
|
236
|
+
|
237
|
+
review_link_list = review_list.find_element_by_css_selector('a').get_attribute('href')
|
238
|
+
|
239
|
+
review_links.append(review_link_list)
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
for review_link in review_links:
|
244
|
+
|
245
|
+
print('review_link ok')
|
246
|
+
|
247
|
+
csv_list = []
|
248
|
+
|
249
|
+
time.sleep(2.0)
|
250
|
+
|
251
|
+
browser.get(review_link)
|
252
|
+
|
253
|
+
elem_product_name = browser.find_element_by_css_selector('.product-name a')
|
254
|
+
|
255
|
+
product_name = elem_product_name.text
|
256
|
+
|
257
|
+
review_box = browser.find_element_by_css_selector('.review_info')
|
258
|
+
|
259
|
+
review_elems = review_box.find_elements_by_css_selector('tr td')
|
260
|
+
|
261
|
+
review_date = review_elems[0].text
|
262
|
+
|
263
|
+
review_score = 0
|
264
|
+
|
265
|
+
imgs = review_box.find_elements_by_css_selector('.valuation img')
|
266
|
+
|
267
|
+
for img in imgs:
|
268
|
+
|
269
|
+
src = img.get_attribute("src")
|
270
|
+
|
271
|
+
if src == 'https://www.satofull.jp/static/master/packages/default/images/common/star_a.png':
|
272
|
+
|
273
|
+
review_score += 1
|
274
|
+
|
275
|
+
review = review_box.find_element_by_css_selector('.comment_area').text
|
276
|
+
|
277
|
+
csv_list.append(product_name)
|
278
|
+
|
279
|
+
csv_list.append(review_date)
|
280
|
+
|
281
|
+
csv_list.append(review_score)
|
282
|
+
|
283
|
+
csv_list.append(review)
|
284
|
+
|
285
|
+
writer.writerow(csv_list)
|
286
|
+
|
287
|
+
|
288
|
+
|
289
|
+
def str2date(date_str):
|
290
|
+
|
291
|
+
result = re.search(r'(\d{4})年(\d{1,2})月(\d{1,2})日', date_str)
|
292
|
+
|
293
|
+
tar_date = datetime(int(result[1]), int(result[2]), int(result[3]))
|
294
|
+
|
295
|
+
return tar_date
|
296
|
+
|
297
|
+
|
298
|
+
|
299
|
+
def is_bf_yesterday(tar_date, last_update_date):
|
300
|
+
|
301
|
+
# now = datetime.now()
|
302
|
+
|
303
|
+
# yesterday = now - timedelta(days=1)
|
304
|
+
|
305
|
+
last_update_date_str = datetime.strftime(last_update_date, '%Y-%m-%d')
|
306
|
+
|
307
|
+
tar_date_str = datetime.strftime(tar_date, '%Y-%m-%d')
|
308
|
+
|
309
|
+
|
310
|
+
|
311
|
+
return tar_date_str > last_update_date_str
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
def pickle_read():
|
316
|
+
|
317
|
+
with open(fine_name,'rb') as f:
|
318
|
+
|
319
|
+
p = pickle.load(f)
|
320
|
+
|
321
|
+
return p
|
322
|
+
|
323
|
+
|
324
|
+
|
325
|
+
def pickle_save(data):
|
326
|
+
|
327
|
+
with open(fine_name, 'wb') as f:
|
328
|
+
|
329
|
+
pickle.dump(data, f)
|
330
|
+
|
331
|
+
print('Done!')
|
332
|
+
|
333
|
+
|
334
|
+
|
335
|
+
if __name__ == "__main__":
|
336
|
+
|
337
|
+
fine_name = 'pickle.binaryfile'
|
338
|
+
|
339
|
+
browser = webdriver.Chrome()
|
340
|
+
|
341
|
+
if len(sys.argv) >= 2:
|
342
|
+
|
343
|
+
if sys.argv[1] == 'init':
|
344
|
+
|
345
|
+
main(is_init=True)
|
346
|
+
|
347
|
+
else:
|
348
|
+
|
349
|
+
main(False)
|
350
|
+
|
351
|
+
```
|
2
修正
test
CHANGED
@@ -44,7 +44,7 @@
|
|
44
44
|
|
45
45
|
def pickle_save(data):
|
46
46
|
|
47
|
-
with open(file_name, 'w') as f:
|
47
|
+
with open(file_name, 'wb') as f:
|
48
48
|
|
49
49
|
pickle.dump(data, f)
|
50
50
|
|
1
test
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
最終的にはこの様な構造でコーディングしていけば良いと思います。
|
2
2
|
|
3
|
-
コードを実行する時に、pickleを読み取るかどうかはgomasan様の中のルールや条件というものがあるでしょうから、それに従ってif文などで処理してください。
|
3
|
+
コードを実行する時に、pickleを読み取るかどうかはgomasan様の中のルールや条件というものがあるでしょうから、それに従ってif文などで処理してください。(初回起動である場合にも読み取る必要ない)
|
4
4
|
|
5
5
|
|
6
6
|
|