HTML コンテンツ運用メモ

Web サーバ設定のために作成したプログラム

動作要件・前提条件

以下の環境が必要である。

Ubuntu では、BeautifulSoup4のインストールは以下のコマンドで行う。

sudo apt install python3-bs4

HTMLファイル複数行置換・一括

#!/usr/bin/env python3
import os
import glob
import tempfile

def read_multiline(prompt):
    print(prompt)
    lines = []
    while True:
        try:
            line = input()
        except EOFError:
            break
        if line == '---':
            break
        lines.append(line)
    return '\n'.join(lines)

old_text = read_multiline('置換前のテキストを入力(--- で終了):')
new_text = read_multiline('置換後のテキストを入力(--- で終了):')

for filepath in glob.glob('/www/**/*.html', recursive=True):
    try:
        with open(filepath, encoding='utf-8') as f:
            content = f.read()
    except UnicodeDecodeError:
        print(f'スキップ(UTF-8以外): {filepath}')
        continue

    if old_text not in content:
        continue

    stat = os.stat(filepath)
    new_content = content.replace(old_text, new_text)

    dirpath = os.path.dirname(filepath)
    fd, tmp_path = tempfile.mkstemp(dir=dirpath, suffix='.tmp')
    try:
        with os.fdopen(fd, 'w', encoding='utf-8') as f:
            f.write(new_content)
        os.replace(tmp_path, filepath)
    except:
        os.unlink(tmp_path)
        raise

    os.utime(filepath, (stat.st_atime, stat.st_mtime))
    print(f'置換: {filepath}')

headingcheck.py - 見出し構造チェッカー

コマンドライン引数で指定したURLのWebページ内のh1〜h6タグを検査し、階層構造の問題(h1の重複、階層の飛び等)を報告する。

headingcheck.py というファイル名で保存

# -*- coding: utf-8 -*-
import sys
import urllib.request
from bs4 import BeautifulSoup

url = sys.argv[1]
html = urllib.request.urlopen(url)
soup = BeautifulSoup(html, "html.parser")

headings = soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])

h1_count = 0
prev_level = 0

for h in headings:
    level = int(h.name[1])
    text = h.get_text().strip()[:30]

    if level == 1:
        h1_count += 1
        if h1_count > 1:
            print('NG: h1が複数存在:', text)

    if prev_level > 0 and level > prev_level + 1:
        print('NG: 階層の飛び h' + str(prev_level) + '→h' + str(level) + ':', text)

    prev_level = level

if h1_count == 0:
    print('NG: h1が存在しない')

使用例

コマンドラインから以下のように実行する。

python headingcheck.py https://www.example.com/page.html

実行結果の例(見出し構造に問題がある場合):

NG: 階層の飛び h1→h3: 機能の詳細説明
NG: h1が複数存在: もう一つのタイトル

見出し構造に問題がない場合は何も出力されない。

imgcheck.py - 画像参照チェッカー

コマンドライン引数で指定したURLのWebページ内の全imgタグを検査し、参照先の画像ファイルが存在しない場合にエラーを報告する。

imgcheck.py というファイル名で保存

# -*- coding: utf-8 -*-
import sys
import urllib.request
from bs4 import BeautifulSoup
from urllib.parse import urljoin

url = sys.argv[1]
html = urllib.request.urlopen(url)
soup = BeautifulSoup(html, "html.parser")

for img in soup.find_all('img'):
    src = img.get('src')
    if src is None:
        continue
    img_url = urljoin(url, src)
    try:
        urllib.request.urlopen(img_url)
    except:
        print('NG:', url, img_url)

使用例

コマンドラインから以下のように実行する。

python imgcheck.py https://www.example.com/page.html

実行結果の例(画像参照エラーがある場合):

NG: https://www.example.com/page.html https://www.example.com/images/missing.jpg
NG: https://www.example.com/page.html https://www.example.com/images/deleted.png

画像参照エラーがない場合は何も出力されない。

title.py - Webページタイトル取得プログラム

コマンドライン引数で指定したURLのWebページからタイトル(<title>タグの内容)を取得し、標準出力に表示する。タイトルが存在しない場合や空の場合は、デフォルト値として「金子邦彦研究室」を出力する。

title.py というファイル名で保存

# -*- coding: utf-8 -*-
import sys
import urllib.request
from bs4 import BeautifulSoup

url = sys.argv[1]
html = urllib.request.urlopen(url)
soup = BeautifulSoup(html, "html.parser")
if soup.title is None:
    print('金子邦彦研究室')
elif soup.title.string is None or len(soup.title.string) == 0:
    print('金子邦彦研究室')
else:
    print(soup.title.string.strip())

使用例

コマンドラインから以下のように実行する。

python title.py https://www.example.com/

実行結果の例:

Example Domain

テスト実行

以下のシェルスクリプトにより、ディレクトリ内の全HTMLファイルに対してtitle.pyを実行できる。

for i in */*.html; do
  python /tmp/title.py https://www.kkaneko.jp/$i
done

desc.py - メタディスクリプション取得プログラム

コマンドライン引数で指定したURLのWebページから、meta name="description" タグのcontent属性値を取得し、標準出力に表示する。該当するmetaタグが存在しない場合は「Empty」を出力する。

desc.py というファイル名で保存

# -*- coding: utf-8 -*-
import sys
import urllib.request
from bs4 import BeautifulSoup

url = sys.argv[1]
html = urllib.request.urlopen(url)
soup = BeautifulSoup(html, "html.parser")
a = soup.find_all('meta', attrs={'name': 'description'})
if a is None or len(a) == 0:
    print('Empty')
else:
    for i in a:
        c = i.get('content')
        if c is None or len(c.strip()) == 0:
            print('Empty')
        else:
            print(c.strip())

使用例

コマンドラインから以下のように実行する。

python desc.py https://www.example.com/

実行結果の例(metaタグにdescriptionが設定されている場合):

This domain is for use in illustrative examples in documents.

実行結果の例(metaタグにdescriptionが設定されていない場合):

Empty