質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

Q&A

解決済

1回答

4593閲覧

PythonでGoogleスプレッドシートの更新をまとめて短時間で行いたい

kazukichi

総合スコア12

Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

selenium

Selenium(セレニウム)は、ブラウザをプログラムで作動させるフレームワークです。この原理を使うことにより、ブラウザのユーザーテストなどを自動化にすることができます。

0グッド

1クリップ

投稿2019/05/20 16:54

環境

Python 3.7.2
gspread 3.1.0
oauth2client 4.1.3

実現したいこと

pythonを使用してGoogleスプレッドシートの更新を「1セルごと、1行ごと」ではなく「全ての行もしくは(例)100行毎」のように行いたい

行っていること現状・問題点

①スプレッドシートの指定した列すべての情報を取得し
②①の一行ごと(セル)にあるURLを使用してページ解析を行い
③データをセルに格納して行く
※for文で1セルごとに更新を行っているため途中「HTTP ERROR 500」のエラーなどで処理が止まってしまう
※データは3000件以上

データと現状ソース

※未熟者ですので何卒ご了承ください。
イメージ説明

#chrome ディレクトリ driver = webdriver.Chrome(chrome_options=opt,executable_path=r"クロームドライバー/chromedriver.exe") scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive'] credentials = ServiceAccountCredentials.from_json_keyfile_name('キーファイル.json', scope) gc = gspread.authorize(credentials) wks = gc.open('スプレッドシートファイル名').worksheet("シート3") list_of_lists = wks.col_values(2) list_of_check = wks.col_values(8) timesleep = 0 listnum = 1 for url in list_of_lists: try: #処理済みのものはパス if "check" == list_of_check[listnum-1]: listnum += 1 continue except: pass if "サイトURL" in url: #ブラウザオープン driver.get(url) time.sleep(2) vall = "" try: #リダイレクトされた場合 driver.find_element_by_xpath('//*[@id="asdfasfa"]/span').text except: vall = "none" try: #完売しているとき if "完売" == driver.find_elements_by_xpath('//*[@id="asdfasdf"]/h3')[0].text: vall = "完売だよ" except: pass try: #残り僅かの時 if "残り僅か" == driver.find_elements_by_xpath('//*[@id="asdfasdfa"]/span[2]')[0].text: vall = "残り僅かだよ" except: pass if vall != "": #セル更新① 「状態フラグ」 wks.update_acell('G'+str(listnum), vall) time.sleep(3) #セル更新② 「チェック済みフラグ」 wks.update_acell('H'+str(listnum), "check") time.sleep(3) listnum += 1 driver.quit()

やりたいこと(参考サイト) + 分からないこと

KISSE様のサイトを参考「Python gspread 処理が遅いと感じたらチェックすること」

↑こちらのように全て取得しまとめて更新を行いたいのですが
参考サイトから:workspace.update_cells(cell_list)

cell_list内にどう格納していけばいいか分からず迷走しております。
ご教授のほどお願いいたします。

全て取得は「wks.get_all_values()」が一番手っ取り早いかなと思っております。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

以下のような流れでどうでしょう。
スクレイピング実行結果は一時格納リストに入れておき、最後に一気に更新するかたちになります。

Python

1# 略 2list_of_lists = wks.col_values(2) 3list_of_check = wks.col_values(8) 4 5# 更新対象セルを取得 6ROWS = len(list_of_lists) 7cellG = wks.range(1,7,ROWS,7) # 状態フラグ 8cellH = wks.range(1,8,ROWS,8) # チェック済みフラグ 9 10# 実行結果を一時格納するリストを用意 11listG = [''] * ROWS 12listH = [''] * ROWS 13 14timesleep = 0 15listnum = 1 16for url in list_of_lists: 17 # 略 18 if "サイトURL" in url: 19 # 略 20 if vall != "": 21 #セル更新① 「状態フラグ」 22 listG[listnum-1] = vall 23 time.sleep(3) 24 25 #セル更新② 「チェック済みフラグ」 26 listH[listnum-1] = 'check' 27 time.sleep(3) 28 # 略 29 30# 一時格納データをセルに反映 31for cG,cH,lG,lH in zip(cellG, cellH, listG, listH): 32 cG.value = lG 33 cH.value = lH 34 35# ワークシートに反映 36wks.update_cells(cellG) 37wks.update_cells(cellH)

投稿2019/05/21 02:39

can110

総合スコア38256

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kazukichi

2019/05/22 14:08

ありがとうございます。 おかげさまでまとめて更新ができました! ただやはりスクレイピング回数が多くなりすぎると途中サーバーから拒絶されることが多々あり 最後までできたことがありません(3000件の場合)100件の場合成功してます。 Googleスプレッドシートを使って100件毎ずつ更新するということは出来るのでしょうか?
can110

2019/05/22 14:19

拒絶されるのはスクレイピング対象サーバでしょうか? であれば待機間隔を伸ばす&リトライ繰り返してみではどうでしょうか。 100件程度しかどうしてもスクレイピングできないのであれば、全体の処理をバッチ的に100件ずつ小分けに処理するしかないかと思います。
kazukichi

2019/05/23 09:55

説明不足で申し訳ありません。 拒絶ではなくよく確認してみるとgoogle api 関係のものでした。 認証、、トークンと読めるのですが、、大変お手数ではありますがご教授いただけると幸いです。 APIError: { "error": { "code": 401, "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.", "status": "UNAUTHENTICATED" } }
can110

2019/05/23 10:23

「未承認」と読めますね。 同様のケースにあったことがないのでちょっと原因、理由は分かりません…
kazukichi

2019/05/23 13:01

わかりました。 ご丁寧にありがとうございまいた。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問