PythonでOGPを確実に取得する方法を解説【スクレイピング】

PythonでOGPを確実に取得する方法を解説【スクレイピング】 プログラミング

PythonでOGPを取得する方法を検証しました。
結論から言うと、Seleniumによるスクレイピングが最強でした。

本記事の内容

  • OGPを取得する方法一覧
  • ogp
  • PyOpenGraph
  • py-ogp-parser
  • Seleniumによるスクレイピング

それでは、上記に沿って解説していきます。

OGPを取得する方法一覧

OGPを取得する方法を4つ検証しました。

  • ogp
  • PyOpenGraph
  • py-ogp-parser
  • Seleniumによるスクレイピング

上の3つは、Pythonのライブラリです。
最後の1つは、自分でスクレイピングするという方法です。
「自分で」と言っても、Seleniumなどのライブラリは利用します。

検証する環境について、説明しておきます。
Pythonのバージョンは、現時点(2021年4月末)における最新のPythonです。

>python -V
Python 3.9.4

OSは、Windows 10を利用します。
しかし、LinuxでもmacOSでもそれほど違いはないでしょう。

では、一つづつOGPを取得する方法を検証していきましょう。
最初は、ogpというそのまんまの名前であるライブラリです。

ogp

結論から言うと、使えません。

ogp PyPlページ
https://pypi.org/project/ogp/

検索で真っ先にヒットしたライブラリです。
最新版は、0.9.1となります。

この0.9.1は、2012年8月2日に公開されています。
全くメンテナンスされていません。

あまり期待せずに、インストールしてみます。

pip install ogp

上記を実行すると、途中でエラーとなります。

ERROR: Cannot install ogp==0.8, ogp==0.9 and ogp==0.9.1 because these package versions have conflicting dependencies.

The conflict is caused by:
    ogp 0.9.1 depends on BeautifulSoup
    ogp 0.9 depends on BeautifulSoup
    ogp 0.8 depends on BeautifulSoup

To fix this you could try to:
1. loosen the range of package versions you've specified
2. remove package versions to allow pip attempt to solve the dependency conflict

ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/user_guide/#fixing-conflicting-dependencies

依存するBeautifulSoupのバージョンで問題が発生しているようです。
詳細は、追いかけません。

そもそも、古すぎてアウトということで十分です。
では、次はPyOpenGraphを検証します。

PyOpenGraph

結論から言うと、使えません。

PyOpenGraph PyPlページ
https://pypi.org/project/PyOpenGraph/

PyOpenGraphは、OGP公式サイトで紹介されています。

OGP公式
https://ogp.me/

公式がおススメするライブラリと言えます。
このライブラリの最新版は、0.2です。

0.2は、2010年5月9日に公開されています。
期待せずにインストールしてみます。

pip install PyOpenGraph

上記を実行すると、インストールが始まります。
無事に終了。
確認してみます。

>pip list
Package     Version
----------- -------
pip         21.1
PyOpenGraph 0.2
setuptools  56.0.0

パッケージもちゃんとインストールされています。
では、動作確認を行います。

import PyOpenGraph

このimport文だけのコードを実行すると、以下のエラーが出ます。

ModuleNotFoundError: No module named 'PyOpenGraph'

これも古すぎて、エラーを追いかける気にもなりません。
そもそも、Python3には未対応の可能性すらありえます。

では、次はpy-ogp-parserの検証していきます。

py-ogp-parser

結論から言うと、使いません。

基本的には使えますが、OGPを取得できない場合があります。
スクレイピング対策をしているサイトでは、無力な場合があります。

py-ogp-parser PyPlページ
https://pypi.org/project/py-ogp-parser/

py-ogp-parserの最新版は、0.2.1となります。
この0.2.1は、2018年12月24日に公開されています。

これは、今までのライブラリと比べると新しい方です。
期待ができます。

インストールは、次のコマンドで行います。

pip install py-ogp-parser

インストール状況を確認します。

>pip list
Package        Version
-------------- ---------
beautifulsoup4 4.9.3
certifi        2020.12.5
chardet        4.0.0
idna           2.10
pip            21.1
py-ogp-parser  0.2.1
requests       2.25.1
setuptools     56.0.0
soupsieve      2.2.1
urllib3        1.26.4

多くのパッケージがインストールされました。
基本的なモノが多いとは言え、これは嫌な感じです。

なぜなら、依存パッケージが多いと気軽に導入ができません。
既存環境には、なるべく影響を与えたくありません。

とりあえずは、動作確認をしてみます。

from py_ogp_parser.parser import request

status_code, result = request('https://www.watch.impress.co.jp/docs/news/1316107.html')
print(status_code)
print(result)

上記を実行した結果は、以下。

200
{'title': 'iOS 14.5公開。マスクでもApple WatchでiPhoneロック解除 - Impress Watch', 'ogp': {'date': ['2021-04-27T11:42:36+09:00'], 'fb:app_id': ['313703452412789'], 'og:type': ['article'], 'og:locale': ['ja_JP'], 'og:site_name': ['Impress Watch'], 'og:url': ['https://www.watch.impress.co.jp/docs/news/1316107.html'], 'og:title': ['iOS 14.5公開。マスクでもApple WatchでiPhoneロック解除'], 'og:description': ['アップルは27日、iOS 14.5を提供開始した。Apple Watchと連携し、マスクを着用していてもiPhoneのFace IDロックをApple Watchで解除できる機能が提供される。また、紛失防止タグの「AirTag」に対応する。'], 'og:image': ['https://www.watch.impress.co.jp/img/ipw/list/1316/107/ios1.jpg'], 'article:published_time': ['2021-04-27T02:57:32+09:00'], 'article:modified_time': ['2021-04-27T11:42:36+09:00'], 'article:tag': ['Apple,テック']}, 'seo': {'author': ['株式会社インプレス'], 'copyright': ['Copyright © Impress Corporation. All Rights Reserved.'], 'keywords': ['Apple,テック'], 'creation_date': ['2021-04-27T02:57:32+09:00'], 'ipw:id': ['1316107'], 'ipw:site': ['ipw'], 'ipw:year': ['2021'], 'ipw:month': ['4'], 'ipw:day': ['27'], 'ipw:firstpage': ['/docs/news/1316107.html'], 'twitter:card': ['summary_large_image'], 'twitter:site': ['@impress_watch'], 'twitter:image:src': ['https://www.watch.impress.co.jp/img/ipw/list/1316/107/ios1.jpg'], 'twitter:url': ['https://www.watch.impress.co.jp/docs/news/1316107.html'], 'twitter:title': ['iOS 14.5公開。マスクでもApple WatchでiPhoneロック解除'], 'twitter:description': ['アップルは27日、iOS 14.5を提供開始した。Apple Watchと連携し、マスクを着用していてもiPhoneのFace IDロックをApple Watchで解除できる機能が提供される。また、紛失防止タグの「AirTag」に対応する。'], 'distributable': ['licensee'], 'referrer': ['always'], 'robots': ['max-image-preview:large']}}

OGPが取得できています。
ただし、これはスクレイピング対策をしていないページだからです。

上手く行かないのは、メルカリの商品ページです。
メルカリはがっつりとスクレイピング対策をしています。

status_code, result = request('https://www.mercari.com/jp/items/m82674740968/')

上記のようにURLを変更して、プログラムを実行した結果は以下。

403
{'title': '403 Forbidden', 'ogp': {}, 'seo': {}}

403エラーで弾かれています。

以上、py-ogp-parserの検証でした。
次は、Seleniumによるスクレイピングの検証です。

Seleniumによるスクレイピング

結論から言うと、使えます。

メルカリのページからもOGPが取得できます。
そのためには、Seleniumでスクレピングができる環境が必要です。

その環境を作るためには、以下が必要となります。

  • Selenium
  • BeautifulSoup4
  • lxml

これらのインストール方法は、次の記事で解説しています。
記事内の「スクレイピングするための準備」が参考になります。

準備が整ったら、次のサンプルコードを動かしてみましょう。

import bs4
import traceback
import re
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

CHROMEDRIVER = "chromedriver.exeのパス"
TARGET_URL = "https://www.mercari.com/jp/items/m43435569677/"

# ドライバー準備
def get_driver():
    # ヘッドレスモードでブラウザを起動
    options = Options()
    options.add_argument('--headless')

    # ブラウザーを起動
    driver = webdriver.Chrome(CHROMEDRIVER, options=options)

    return driver

# 対象ページのソース取得
def get_source_from_page(driver, page):
    try:
        # ターゲット
        driver.get(page)
        page_source = driver.page_source

        return page_source

    except Exception as e:

        print("Exception\n" + traceback.format_exc())

        return None


# ソースからスクレイピングする
def get_data_from_source(src):
    # スクレイピングする
    soup = bs4.BeautifulSoup(src, features='lxml')

    try:
        items = {}
        elems = soup.find_all("meta", property=re.compile(r'^og'))

        for elem in elems:
            key = elem['property'][3:]
            if key == "image:url":
                key = "image"

            items[key] = elem['content']

        return items

    except Exception as e:

        print("Exception\n" + traceback.format_exc())

        return None


if __name__ == "__main__":

    # ブラウザのdriver取得
    driver = get_driver()

    page = TARGET_URL
    source = get_source_from_page(driver, page)

    # 記事ページURL取得
    ogp = get_data_from_source(source)

    print(ogp)

    # 閉じる
    driver.quit()

上記のプログラムを実行した結果は、以下。

{'type': 'website', 'site_name': 'メルカリ スマホでかんたん フリマアプリ', 'title': '4.21 w-1097 GRL\u3000グレイル\u3000マキシ\u3000ロングスカート(¥1,500) - メルカリ スマホでかんたん フリマアプリ', 'description': '数ある中からご覧頂き、ありがとうございます。プロフィールを必ずお読みになってからのご購入をお願いいたします。サイズ:Mウエスト幅 約58cmヒップ 約82 cm総丈 約88cm色\u3000グリーン系素材表記が分かる場合は、画像にて載せてますのでご確認下さい。素人の採寸ですので若干の誤差はご了承ください。usedということをご理解して頂いた上でのご購入をお願い致します。ご質問などが御座いましたらお気軽にコメント下さい。', 'url': 'https://www.mercari.com/jp/items/m43435569677/', 'image': 'https://static.mercdn.net/item/detail/orig/photos/m43435569677_1.jpg?1618973940'}

py-ogp-parserでは、メルカリのページへアクセスすらできませんでした。
しかし、SeleniumによるスクレイピングであればOGPを取得できます。

なお、定数は以下の箇所で設定しています。

CHROMEDRIVER = "chromedriver.exeのパス"
TARGET_URL = "https://www.mercari.com/jp/items/m43435569677/"

CHROMEDRIVERに関しては、次の記事で説明しています。

TARGET_URLには、OGPを取得したページのURLを設定します。
なお、プログラムの詳細に関しては、本サイトにおける他の記事で説明しています。

基本的には、同じような関数を利用しています。

  • get_driver
  • get_source_from_page
  • get_data_from_source

よって、上記の関数で本サイトを検索するとよいでしょう。

以上、Seleniumによるスクレイピングの検証でした。
より完璧を求めるなら、Seleniumによるスクレイピングがおススメです。

タイトルとURLをコピーしました