Python3 で音声認識 & Google画像スクレイピング

column B3 Python

初めまして。B3の名執と申します。Python 初心者です。

今回作成したプログラムは、自分の話した単語を認識させ、その単語でGoogle画像検索を行なって、検索画像を自動で保存するというものです。

目次

  1. 概要
  2. プログラムの構造
  3. 実行環境
  4. 手順
  5. ソースコード
  6. 実行例
  7. おわりに
  8. 参考文献

概要

純粋に画像スクレイピングを行いたいのであれば、音声認識をわざわざするのではなく直接 CUI でも GUI でも文字を入力した方が早いのですが、Python の練習のために音声認識を取り入れました。

下記に示すソースコードをコピペすれば少しパスを変更するだけで動くと思いますが、そのためにはかなりの数のライブラリをインストールする必要があります。

なお、今回はお試しでこのプログラムを作りましたが、実際に大規模な画像スクレイピングを実施する場合には、著作権やサーバへの負担を考慮する必要があります。


プログラムの構造

作成したプログラムは、簡単に書くとこの二段構成です。

  • PyAudio を利用して、Speech Recognition で音声認識
  • webdriver で Chrome を開いて画像検索と保存

ライブラリの細かい仕様等はこの記事では省かせていただきます。


実行環境

私の実行環境を以下に示します。なお、正しく動作することを確認しているのは 2021/11/16 現在です。

  • PC
    • iMac (Retina 5K, 27-inch, 2020)
    • OS: macOS Big Sur ver 11.6
    • Processor: 3.8 GHz 8-Core Intel Core i7
    • Memory: 16 GB 2667 MHz DDR4
  • Python
    • Python 3.9.7
  • Chrome
    • Version 95.0.4638.69

手順

上記の通り、プログラムをコピペすれば基本的には動きますが、ライブラリのインストールがかなり必要です。

1. Speech Recognition のインストール

音声を認識してくれるモジュールである、Speech Recognition をインストールします。

$ pip install SpeechRecognition
$ pip install pyaudio

エラーが吐かれたら、macにpyaudioをインストールできない時 [1] の記事を参考にしてください。portaudioがないと、うまくいかないと思います。 私もこちらで解決したのですが、brew update にはかなりの時間がかかります。

2. ChromeDriver のインストール

次に、自動的に Chrome をいじれるよう Chrome の Driver をインストールします。現在使っている Chrome のバージョンを確認して、そのバージョンに合ったドライバーを ChromeDriver - Downloads [2] からインストールしてください。

3. パスの指定とディレクトリの作成

下記に示すソースコード中には、先ほどインストールしたドライバーのパスを指定する部分があります。そこに、ドライバーがあるパスを指定するようにしてください。

WEB_DRIVER_PATH = '/ここにパスをいれてください/chromedriver'

次に、ソースコードがあるディレクトリの直下に "data" という名前のディレクトリを作成してください。これは、画像検索して出てきた画像を保存するディレクトリです。

4. 実行する前に

以上で、大まかな準備は完了です。あとは実際にコードを実行すれば、間違いなくエラーが吐かれると思うので、それを一つ一つ潰すことになります。

ただ、基本的にはライブラリがないよって返されるものがほとんどだと思うので、その場合は以下でインストールしてください。

$ pip install ライブラリ名

ソースコード

#coding:utf-8

import speech_recognition as sr
from datetime import datetime
import os
import time
from selenium import webdriver
from PIL import Image
import io
import requests
import hashlib

# クリックなど動作後に待つ時間(秒) [default = 2]
sleep_between_interactions = 1
# 検索したい回数
count = 1
# ダウンロードする枚数
download_num = 3
# 画像検索用のurl
search_url = "https://www.google.com/search?safe=off&site=&tbm=isch&source=hp&q={q}&oq={q}&gs_l=img"

### 要変更 ###
# webdriverのpathを指定
WEB_DRIVER_PATH = '/ここにパスをいれてください/chromedriver'

# filename = 現在の時刻
filename = datetime.now().strftime('%Y%m%d_%H:%M:%S')
txt =filename +".txt"

r = sr.Recognizer()
mic = sr.Microphone()

# count に代入した数分だけ実行
while count > 0:
    print("\nSay something ...\n")

    with mic as source:
        r.adjust_for_ambient_noise(source) #雑音対策
        audio = r.listen(source)

    print ("Now recognizing ...\n")

    try:
        # 検索ワード
        query = r.recognize_google(audio, language='ja-JP')
        # 話しかけた単語を表示
        print("Searching word = [ " + query + " ]" + '\n')
        print("end\n")

        # サムネイル画像のURL取得
        wd = webdriver.Chrome(executable_path=WEB_DRIVER_PATH)
        wd.get(search_url.format(q=query))
        # サムネイル画像のリンクを取得
        thumbnail_results = wd.find_elements_by_css_selector("img.rg_i")

        # サムネイルをクリックして、各画像URLを取得
        image_urls = set()
        for img in thumbnail_results[:download_num]:
            try:
                img.click()
                time.sleep(sleep_between_interactions)
            except Exception:
                continue
            # 一発でurlを取得できないので、候補を出してから絞り込む
            # 'n3VNCb'は変更されることあるので、クリックした画像のエレメントをみて適宜変更する
            url_candidates = wd.find_elements_by_class_name('n3VNCb')
            for candidate in url_candidates:
                url = candidate.get_attribute('src')
                if url and 'https' in url:
                    image_urls.add(url)
        # 正常終了のための待ち
        time.sleep(sleep_between_interactions)
        wd.quit()

        # 画像のダウンロード [このファイルと同じディレクトリ下にdataフォルダを用意しておく]
        image_save_folder_path = 'data'
        for url in image_urls:
            try:
                image_content = requests.get(url).content
            except Exception as e:
                print(f"ERROR - Could not download {url} - {e}")

            try:
                image_file = io.BytesIO(image_content)
                image = Image.open(image_file).convert('RGB')
                file_path = os.path.join(image_save_folder_path,hashlib.sha1(image_content).hexdigest()[:10] + '.jpg')
                with open(file_path, 'wb') as f:
                    image.save(f, "JPEG", quality=90)
                print(f"SUCCESS - saved {url} - as {file_path}")
            except Exception as e:
                 print(f"ERROR - Could not save {url} - {e}")
        f = open(txt,'a')
        f.write(filename + "\n") #最初の一行目にはfilenameを記載する
        f.write(r.recognize_google(audio, language='ja-JP')) #二行目に検索単語を記載する

        count = count-1

    # 以下は認識できなかったときに止まらないように
    except sr.UnknownValueError:
        print("could not understand audio")
    except sr.RequestError as e:
        print("Could not request results from Google Speech Recognition service; {0}".format(e))

実行例

実際に実行すると、このような感じです。


// マイクに向かって、「電気通信大学 りさじゅう」と話しかけています

// アスキーアートは遊びで入れているので、ソースコードには入れていません


おわりに

画像スクレイピングはブラウザのAPIが変わってしまうとコードの改良が必要になってしまうので、貼り付けただけで動くというケースはめったにありません。このプログラムを作るために色々なサイトを調べて試したのですが、うまく動くまでに相当な時間がかかりました。参考にさせていただいた記事を見ればわかると思いますが、作成したプログラムの多くは、コピペさせていただいてそれを組み合わせています。先人の皆様に感謝です。

今回の練習を通して、Python への理解が深まりました。色々なライブラリがある分、どれを使ったら効率が良いのか、どれとどれが相性が良いのか、考える必要があって難しいですが、実際に自分の手を動かして作りたいものを作れた時の達成感は、得難いものだと思います。


参考文献

今回のプログラムの作成にあたり、[3] [4] の記事を特に参考にさせていただきました。ありがとうございます。

[1] 「macにpyaudioをインストールできない時」, Qiita, 2018年5月20日更新, 最終閲覧日:2021年11月16日, https://qiita.com/nyancook/items/ebc0afd535210f487f47

[2] 「ChromeDriver - Downloads」, 最終閲覧日:2021年11月16日, https://chromedriver.chromium.org/downloads

[3] 「SpeechRecognitionを使って音声入力からテキスト化する自動議事録を作ってみた」, Qiita, 2019年9月14日更新, 最終閲覧日:2021年11月16日, https://qiita.com/daiarg/items/ff1b9f91d0804e6a8f18

[4] 「Google画像検索の画像をオリジナルサイズで取得する」, Qiita, 2020年4月1日更新, 最終閲覧日:2021年11月16日, https://qiita.com/maruman029/items/8dc7f8190d0e3f892d99

[5] 「Pythonで音声からテキストへ変換【SpeechRecognition】」ジコログ, 最終閲覧日:2021年11月16日, https://self-development.info/python%E3%81%A7%E9%9F%B3%E5%A3%B0%E3%81%8B%E3%82%89%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%B8%E5%A4%89%E6%8F%9B%E3%80%90speechrecognition%E3%80%91/

Previous Post Next Post