Pythonスクリプトでウェブサイトのfaviconを取得したい場面はあるでしょう。リンクプレビュー、ブックマークマネージャー、監視ダッシュボードなどが考えられます。良いニュースは、重厚なブラウザ自動化ツールは不要だということです。requestsとBeautifulSoupを使えば数行で済みます。

このチュートリアルでは、一般的なケースに対応するpython get favicon from url関数の書き方を具体的に示します。HTMLの解析、/favicon.icoへのフォールバック、バイナリファイルの保存までを扱います。

前提条件

Python 3.7以上と2つのライブラリ、requestsとbeautifulsoup4が必要です。pipでインストールします。

pip install requests beautifulsoup4

HTMLを手動で解析したくない場合は、PyPIで入手できるfaviconのようなライブラリも使えますが、ここでは完全に制御するためにゼロから構築します。

ステップ1: ページのHTMLを取得する

まずページのソースをダウンロードします。現実的なUser-Agentヘッダーを使用してください。一部のサーバーはデフォルトのPythonリクエストをブロックします。

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse

def get_favicon_url(page_url):
    headers = {'User-Agent': 'Mozilla/5.0 (compatible; FaviconFetcher/1.0)'}
    resp = requests.get(page_url, headers=headers, timeout=10)
    resp.raise_for_status()
    soup = BeautifulSoup(resp.text, 'html.parser')
    # ... continue below

必ずタイムアウトを設定してください。設定しないと、遅いサーバーがスクリプトを無期限にハングさせる可能性があります。

ステップ2: link rel="icon"タグを探す

HTML仕様では、faviconを宣言する標準的な方法としてrel="icon"が定義されています。ブラウザはshortcut iconやapple-touch-iconも受け入れます。ここではそれらすべてをチェックし、ICOよりSVGとPNGを優先します。

    icon_link = soup.find('link', rel=lambda x: x and 'icon' in x.lower())
    if icon_link and icon_link.get('href'):
        return urljoin(page_url, icon_link['href'])
    # Fallback to /favicon.ico
    parsed = urlparse(page_url)
    return f'{parsed.scheme}://{parsed.netloc}/favicon.ico'

urljoinの使用に注意してください。faviconのhrefはしばしば相対パス(例: /assets/favicon.png)であり、ページURLを基準に解決する必要があります。

ステップ3: アイコンをダウンロードして保存する

URL が取得できたら、バイナリデータを取得してファイルに書き込みます。拡張子を選ぶには、Content-Type ヘッダーを確認します。

def download_favicon(favicon_url, output_path='favicon.ico'):
    headers = {'User-Agent': 'Mozilla/5.0 (compatible; FaviconFetcher/1.0)'}
    resp = requests.get(favicon_url, headers=headers, timeout=10)
    resp.raise_for_status()
    content_type = resp.headers.get('Content-Type', '')
    if 'png' in content_type:
        output_path = output_path.replace('.ico', '.png')
    elif 'svg' in content_type:
        output_path = output_path.replace('.ico', '.svg')
    with open(output_path, 'wb') as f:
        f.write(resp.content)
    return output_path

これが中核となるロジックです。2つの関数を1つのスクリプトにまとめれば、コマンドラインから URL を受け取れるようにできます。

よくある落とし穴

複数の icon format(Apple Touch、manifest icons)を抽出する必要がある場合は、利用可能な icon をすべて調べられる Mzu favicondl のような専用ツールを検討してください。favicon の format の詳細については、favicon format ガイド を参照してください。

結論

これで、任意の URL から favicon を取得できる Python 関数が完成しました。重要な手順は、ページを取得し、<link> タグを解析し、相対 URL を解決し、バイナリをダウンロードすることです。エラーやエッジケースを処理すれば完了です。

多くのサイトをスクレイピングする場合は、robots.txtとレート制限を尊重してください。完全なfaviconソリューションについては、比較のためにPHPチュートリアルを確認してください。

文書化された要件を確認する

HTML Standardは、rel='icon'を、現在のページを表すアイコンのリンク関係として定義しています。