頑張らないために頑張る

ゆるく頑張ります

PythonでExcelファイルのキーワードを参照して自動的にGoogle検索し結果を保存する

Posted at — Nov 22, 2019

職場からExcelが駆逐される日は来るのだろうか

Excel

いいアプリケーションだと思います。実力に裏打ちされた歴史もあるしね。とはいえ、こと日本においては単なる表計算ソフトに留まらず、エゲツない「1セルにつき1文字」という縛りでDTPの真似事までやらされる姿を見るに、個人的には落涙を禁じえません。「ネ申Excel」なんていう話もあるわけで、日本のExcelがいわれのない誹りを受けずに本来の表計算作業を全うする日は来るのか、という思いを抱かずにはいられません。

また、前述のようなリッチな使い方とはまったく逆のベクトルで利用されることがあります。何はなくとも「とりあえずExcelファイルでやります」とExcelを立ち上げるケースです。今日も、テキストファイルでいいのにわざわざExcelファイルに箇条書きする、サラリーマンの姿がどこかで見られるかもしれません。そしてそのExcelファイルを送り付けられて、しかもいろんな情報までてんこ盛りだったりすると、「何この・・・何・・・?」などと口走りながらエンジニアが頭を抱えることになるでしょう。「テキストでいいじゃん」って言いたいところなのですが、相手側にはその発想がそもそもないわけです。

となれば

ExcelファイルをそのままCSVなどのテキスト形式にエクスポートすればいいわけです。文字列だとダブルクォーテーションが付与されたりだとか、いろいろExcelが余計なことをしてくれるかもしれませんが、とりあえずテキストまで落とせればどうにでもなります。

ところが必要な情報が一部の列だけで他は必要ない、という場合にはテキストファイルにエクスポートしたせいで却って利用しにくくなってしまう場合もあります。たとえば下記のような感じ。

pic

いくつかある列のうち、「項目名」の列に含まれる値のみを利用するとしましょう。テキスト出力した場合、CSVならカンマで各項目が区切られているので、カンマでsplitして必要な要素だけ利用する、という方法も可能です。この場合では各行を最初の要素のみを参照し、他のデータは捨てる、という処理をループするわけです。ですが、それなら最初からExcelファイルの必要な列だけを参照すればいいんじゃね?という気がします。「読み込むだけは読むけど使わない」なら、最初から読み込まなければいいわけですから。

というわけで実現したい内容を

送り付けられたExcelファイルの必要な部分だけを参照しつつ、ついでに別の処理を行うこととしましょう。とりあえず下記のようなことを要求されていると仮定します。

こんなところでしょうか。

なお、検索結果について解析したりアクセスしその内容を取得するのは、Beautiful SoupScrapyなどを用いて検索結果を解析する必要があります。ここではそこまでは要求されていない、として割愛します。

また、数字が格納されている特定の列に対して何かしらの計算を行いたい場合も、Excelファイルを読み込む処理までは同様に考えることができます。読み込んで値を参照しながら、行いたい計算をPythonで記述すればいいわけです。

環境

結論から

こんなソースを書きました。

import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import xlwings as xw


# 時間計測
start = time.time()

options = Options()
# options.add_argument('--headless')

# ChromeのWebDriverオブジェクトを作成(ヘッドレスモードの場合)
# ノーヘッドレスの場合は引数なしで実行する
driver = webdriver.Chrome(chrome_options=options)

driver.command_executor._commands["send_command"] = (
    "POST",
    '/session/$sessionId/chromium/send_command'
)
params = {
    'cmd': 'Page.setDownloadBehavior',
    'params': {
        'behavior': 'allow'
    }
}


def getCorpName():
    b = xw.Book(r"C:\\app\\input.xlsx")
    sh = b.sheets(1)
    return sh.range((5, 1), (sh.range(5, 1).end("down").row, 1)).value


names = getCorpName()
# キーワード順を逆転させたい場合はreverse()
# names.reverse()

# 保存先ファイル
filepath = r"C:\\app\\searchresult.txt"

# 追加キーワードがあれば
add_words = ["由来", "使い方"]
if len(add_words) > 0:
    add_words.insert(0, "")

words = " ".join(add_words)

with open(filepath, mode="w", encoding="utf-8") as f:
    for name in names:
        url = "https://www.google.com/search?q={}&safe=off".format(name + words)
        driver.get(url)
        time.sleep(2)

        elem_titles = driver.find_elements_by_class_name("LC20lb")
        elem_details = driver.find_elements_by_class_name("st")

        for title, detail in zip(elem_titles, elem_details):

            f.write(title.text + "\n")
            f.write(detail.text + "\n")

            f.write("=====================================" + "\n")

print("処理時間: " + str(time.time() - start))
driver.quit()

上記のExcelファイルを入力にした場合、実行結果であるテキストファイルには下記のように出力されます。

「バズる」の意味や使い方 Weblio辞書
Weblio辞書では「バズる」の意味や使い方、用例、類似表現などを解説しています。 ... バズる」の由来は英語の動詞 buzz を日本語化した語と捉えられる。語尾「る」を活用することで「バズっている」「バズった」という風に文脈に応じた使い方ができる。 バズる話題 ...
=====================================
ネット用語「バズる」の意味とその由来を解説!「バズった」とは ...
バズる」の使い方 に移動 - 「バズる」はネット上で急に話題になり、注目を集めている状態を意味します。 ネット上で宣伝活動をしている担当者にとっては、自社の商品やサービスを意図的に「バズらせる」ことが業務の目的であり、「バズった」ら ...
=====================================
・・・(以下省略)

大したことはやっていないのですが、少し補足したいともいます。

補足

Headlessモードにはしていない

以前の記事において「HeadlessモードのChromeでは検索結果が正常に取得できなかった」ことを書きましたが、相変わらず今回も同様だったのでHeadlessモードを外してあります。

Excelファイルの読み込み

Excelファイルの読み込みはxlwingsを利用しています。そして抽出したいセルの領域を指定しています。

def getCorpName():
    b = xw.Book(r"C:\\app\\input.xlsx")
    sh = b.sheets(1)
    return sh.range((5, 1), (sh.range(5, 1).end("down").row, 1)).value

上記の例では、A列の5行目からデータが複数件あり、空のデータは存在しないという前提です。空データがあるとend()が正常に動作しないからです。

検索結果の取得

        elem_titles = driver.find_elements_by_class_name("LC20lb")
        elem_details = driver.find_elements_by_class_name("st")

この部分で得られる情報には、実際のテキスト以外にもタグなどの余計な情報を含まれています。そのため、次のループ文においてtitle.textなどとし、テキストのみを出力しています。

まとめ

Excelくんは悪くないよ・・・。

まぁ、使い方が悪いのだよね。ビールよろしく「とりあえずExcel」のように、何でもかんでもExcelでどうにかしようとする文化はなくなってほしいものです。

comments powered by Disqus