morikomorou’s blog

自分が学んだことなどの備忘録的なやつ

【python】スクレイピングで入手した情報をGoogleスプレッドシートに書き込んでみる


Googleニュースをスクレイピングして、Googleスプレッドシートに結果を書き出す方法について解説します。

はじめに

前回Googleニュースから情報を抜き出すスクレイピングというものを紹介しました。今回はそこで得た情報をスプレッドシートにためれるようにしたいと思います。

スクレイピングについては以下で行いました。

pythonでのスプレッドシートの操作は以下で実施しました。

今回はその集大成ということで、二つを組み合わせて自動でニュースの情報を集めてまとめておくシステムを作成していきたいと思います。




保存先のスプレッドシートのひな型を作る

まずはスクレイピングした情報を入れるスプレッドシートのひな型を作っておきましょう。カラム名を先に入力しておきます。せっかくpythonで作れるようになったのでpythonで作ります。

プログラムの構成としては、最初に保存したいスプレッドシートのキーを指定する変数を作っておき、そこがNoneなら新しくスプレッドシートを作成する形にします。あらかじめその変数にキーを入れておくと、そのキーに対応するスプレッドシートに追記できるようにしておきましょう。

また、検索したいキーワードごとにシートを分けておいて、それぞれのシートは検索したいキーワードにしておきましょう。

import gspread
import os

KEY = None # スプレッドシートのキー(既に作ってたらここに入れる)
KEY_WORD = ['機械学習', '仮想通貨 NFT'] # 検索キーワード

# スプレッドシート認証
dir_path = os.path.dirname(__file__)
gc = gspread.oauth(
                   credentials_filename=os.path.join(dir_path, "client_secret.json"),
                   authorized_user_filename=os.path.join(dir_path, "authorized_user.json"),
                   )

# スプレッドシートのKEYが入力されてないときは雛形を作成する
if KEY is None:
    data = ['Date', 'Title', 'Publisher', 'Link'] # カラム名
    wb = gc.create("Googleニュースまとめ") # 保存先のファイルを作成
    KEY = wb.id
    wb = gc.open_by_key(KEY)
    # ついでに検索したいキーワードごとにシートを作成しカラム名を入力しておく
    for i, word in enumerate(KEY_WORD):
        if i == 0:
            ws = wb.get_worksheet(0)
            ws.update_title(word)
        else:
            wb.add_worksheet(title=word, rows=50, cols=10)
            ws = wb.worksheet(word)

        # 複数行一括書き込み
        ws.append_row(data, value_input_option='USER_ENTERED')

無事作成できました。


あとは、前回やったコードの出力をここの各シートに入れるだけですね。

スクレイピング

前回のコードを関数にまとめて、出力をスプレッドシートにそのまま写せるように2次元配列リストで結果を出せるようにしておきます。

from bs4 import BeautifulSoup
import requests
import urllib.parse
import datetime

def get_news(key_word):
    key_word_encoded = urllib.parse.quote(key_word + ' when:1d')
    url = 'https://news.google.com/search?q={}&hl=ja&gl=JP&ceid=JP%3Aja'.format(key_word_encoded)

    res = requests.get(url) # urlにリクエストを送りレスポンスを取得
    res.encoding = res.apparent_encoding # エンコーディング
    html_text = res.text # レスポンスのテキスト情報

    soup = BeautifulSoup(html_text, 'html.parser') # html情報をBeautifulSoupで解析する
    articles = soup.find_all('article') # articleタグをすべて抜き出す
    base_url = 'https://news.google.com'
    print('今日の記事数{}個'.format(len(articles)))
    today = datetime.datetime.now().strftime('%Y/%m/%d')
    article_data = []
    for article in articles:
        txt = article.find('h3') # articleタグ内のh3タグを抜き出す
        txt = txt.find('a') # 上のh3タグ内のaタグを抜き出す
        source = article.find_all('div')[0] # articleタグ内の最初のdivタグを抜き出す
        source_name = source.find('a').text
        article_data.append([today, txt.text, source_name, base_url + txt.get('href')[1:]])
    return article_data

res = get_news('機械学習')
print(res)

結果は以下です。(長いので省略)

[['2023/05/08', 'KLabがAI・機械学習のゲーム開発・運営における活用事例を発表 研究機関との共同研究や他社への技術提供も推進', 'オーヴォ', 'https://news.google.com/articles/CBMiLmh0dHBzOi8vb3ZvLmt5b2RvLmNvLmpwL25ld3MvY3VsdHVyZS9hLTE4NjU4MDHSATJodHRwczovL292by5reW9kby5jby5qcC9uZXdzL2N1bHR1cmUvYS0xODY1ODAxL2FtcA?hl=ja&gl=JP&ceid=JP%3Aja'], 
...
['2023/05/08', '高齢期にむけた健康的な食事のタンパク質比率は25〜35%', '47NEWS', 'https://news.google.com/articles/CBMiK2h0dHBzOi8vd3d3LjQ3bmV3cy5qcC8tL3Byd2lyZS85Mjk2Mzc0Lmh0bWzSAQA?hl=ja&gl=JP&ceid=JP%3Aja']]

無事出力できてます。




スクレイピング結果をスプレッドシートに保存する

最後に結果をスプレッドシートに出力していきましょう。これまでのコードと一緒に全コード記載します。

import gspread
import os
import requests
import urllib.parse
import datetime
from bs4 import BeautifulSoup

KEY = None # スプレッドシートのキー(既に作ってたらここに入れる)
KEY_WORD = ['機械学習', '仮想通貨 NFT'] # 検索キーワード


def get_news(key_word):
    key_word_encoded = urllib.parse.quote(key_word + ' when:1d')
    url = 'https://news.google.com/search?q={}&hl=ja&gl=JP&ceid=JP%3Aja'.format(key_word_encoded)

    res = requests.get(url) # urlにリクエストを送りレスポンスを取得
    res.encoding = res.apparent_encoding # エンコーディング
    html_text = res.text # レスポンスのテキスト情報

    soup = BeautifulSoup(html_text, 'html.parser') # html情報をBeautifulSoupで解析する
    articles = soup.find_all('article') # articleタグをすべて抜き出す
    base_url = 'https://news.google.com'
    print('今日の記事数{}個'.format(len(articles)))
    today = datetime.datetime.now().strftime('%Y/%m/%d')
    article_data = []
    for article in articles:
        txt = article.find('h3') # articleタグ内のh3タグを抜き出す
        txt = txt.find('a') # 上のh3タグ内のaタグを抜き出す
        source = article.find_all('div')[0] # articleタグ内の最初のdivタグを抜き出す
        source_name = source.find('a').text
        article_data.append([today, txt.text, source_name, base_url + txt.get('href')[1:]])
    return article_data


# スプレッドシート認証
dir_path = os.path.dirname(__file__)
gc = gspread.oauth(
                   credentials_filename=os.path.join(dir_path, "client_secret.json"),
                   authorized_user_filename=os.path.join(dir_path, "authorized_user.json"),
                   )

# スプレッドシートのKEYが入力されてないときは雛形を作成する
if KEY is None:
    data = ['Date', 'Title', 'Publisher', 'Link'] # カラム名
    wb = gc.create("Googleニュースまとめ") # 保存先のファイルを作成
    KEY = wb.id
    wb = gc.open_by_key(KEY)
    # ついでに検索したいキーワードごとにシートを作成しカラム名を入力しておく
    for i, word in enumerate(KEY_WORD):
        if i == 0:
            ws = wb.get_worksheet(0)
            ws.update_title(word)
        else:
            wb.add_worksheet(title=word, rows=50, cols=10)
            ws = wb.worksheet(word)

        # 複数行一括書き込み
        ws.append_row(data, value_input_option='USER_ENTERED')

# スプレッドシートに書き込み
wb = gc.open_by_key(KEY)
for word in KEY_WORD:
    ws = wb.worksheet(word)
    res = get_news(word)
    ws.append_rows(res, value_input_option='USER_ENTERED')

結果は以下です。ほしい形で結果が得られて満足です。



おわりに

こんな感じでスプレッドシートなら何も考えずすぐ結果が確認できるし、DBでSQLゴリゴリ触らなくていいので便利ですね。

参考になった文献

様々な形式のサイトに使えるスクレイピング手法や、欲しいページまで自動的にサイトを辿っていってくれるクローラーの作成方法まで幅広く載っていて入門にオススメです!