質問編集履歴

1

ソースコードを記載しました。

2019/07/18 12:09

投稿

退会済みユーザー
test CHANGED
File without changes
test CHANGED
@@ -2,7 +2,685 @@
2
2
 
3
3
 
4
4
 
5
- Pythonのrequestsを使ってグーグルの検索結果のタイトルやHタグを抜き出すスクレイピングを試みています。
5
+ Pythonのrequestsを使ってグーグルの検索結果のタイトルやHタグを抜き出すスクレイピングを試みています。ソースコードは以下です。
6
+
7
+
8
+
9
+ ```ここに言語を入力
10
+
11
+ from selenium import webdriver
12
+
13
+ from selenium.webdriver.chrome.options import Options
14
+
15
+ from selenium.webdriver.common.keys import Keys
16
+
17
+ import requests
18
+
19
+ from bs4 import BeautifulSoup
20
+
21
+ import gspread
22
+
23
+ from oauth2client.service_account import ServiceAccountCredentials
24
+
25
+ import time
26
+
27
+
28
+
29
+
30
+
31
+ URL = 'https://www.google.co.jp'
32
+
33
+ URL_TITLE = 'Google'
34
+
35
+
36
+
37
+ # 2つのAPIを記述しないとリフレッシュトークンを3600秒毎に発行し続けなければならない
38
+
39
+ scope = [
40
+
41
+ 'https://spreadsheets.google.com/feeds',
42
+
43
+ 'https://www.googleapis.com/auth/drive'
44
+
45
+ ]
46
+
47
+
48
+
49
+ # 認証情報設定
50
+
51
+ # ダウンロードしたjsonファイル名をクレデンシャル変数に設定(秘密鍵、Pythonファイルから読み込みしやすい位置に置く)
52
+
53
+ credentials = ServiceAccountCredentials.from_json_keyfile_name(
54
+
55
+ 'google-multi-search-〇〇〇〇〇.json', scope)
56
+
57
+
58
+
59
+ # 共有設定したスプレッドシートキーを格納
60
+
61
+ SPREADSHEET_KEY = '〇〇〇〇〇〇'
62
+
63
+
64
+
65
+
66
+
67
+ def main():
68
+
69
+ '''
70
+
71
+ メインの処理
72
+
73
+ Googleでキーワードを検索
74
+
75
+ 1ページ目の情報を取得し、Googleスプレッドシートに出力
76
+
77
+ '''
78
+
79
+
80
+
81
+ with open('keyword.txt', encoding='UTF-8') as f:
82
+
83
+ keywords = [s.rstrip() for s in f.readlines()] # 検索キーワードが入力されたテキストファイルを読み込む
84
+
85
+
86
+
87
+ options = Options()
88
+
89
+ options.add_argument('--headless') # ヘッドレスモードを有効にする
90
+
91
+ driver = webdriver.Chrome(options=options) # ChromeのWebDriverオブジェクトを作成
92
+
93
+ driver.get(URL) # Googleのトップページを開く
94
+
95
+ time.sleep(2) # 2秒待機
96
+
97
+ assert URL_TITLE in driver.title # タイトルに'Google'が含まれていることを確認
98
+
99
+
100
+
101
+ for keyword in keywords:
102
+
103
+ print('検索キーワード:' + keyword)
104
+
105
+
106
+
107
+ # Google検索処理
108
+
109
+ search(driver, keyword)
110
+
111
+
112
+
113
+ # 情報取得処理
114
+
115
+ items = get_info(driver, keyword)
116
+
117
+
118
+
119
+ # Googleスプレッドシート出力処理
120
+
121
+ count = 0
122
+
123
+ while True:
124
+
125
+ if count == 3:
126
+
127
+ break
128
+
129
+ else:
130
+
131
+ count = googlespreadsheets(items, keyword, count)
132
+
133
+
134
+
135
+ driver.quit() # ブラウザーを閉じる
136
+
137
+
138
+
139
+
140
+
141
+ def search(driver, keyword):
142
+
143
+ '''
144
+
145
+ 検索テキストボックスに検索キーワードを入力し、検索する
146
+
147
+ '''
148
+
149
+
150
+
151
+ input_element = driver.find_element_by_name('q') # 検索テキストボックスの要素をname属性から取得
152
+
153
+ input_element.clear() # 検索テキストボックスに入力されている文字列を消去
154
+
155
+ input_element.send_keys(keyword) # 検索テキストボックスにキーワードを入力
156
+
157
+ input_element.send_keys(Keys.RETURN) # Enterキーを送信
158
+
159
+ time.sleep(2) # 2秒待機
160
+
161
+
162
+
163
+
164
+
165
+ def get_info(driver, keyword):
166
+
167
+ '''
168
+
169
+ 情報を取得
170
+
171
+ '''
172
+
173
+
174
+
175
+ items_num = 0
176
+
177
+ items = {
178
+
179
+ 'keyword': keyword,
180
+
181
+ 'title': [],
182
+
183
+ 'url': [],
184
+
185
+ 'description': [],
186
+
187
+ 'h1': [],
188
+
189
+ 'h2': [],
190
+
191
+ 'h3': [],
192
+
193
+ 'h4': [],
194
+
195
+ 'h5': [],
196
+
197
+ 'h6': []
198
+
199
+ }
200
+
201
+
202
+
203
+ # url
204
+
205
+ urls = driver.find_elements_by_css_selector('.r > a')
206
+
207
+ if urls:
208
+
209
+ for url in urls:
210
+
211
+ if 'translate' not in url.get_attribute('href'):
212
+
213
+ items['url'].append(url.get_attribute('href').strip())
214
+
215
+
216
+
217
+ # title
218
+
219
+ titles = driver.find_elements_by_css_selector('.r > a > .LC20lb')
220
+
221
+ if titles:
222
+
223
+ for title in titles:
224
+
225
+ items['title'].append(title.text.strip())
226
+
227
+
228
+
229
+ # description
230
+
231
+ descriptions = driver.find_elements_by_css_selector('.s > div > .st')
232
+
233
+ if descriptions:
234
+
235
+ for description in descriptions:
236
+
237
+ items['description'].append(description.text.strip())
238
+
239
+
240
+
241
+ # h1〜h6
242
+
243
+ for url in items['url']:
244
+
245
+ r = requests.get(url)
246
+
247
+ soup = BeautifulSoup(r.content, 'lxml')
248
+
249
+ time.sleep(1) # 1秒待機
250
+
251
+
252
+
253
+ # h1
254
+
255
+ h1s = soup.find_all('h1')
256
+
257
+ h1_list = []
258
+
259
+ for h1 in h1s:
260
+
261
+ if h1.text.strip():
262
+
263
+ h1_list.append(h1.text.strip())
264
+
265
+ items['h1'].append(h1_list)
266
+
267
+
268
+
269
+ # h2
270
+
271
+ h2s = soup.find_all('h2')
272
+
273
+ h2_list = []
274
+
275
+ for h2 in h2s:
276
+
277
+ if h2.text.strip():
278
+
279
+ h2_list.append(h2.text.strip())
280
+
281
+ items['h2'].append(h2_list)
282
+
283
+
284
+
285
+ # h3
286
+
287
+ h3s = soup.find_all('h3')
288
+
289
+ h3_list = []
290
+
291
+ for h3 in h3s:
292
+
293
+ if h3.text.strip():
294
+
295
+ h3_list.append(h3.text.strip())
296
+
297
+ items['h3'].append(h3_list)
298
+
299
+
300
+
301
+ # h4
302
+
303
+ h4s = soup.find_all('h4')
304
+
305
+ h4_list = []
306
+
307
+ for h4 in h4s:
308
+
309
+ if h4.text.strip():
310
+
311
+ h4_list.append(h4.text.strip())
312
+
313
+ items['h4'].append(h4_list)
314
+
315
+
316
+
317
+ # h5
318
+
319
+ h5s = soup.find_all('h5')
320
+
321
+ h5_list = []
322
+
323
+ for h5 in h5s:
324
+
325
+ if h5.text.strip():
326
+
327
+ h5_list.append(h5.text.strip())
328
+
329
+ items['h5'].append(h5_list)
330
+
331
+
332
+
333
+ # h6
334
+
335
+ h6s = soup.find_all('h6')
336
+
337
+ h6_list = []
338
+
339
+ for h6 in h6s:
340
+
341
+ if h6.text.strip():
342
+
343
+ h6_list.append(h6.text.strip())
344
+
345
+ items['h6'].append(h6_list)
346
+
347
+
348
+
349
+ return items
350
+
351
+
352
+
353
+
354
+
355
+ def googlespreadsheets(items, keyword, count):
356
+
357
+ '''
358
+
359
+ Googleスプレッドシート出力
360
+
361
+ '''
362
+
363
+
364
+
365
+ # 制限
366
+
367
+ # ①ユーザーごとに100秒あたり100件のリクエスト
368
+
369
+ # ②1回のプログラムで設定できる最大値は1,000件まで
370
+
371
+ # ③1秒あたり10件まで
372
+
373
+
374
+
375
+ # OAuth2の資格情報を使用してGoogleAPIにログイン
376
+
377
+ gc = gspread.authorize(credentials)
378
+
379
+
380
+
381
+ # シートが作成されているか確認するためのフラグ
382
+
383
+ flag = False
384
+
385
+
386
+
387
+ try:
388
+
389
+ # 共有設定したスプレッドシートのシート1を開く
390
+
391
+ workbook = gc.open_by_key(SPREADSHEET_KEY)
392
+
393
+ worksheet = workbook.add_worksheet(title=keyword, rows='100', cols='100')
394
+
395
+
396
+
397
+ # シートが作成されたらフラグを立てる
398
+
399
+ flag = True
400
+
401
+
402
+
403
+ # スプレッドシート書き込み処理
404
+
405
+ # キーワード
406
+
407
+ worksheet.update_cell(1, 1, keyword)
408
+
409
+ time.sleep(1) # 1秒待機
410
+
411
+
412
+
413
+ # 順位
414
+
415
+ ranking = 1
416
+
417
+ row = 2
418
+
419
+ column = 1
420
+
421
+ for title in items['title']:
422
+
423
+ worksheet.update_cell(row, column, ranking)
424
+
425
+ ranking += 1
426
+
427
+ column += 1
428
+
429
+ time.sleep(3) # 3秒待機
430
+
431
+
432
+
433
+ # 「タイトル」
434
+
435
+ row = 3
436
+
437
+ column = 1
438
+
439
+ for title in items['title']:
440
+
441
+ worksheet.update_cell(row, column, title)
442
+
443
+ column += 1
444
+
445
+ time.sleep(3) # 3秒待機
446
+
447
+
448
+
449
+ # 「URL」
450
+
451
+ row = 4
452
+
453
+ column = 1
454
+
455
+ for url in items['url']:
456
+
457
+ worksheet.update_cell(row, column, url)
458
+
459
+ column += 1
460
+
461
+ time.sleep(3) # 3秒待機
462
+
463
+
464
+
465
+ # 「ディスクリプション」
466
+
467
+ row = 5
468
+
469
+ column = 1
470
+
471
+ for description in items['description']:
472
+
473
+ worksheet.update_cell(row, column, description)
474
+
475
+ column += 1
476
+
477
+ time.sleep(3) # 3秒待機
478
+
479
+
480
+
481
+ # 「h1」
482
+
483
+ row = 6
484
+
485
+ column = 1
486
+
487
+ for h1s in items['h1']:
488
+
489
+ if h1s:
490
+
491
+ h1_str = '*****'.join(h1s)
492
+
493
+ worksheet.update_cell(row, column, h1_str)
494
+
495
+ column += 1
496
+
497
+ else:
498
+
499
+ worksheet.update_cell(row, column, 'なし')
500
+
501
+ column += 1
502
+
503
+ time.sleep(3) # 3秒待機
504
+
505
+
506
+
507
+ # 「h2」
508
+
509
+ row = 7
510
+
511
+ column = 1
512
+
513
+ for h2s in items['h2']:
514
+
515
+ if h2s:
516
+
517
+ h2_str = '*****'.join(h2s)
518
+
519
+ worksheet.update_cell(row, column, h2_str)
520
+
521
+ column += 1
522
+
523
+ else:
524
+
525
+ worksheet.update_cell(row, column, 'なし')
526
+
527
+ column += 1
528
+
529
+ time.sleep(3) # 3秒待機
530
+
531
+
532
+
533
+ # 「h3」
534
+
535
+ row = 8
536
+
537
+ column = 1
538
+
539
+ for h3s in items['h3']:
540
+
541
+ if h3s:
542
+
543
+ h3_str = '*****'.join(h3s)
544
+
545
+ worksheet.update_cell(row, column, h3_str)
546
+
547
+ column += 1
548
+
549
+ else:
550
+
551
+ worksheet.update_cell(row, column, 'なし')
552
+
553
+ column += 1
554
+
555
+ time.sleep(3) # 3秒待機
556
+
557
+
558
+
559
+ # 「h4」
560
+
561
+ row = 9
562
+
563
+ column = 1
564
+
565
+ for h4s in items['h4']:
566
+
567
+ if h4s:
568
+
569
+ h4_str = '*****'.join(h4s)
570
+
571
+ worksheet.update_cell(row, column, h4_str)
572
+
573
+ column += 1
574
+
575
+ else:
576
+
577
+ worksheet.update_cell(row, column, 'なし')
578
+
579
+ column += 1
580
+
581
+ time.sleep(3) # 3秒待機
582
+
583
+
584
+
585
+ # 「h5」
586
+
587
+ row = 10
588
+
589
+ column = 1
590
+
591
+ for h5s in items['h5']:
592
+
593
+ if h5s:
594
+
595
+ h5_str = '*****'.join(h5s)
596
+
597
+ worksheet.update_cell(row, column, h5_str)
598
+
599
+ column += 1
600
+
601
+ else:
602
+
603
+ worksheet.update_cell(row, column, 'なし')
604
+
605
+ column += 1
606
+
607
+ time.sleep(3) # 3秒待機
608
+
609
+
610
+
611
+ # 「h6」
612
+
613
+ row = 11
614
+
615
+ column = 1
616
+
617
+ for h6s in items['h6']:
618
+
619
+ if h6s:
620
+
621
+ h6_str = '*****'.join(h6s)
622
+
623
+ worksheet.update_cell(row, column, h6_str)
624
+
625
+ column += 1
626
+
627
+ else:
628
+
629
+ worksheet.update_cell(row, column, 'なし')
630
+
631
+ column += 1
632
+
633
+ time.sleep(3) # 3秒待機
634
+
635
+
636
+
637
+ count = 3
638
+
639
+ return count
640
+
641
+
642
+
643
+ # エラー処理
644
+
645
+ except gspread.exceptions.APIError as e:
646
+
647
+ # 制限に達した場合
648
+
649
+ if '"code": 429' in str(e):
650
+
651
+ if flag:
652
+
653
+ workbook.del_worksheet(worksheet)
654
+
655
+ print('100秒待機してリトライします')
656
+
657
+ time.sleep(100) # 100秒待機
658
+
659
+ count += 1
660
+
661
+ return count
662
+
663
+ # スプレッドシートに既にデータが存在している場合
664
+
665
+ elif '"code": 400' in str(e):
666
+
667
+ print('既に同じキーワードが存在します')
668
+
669
+ count = 3
670
+
671
+ return count
672
+
673
+
674
+
675
+
676
+
677
+ if __name__ == '__main__':
678
+
679
+ main()
680
+
681
+
682
+
683
+ ```
6
684
 
7
685
 
8
686