ChatGPTでタグ整理機能を作ってみた(その1)タグ一覧を取得する

どーもボキです。

今回の連休、前々からこのブログで修正したいと思っていた「タグ」、この反映作業を自動化してみました。しっかり触ったこともないPythonを使って、です。

みなさんもタグ修正を楽ちんにしたいと思いませんか?
ボキは常々思ってきました。

ブログを続けるにつれて、タグの設定が細かすぎた・粗すぎた、表記が揺れていた(YouTubeとYoutubeの混在)など、数個の記事なら手で直せばよいですが、記事数が多くなると修正作業だけでひと苦労……。気づいてしまったら気になってしゃーない。ないですか?


なのでこの連休、ChatGPTを使ったプログラム開発に挑戦してみました!
ChatGPTさんにPython環境の導入~プログラム実装、そしてデバッグまでをお願いしながら、です。


やってみてわかったこと、
ChatGPTはすごい!むっちゃ進化しているっ!?こりゃ~世界が変わりますわ。

まともに触ったことがなかったPythonですが、たった1日ですべての記事の取得~修正データ反映までが自動化ができました!!



今回の肝は、Webブラウザの自動化、Webページのスクレイピング(Webサイトから特定の情報を自動的に抽出・収集すること)、です。エキサイトブログには記事一覧の取得機能がありません。なので、スクレイピングは必須です。この記事で紹介した技術も、まさにスクレイピングですね。


エキサイトブログ制約をまとめると以下になります。
  • 全ての記事の一括取得や一覧化できるページがない。できることは、記事の管理ページ(20~100個の記事を表示できる)をめくり、すべての記事の取得すること。
  • 記事の管理ページでは、タイトル名やカテゴリ名の長さによって末尾が省略される(長い場合は末尾が「...」となる)。
  • 記事の管理ページには、記事に設定したタグは記載されない。タグを確認するには、記事を開く必要がある。


上記のような制約を踏まえ、すべての記事データを取得するために以下のような処理ステップを考えてみました。
  1. エキサイトブログにログインし、記事の管理ページから記事データを取得する。
  2. 1で取得した記事データ(URL)から、記事本体を開き、そこからタイトル名・カテゴリ名・設定されているタグを取得する。
  3. 上記を、記事の管理ページをめくっても記事が表示されなくなるまで繰り返す。


ChatGPTがプログラムを書いてくれるので、それを実行しながら、出てきたエラーメッセージをChatGPTへ伝えて修正をかけながら進めます。

このやりとりでChatGPTの反応にビックリしました!
なぜなら……
ChatGPTでタグ整理機能を作ってみた(その1)タグ一覧を取得する_a0021757_16263855.png
ムチャクチャ褒めてくれます😍


表示されたエラーをコピペで伝えると……、
ChatGPTでタグ整理機能を作ってみた(その1)タグ一覧を取得する_a0021757_16191549.png
まっさきに褒めてくれます😂


気持ち良すぎる……。こりゃぁ自己肯定感、爆上がりですよ。


以下のようなコードを作りました。貼っておきますね。

ブログのURL、ブログのアクセスIDとパスワードは、みなさんのものに打ち換えてください(赤文字のところ)。実行すると、全ての記事をCSVファイルへ保存します。
ChatGPTでタグ整理機能を作ってみた(その1)タグ一覧を取得する_a0021757_17061996.png
上図のように、タイトル、リンク、日付、カテゴリ、タグ1~3、本文が取得できます。


ちなみに……、ボキは以下のPythonのコードを事細かく理解していません。けれど、動くものが超短期間に作れてしまう。

ChatGPT……おそろしい子……!


その2では、取得したCSVファイルを使って、ブログのタグ設定を更新する方法を紹介しますね。


このシリーズの記事リスト



■Pythonのソースコード(ChatGPTに作らせたエキサイトブログの投稿記事の一覧取得ツール)
print("== 実行中のスクリプト: 記事一覧タグ付3列+本文+カテゴリ取得 ==")

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
import time
import csv
from datetime import datetime

# --- 設定エリア ---
driver_path = r"C:\tools\chromedriver\chromedriver.exe"
login_needed = True
your_blog_url = "https://yozda.exblog.jp/"
your_login_id = "yozda"
your_login_pw = "************************"
BASE_URL = "https://userconf.exblog.jp/posts/index.php?page="
CSV_FILENAME = "blog_articles_with_tags.csv"
DEBUG_STOP_PAGE = None # 例)2なら2ページまで、Noneで全ページ
# --- ここまで設定エリア ---

# ログの設定
def log(msg):
now = datetime.now().strftime("[%H:%M:%S]")
print(f"{now} {msg}")
start_time = time.time()

# 警告メッセージの最小化
chrome_options = Options()
chrome_options.add_argument("--log-level=3")
service = Service(driver_path)
driver = webdriver.Chrome(service=service, options=chrome_options)

if login_needed:
driver.get("https://ssl2.excite.co.jp/idc/login/")
wait = WebDriverWait(driver, 15)
email_input = wait.until(EC.presence_of_element_located((By.NAME, "loginid")))
email_input.send_keys(your_login_id)
password_input = driver.find_element(By.NAME, "password")
password_input.send_keys(your_login_pw)
driver.find_element(By.CLASS_NAME, "btn_login").click()
time.sleep(3)

# ブログを開く
driver.get(f"{your_blog_url}")
time.sleep(2)

# CSV初期化(見出し行書き込み)
with open(CSV_FILENAME, mode="w", newline="", encoding="shift_jis", errors="ignore") as f:
writer = csv.writer(f)
writer.writerow(["タイトル", "リンク", "日付", "カテゴリ", "公開状態", "タグ1", "タグ2", "タグ3", "本文"])

page = 1
while True:
url = f"{BASE_URL}{page}"
log(f"取得中: {url}")
driver.get(url)
time.sleep(2)

if DEBUG_STOP_PAGE is not None and page > DEBUG_STOP_PAGE:
log(f"デバッグ指定: {DEBUG_STOP_PAGE}ページ直前で終了")
break

rows = driver.find_elements(By.CSS_SELECTOR, "tbody tr")
if not rows:
log("記事が見つかりません。")
break

for row in rows:
try:
title_elem = row.find_element(By.CSS_SELECTOR, "td.headline a")
title = title_elem.text.strip()
link = title_elem.get_attribute("href").strip()
try:
title_elem.find_element(By.TAG_NAME, "img")
visibility = "非公開"
except:
visibility = "公開"
except:
continue

date = row.find_element(By.CSS_SELECTOR, "td.date").text.strip() if row.find_elements(By.CSS_SELECTOR, "td.date") else ""

# 個別記事ページからカテゴリ・タグ・本文取得
driver.execute_script("window.open('');")
driver.switch_to.window(driver.window_handles[1])
driver.get(link)

try:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "h1")))
time.sleep(0.5)
except:
pass

# 正式タイトル
try:
h1 = driver.find_element(By.CSS_SELECTOR, "h1.post-title")
title = h1.text.strip()
except:
pass

# 本文
try:
body_elem = driver.find_element(By.CSS_SELECTOR, "div.post-main")
body = body_elem.text.strip().replace("\u3000", " ").replace("\n", " ")
except:
body = ""

# タグ
tags = []
try:
tag_elements = driver.find_elements(By.CSS_SELECTOR, "ul.taglist-list li a")
for elem in tag_elements:
tag_text = elem.text.strip()
if tag_text:
tags.append(tag_text)
except:
pass

tag1 = tags[0] if len(tags) > 0 else ""
tag2 = tags[1] if len(tags) > 1 else ""
tag3 = tags[2] if len(tags) > 2 else ""

# カテゴリ(記事末尾のリンク)
try:
category_link = driver.find_element(By.CSS_SELECTOR, "span.TIME a:nth-of-type(2)")
category = category_link.text.strip()
except:
category = ""

# CSV追記
with open(CSV_FILENAME, mode="a", newline="", encoding="shift_jis", errors="ignore") as f:
writer = csv.writer(f)
writer.writerow([title, link, date, category, visibility, tag1, tag2, tag3, body])
log(f"✔ 保存: {title[:30]}...")

driver.close()
driver.switch_to.window(driver.window_handles[0])

try:
next_button = driver.find_element(By.CSS_SELECTOR, "li.next a")
if next_button:
page += 1
else:
break
except:
break

driver.quit()
elapsed = time.time() - start_time
log(f"完了!経過時間: {elapsed:.1f}秒")





名前
URL
削除用パスワード

※このブログはコメント承認制を適用しています。ブログの持ち主が承認するまでコメントは表示されません。

by yozda | 2025-04-30 16:31 | ボキ、しごとのヒント集める | Comments(0)

ボキの興味、書き散らかします


by ボキ
カレンダー
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31