techno_memo

個人用の技術メモ。python・ROS・AI系のソフトウェア・ツールなどの情報を記載

Webサイトからのデータ取得 ①Google系Webサービスのデータ取得(サイト検索・画像検索・Youtube検索)

やりたいこと

 pythonで下記のGoogleWebサービスの結果を自動取得する

  • Gooogle検索 (キーワードにヒットした検索結果のタイトル、リンク一覧)

  • Google画像検索 (キーワードにヒットした検索結果の画像ファイル)

  • Youtube動画検索 (キーワードにヒットした検索結果の動画ファイル)

f:id:sd08419ttic:20190227004611p:plain

Google検索(キーワードにヒットした検索結果のタイトル、リンク一覧)

実装手順

①requestsライブラリでgoogleに検索を要求し、結果を取得

②Beautifulsoupライブラリでタイトル・リンクを抽出

③日本語エンコード変換に注意しつつ結果をpandas dataframeに保存

※検索結果の説明文も取得することは可能だが、タイトルと紐づけて取得するのが難しかった (リンクだけ表示されるものがある)ので省略

    def Get_GoogleWebSearch_Result(self,keyword,num=100):
        '''
        GoogleWeb検索結果と説明文の取得
        '''
        result_df = pd.DataFrame(columns=['Title','Link'] )
        title_list = []
        link_list = []

        print("Loading...")
        res = requests.get("https://google.com/search?num="+str(num)+"&q=" + " ".join(keyword))
        res.encoding = res.apparent_encoding
        res.raise_for_status()
 
        # 上位の検索結果のリンクを取得する
        soup = BeautifulSoup(res.content, "lxml")
        link_elems = soup.select('.r > a')         #タイトル・リンク
        link_elems2 = soup.select('.s > .st')      #説明文 (タイトル・リンクと一緒に表示させたかったがずれるので取得のみ)
 
        # 各結果をブラウザのタブで開く
        num_open = min(100, len(link_elems2))
        for i in range(num_open):
             tex_temp = link_elems[i].get_text()    #タイトル文字列の処理
             try:
                print(tex_temp)
             except:    #機種依存文字を含む場合はエンコード可能な文字だけを出力
                tex_temp = tex_temp.encode('cp932',"ignore")
                tex_temp = tex_temp.decode('cp932')
                print(tex_temp)

             link_temp = "https://google.com" + link_elems[i].get("href")
        
             #結果への追加
             title_list.append(tex_temp)
             link_list.append(link_temp)
             #tex_temp2 = link_elems2[i].get_text() #説明文の保存 (タイトル・リンクと一緒に表示させたかったがずれるので取得のみ)
             #try:
             #   print(tex_temp2)
             #except:    #機種依存文字を含む場合はエンコード可能な文字だけを出力
             #   tex_temp2 = tex_temp2.encode('cp932',"ignore")
             #   tex_temp2 = tex_temp2.decode('cp932')
             #   print(tex_temp2)
             #webbrowser.open("https://google.com" + link_elems[i].get("href"))

        result_df['Title'] = pd.Series(title_list)
        result_df['Link'] = pd.Series(link_list)

        return result_df

Google画像検索 (キーワードにヒットした検索結果の画像ファイル)

実装手順

①画像保存先ディレクトリの存在を確認し、すでにある場合はツリーごと削除(自動でリネーム保存されるため)

google_images_downloadライブラリで画像検索結果をフォルダに保存

    def Get_GoogleImageSearch_Result(self,keyword,imnum=100):
        '''
        Google画像検索結果の取得 (取得した画像は実行ファイルと同じ階層のdownloadフォルダに検索ワードのフォルダを作って保存)
        '''
        imnum = int(min(99,imnum))   #100以上の場合はchrome driverの設定が必要
        target_dir =os.path.dirname(os.path.abspath(__file__))+"/downloads/"+keyword
        if os.path.exists(target_dir):
            shutil.rmtree(target_dir)

        response = google_images_download.googleimagesdownload()
        arguments = {"keywords":keyword,"limit":imnum,"la":"Japanese","pr":"test"}   #creating list of arguments
        response.download(arguments)
        return

Youtube動画検索 (キーワードにヒットした検索結果の動画ファイル)

実装手順

①requestsライブラリでYoutubeに検索を要求し、結果を取得

②Beautifulsoupライブラリでタイトル・リンクを抽出

※①②については下記記載の参考リンクにある処理を転用させていただきました

③pytubeライブラリで取得したリンクから動画をmp4形式でダウンロード

※動画形式によっては失敗する場合がある。成功したものだけを取得する。

    def Get_YoutubeSearch_Result(self,keyword,imnum=20):
        '''
        Youtube検索結果の取得 (取得した画像は実行ファイルと同じ階層のmovieフォルダに検索ワードのフォルダを作って保存)
        '''
        imnum = int(min(20,imnum))
        contents = list(Youtube.search(keyword, num=imnum))

        target_dir =os.path.dirname(os.path.abspath(__file__))+'/movie/'+keyword+"/"
        if os.path.exists(target_dir):
            shutil.rmtree(target_dir)
        os.makedirs(target_dir)

        for indx in range(len(contents)):
            tex_title = contents[indx].title.encode('cp932',"ignore")
            tex_title = tex_title.decode('cp932')
            print(tex_title)
            try:
                yt = YouTube(contents[indx].url)
                stream = yt.streams.get_by_itag(22) #MP4動画(720p)は22/ MP4音楽:140 失敗する動画はyt.streams.all()で表示後個別調整すれば取得可能
                stream.download(target_dir)
            except:
                print("error")
        return

実装済ソースコード

github.com

参考サイト

Google検索結果のスクレイピング

su-gi-rx.com

Google画像検索の取得ライブラリ Google-images-download

github.com

Youtube検索結果のスクレイピング方法

qiita.com

Youtube動画ダウンロードライブラリ Pytube

github.com