pythonで書いたスクレイピングプログラムがエラーを出さずに落ちてしまいます
解決したいこと
Googleでニュースを検索するpythonコードを書こうとしています。
macOS Catalina 10.15.7 / ターミナル 2.10 / python 3.9.7
下に載せましたサンプルを走らせますと次のケースのいずれかで止まり、最後まで検索を終了できません。エラーも出力されず、これらへの対処法を調べることができないまま手を束ねています。
1) 159,160行でページ読み込みがタイムアウトになった場合、あきらめて次のページに行くように書いたつもりですが、プログラムがここで止まってしまいます("AA"までを表示するが、"AAA"を表示しない)。
driver.get(link)
wait.until(EC.presence_of_all_elements_located)
2) 180,181行で、プログラム止まってしまいます("BBB"までを表示するが、"BBBBBB"を表示しない)。
html = driver.page_source
wait.until(EC.presence_of_all_elements_located)
上の2件を含め、他にもお気づきの点をご指摘いただけましたら幸いです。
発生している問題・エラー
(エラーがターミナルに表示されません。)
該当するソースコード
# -*- coding: utf-8 -*-
"""""""""""""""
#使用例;$ python google_news_step.py 環境 after:1990-01-01 before:1990-12-31 > log.txt
"""""""""""""""
import sys
#sys.path.append('/Applications/anaconda3/lib/python3.9/site-packages')
sys.path.append('/Volumes/Dropbox/Dropbox/study_work/webdriver')
### 【Selenium】PythonでYahooニュースの一覧を取得
### https://teshi-learn.com/2020-09/python-scrayping-driver/
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
import time
"""""""""""""""
#作業フォルダ指定
"""""""""""""""
options = Options()
#options.add_argument('--headless')
#driver = webdriver.Chrome("chromedriver.exe", options=options)
CHROMEDRIVER = "/Volumes/Dropbox/Dropbox/study_work/webdriver/chromedriver"
from selenium.webdriver.chrome import service as fs
chrome_service = fs.Service(executable_path=CHROMEDRIVER)
import os
iDir = os.getcwd()
options = webdriver.ChromeOptions()
options.add_experimental_option("prefs", {"download.default_directory": iDir })
# ヘッドレスモード
options.add_argument('--headless')
# 「暫定的なフラグ」らしい。
options.add_argument('--disable-gpu')
# セキュリティ対策などのchromeに搭載してある保護機能をオフにする。
options.add_argument('--no-sandbox')
# ディスクのメモリスペースを使う。
options.add_argument('--disable-dev-shm-usage')
# リモートデバッグフラグを立てる。←これは✕
#options.add_argument('--remote-debugging-port=9222')
driver = webdriver.Chrome(service=chrome_service, options=options)
#ポップアップブロック機能の無効化
options.add_argument('--disable-popup-blocking')
# 最大の読み込み時間を設定
wait = WebDriverWait(driver=driver, timeout=30)
driver.implicitly_wait(30) # seconds# ページロードされるまでのタイムアウトを 5秒 に設定
driver.set_page_load_timeout(30)
#指定のWebサイトに移動
driver.get('https://www.google.com/?hl=ja')
# selenium.webdriver.support.ui の Select をimport
from selenium.webdriver.support.ui import Select
# selenium.webdriver.common.alert の Alert をimport
from selenium.webdriver.common.alert import Alert
#
from selenium.webdriver.common.by import By
"""""""""""""""
#キーワードと年代を入力
"""""""""""""""
key_word_list = sys.argv
key_word_list.pop(0)
key_word = " ".join(key_word_list)
print('key_word:', key_word)
element = driver.find_element(By.XPATH, "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[2]/input")
element.send_keys(key_word)
"""""""""""""""
#Google検索ボタンを押す
"""""""""""""""
element = driver.find_element(By.XPATH, "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[3]/center/input[1]")
element.click()
"""""""""""""""
#「ニュース」ボタンを押す
"""""""""""""""
element = driver.find_element(By.XPATH, "/html/body/div[7]/div/div[4]/div/div[1]/div/div[1]/div/div[2]/a")
element.click()
"""""""""""""""
#手続き(検索ページを遷移しながらタイトルとURLを収集)
"""""""""""""""
import requests
def text_collect(driver):
title_list = [] # タイトルを格納する空リストを用意
link_list = [] # URLを格納する空リストを用意
# ウィンドウハンドルを取得する
handle_array = driver.window_handles
# タイトルとURLを取得しながら検索ページの遷移
while 1:
# リンク('a href')とタイトル('h3')の入ったHTMLを抽出(クラス名で)→アプデで変わる可能性あり
class_group = driver.find_elements(By.CLASS_NAME, 'ftSUBd')
html = driver.page_source
# リンクとタイトルを抽出しリストに追加するforループ
for elem in class_group:
try:
# タイトル
title = elem.find_element(By.CLASS_NAME, 'mCBkyc').text
# リンク
link = elem.find_element(By.TAG_NAME, 'a').get_attribute('href')
except Exception as e:
#print(e)
continue
# 動画、画像、説明, 「他の人は〜」といった記事とは関係ないコンテンツを排除
if title != '動画' and title != '画像' and title != '説明':
if title != '':
# URLを指定して、新しいタブを開く# 新しいタブを作成する
driver.execute_script("window.open()")
# 新しいタブに切り替える
driver.switch_to.window(driver.window_handles[-1])
try:
alert = driver.switch_to_alert()
print(alert.text)
alert.accept()
except:
#print("no alert to accept")
pass
# 新しいタブでURLアクセス
try:
print("A")
print(link)
wait.until(EC.presence_of_all_elements_located)
print("AA")
except Exception as e:
#print(e)
continue
# 新しいタブでURLアクセス
try:
driver.get(link)
wait.until(EC.presence_of_all_elements_located)
print("AAAA")
except Exception as e:
#print(e)
continue
# 新しいタブでURLアクセス
try:
driver.refresh()
#wait.until(EC.presence_of_all_elements_located)
print("AAAAA")
except Exception as e:
#print(e)
continue
time.sleep(3)
#ページソースの取得
try:
print("BBB")
html = driver.page_source
wait.until(EC.presence_of_all_elements_located)
print("BBBBBB")
except Exception as e:
#print(e)
continue
print("CCC")
#BeautifulSoup形式で取得
soup = BeautifulSoup(html, 'html.parser')
#テキストのみを取得=タグは全部取る
text=soup.get_text()
# textを改行ごとにリストに入れて、リスト内の要素の前後の空白を削除
lines= [line.strip() for line in text.splitlines()]
# 【補足】ここはリスト内包表記です。書き下すと以下のことをやっています。
# lines=[]
# for line in text.splitlines():
#lines.append(line.strip())
#print(lines)
#リストの空白要素以外をすべて文字列に戻す
text="\n".join(line for line in lines if line)
print("CCCCCC")
#このリンクの解析結果を出力
title_list.append(title)
link_list.append(link)
print (title)
print (link)
print (text)
#time.sleep(5)
wait.until(EC.presence_of_all_elements_located)
driver.close()
#前のタブに切り替え
driver.switch_to.window(driver.window_handles[0])
# 次ページがあれば遷移する
try:
driver.find_elements(By.XPATH, ("//*[text()='次へ']"))
driver.find_element(By.XPATH, ("//*[text()='次へ']")).click()
time.sleep(3)
except Exception as e:
#print(e)
break
return title_list, link_list
"""""""""""""""
#text_collect(driver)
"""""""""""""""
titles, links = text_collect(driver)
#print(ranking(driver))
# タイトルリストをテキストに保存
with open('title.txt', mode='w', encoding='utf-8') as f:
f.write("\n".join(titles))
# URLリストをテキストに保存
with open('link.txt', mode='w', encoding='utf-8') as f:
f.write("\n".join(links))
# ブラウザを閉じる
time.sleep(3)
driver.quit()
例)
def greet
puts Hello World
end
自分で試したこと
$ python google_news_step-sample.py 環境
等を実行したものです(コードの中のコメントにある「年代」は気にしないでください)。