Google検索結果ページをスクレイピング【Python x BeautifulSoup】

Google検索結果ページをスクレイピング【Python x BeautifulSoup】
Google検索結果ページをスクレイピング【Python x BeautifulSoup】

この記事では、PythonでGoogle検索結果をスクレイピングして、特定のサイトの検索キーワードに対する検索順位の抽出を行います。また、簡単にスクレイピングを可能とするBeautifulSoupの使い方を説明します。

▼ Pythonを使うのがはじめてな方は、こちらの書籍で基本的な使い方を学んでおくと良いでしょう。

▼ こちらの本は、Beautiful Soup4のクローリングをはじめ、pandasやmatplot、OpenPyXLなどを使ってデータ解析までを解説したスクレイピングの書籍となります。分かりやすくておすすめです!

スクレイピングとは

スクレイピングとは
スクレイピングとは

スクレイピングとは、英語のscrapingで「こすること」「削ること」の意味があります。Webでスクレイピングといった場合は、Webサイトの状態をかき集め(クローリング)、その中から必要なデータを抽出(スクレイピング)することになります。

Pythonでは、Webスクレイピングを簡単に行えるようにしてくれるツールのひとつに、BeautifulSoupというライブラリがあります。BeautifulSoupを使ってWebスクレイピングを行うには、次の流れで作業していきます。

  1. urllibでスクレイピングしたいサイトのHTMLをダウンロードする
  2. BeautifulsoupでHTMLをパースしてオブジェクト化する
  3. Beautifulsoupで目的のデータを抽出する

それでは、さっそくBeautifulSoupをインストールし、BeautifulSoupの簡単な使い方を説明していきます。

BeautifulSoupのインストール

まずは、BeautifulSoupをpipでインストールします。この記事では、Python3を使用しますのでpip3でインストールしました。BeautifulSoup最新版はbeautifulsoup4ですので、次のようにしてインストールします。

サイトタイトルを抽出してみよう

まずは大雑把なイメージをつかむために、適当なサイトをスクレイピングして、titleタグの文字を抽出してみましょう。

a.py
import urllib.request
from bs4 import BeautifulSoup

url = "https://101010.fun/posts/world-ios-android-share-2021.html"
req = urllib.request.Request(url)

with urllib.request.urlopen(req) as res:
    html = res.read()
    soup = BeautifulSoup(html, 'html.parser')
    title = soup.find('title').get_text()
    print(title)

BeautifulSoupを使うことで、このように驚くほど簡単にtitleタグの文字を抽出できました。それでは、BeautifulSoupの使い方をもう少し詳しくみていきましょう。

BeautifulSoupの使い方

BeautifulSoupの使い方を説明します。

HTMLをオブジェクト化(パースパースツリー)

urlib などでHTMLファイルをダウンロードしたら、BeautifulSoupでパースパースツリーを作成しオブジェクト化します。
py
soup = BeautifulSoup(html, 'html.parser')

この soup オブジェクトを使って必要なタグを検索、抽出していきます。

特定のタグを見つける

たとえば、パースパースツリーの中からaタグを検索したい場合は、soup.find_all('a')のようにします。もし、aタグが見つかれば、返り値としてその結果が配列で返されます。

py
for a_tag in soup.find_all('a'):
    h2 = a_tag.select("h2")
    if len(h2) > 0:
        print(h2.get_text())

この例は、aタグの子要素のh2タグのテキストにアクセスしてます。

属性の値を取得

a タグの href 属性の値を取得したい場合は次のようにします。
py
for a in soup.find_all('a'):
    href = a.get('href')

CSSクラスへアクセス

py
soup.find_all("a", class_="hoge")

親要素へアクセス

parent で親要素へ parents で複数の親要素へアクセスできます。
py
parent = h2.parent
print(parent.get_text())

兄弟要素へアクセス

next_siblingprevious_sibling で兄弟要素の前後へアクセスできます。
py
next_sibling = h2.next_sibling
print(next_sibling.get_text())

previous_sibling = h2.previous_sibling
print(previous_sibling.get_text())

パースパースツリーを変更する

BeautifulSoupでは、パースパースツリーの変更もできます。

py
soup = BeautifulSoup("<a>Hoge</a>")
soup.a.append("Fuga")

aタグのテキストはHogeFugaとなります。

▼ BeautifulSoupについてより詳しく知りたい方はこちら。 kondou.com - Beautiful Soup 4.2.0 Doc. 日本語訳 (2013-11-19最終更新)

▼ また、pandasやOpenPyXL、twintなどを使ったスクレイピング関連の記事も書いてます。

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

それでは、BeautifulSoupを使ってGoogle検索結果をスクレイピングしてみましょう。次の手順でプログラムを組んで、検索キーワードに対する指定サイトの検索順位を抽出してみます。

  1. urllibで検索結果のHTMLをダウンロード
  2. HTMLをBeautifulSoupでパースツリー化
  3. 特定のURLが検索結果に含まれているかチェックしり
  4. 検索結果に見つからなければ最大5ページまで手順を繰り返す

以上の仕様で作ってみたプログラムがこちらとなります。

Pythonプログラム

google.py
# Created by Toshihiko Arai.
# https://101010.fun/programming/python-beautifulsoup-googlerank.html

import urllib.request
from urllib.parse import quote
from bs4 import BeautifulSoup
import time

keyword = 'ios android シェア'
target = 'https://101010.fun/posts/world-ios-android-share-part1.html'
user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"

def get_search_html(keyword, page):
    start = "&start=" + str(page * 10) # 次ページstart=10
    url = 'https://www.google.com/search?q=' + quote(keyword) + start 
    
    headers = {'User-Agent': user_agent}
    req = urllib.request.Request(url, headers=headers)

    with urllib.request.urlopen(req) as res:
        body = res.read()
        return body

def get_page_rank(soup, page):
    res_rank = 1

    for a_tag in soup.find_all('a'):
        h3_tag = a_tag.select("h3")

        if len(h3_tag) > 0:
            if a_tag.get('href').startswith(target) == True:
                # print(h3_tag[0].get_text())
                # print(a_tag.get('href'))
                return res_rank + page * 10

            res_rank += 1
    return -1

rank = -1
max_page = 5

for page in range(max_page):
    html = get_search_html(keyword, page)
    soup = BeautifulSoup(html, 'html.parser')

    title_text = soup.find('title').get_text()
    print(title_text)
    rank = get_page_rank(soup, page)

    page += 1
    if rank != -1:
        break

    time.sleep(3) # アクセス制限対策
    
if rank != -1:
    print("順位: {}位".format(rank))
else:
    print("見つかりませんでした")

もし、検索結果に対象ページが含まれていれば、次のようなに検索順位が標準出力されるでしょう。

ios android シェア - Google 検索
順位: 2位

プログラム中の検索キーワードや対象ページのURLを変更して、いろいろ試してみてください。このプログラムをさらに改造すれば、Rank TrackerのうようなSEOツールが作れるでしょう。そのためには、検索キーワードを別ファイルで管理したり、実行結果をエクセルへ書き出したりすれば良いです。ぜひご活用ください。

関連記事

 
最後までご覧いただきありがとうございます!

▼ 記事に関するご質問やお仕事のご相談は以下よりお願いいたします。
お問い合わせフォーム

Python学習にオススメの本をご紹介!
Pandasでデータサイエンスはじめよう!
スクレイピングにオススメの書籍

▼ Beautiful Soup4を使ったWebクローリングをはじめ、表データをpandasやOpenPyXL、matplotでデータ解析、グラフ表示などのスクレイピングのやり方が分かりやすく説明されてます。図解が多いのでPython初心者の方でも読み進められる内容となってます。

関連記事