標籤雲 是一種視覺化呈現方式,根據關鍵詞出現頻率(權重)動態調整字體大小,讓使用者快速掌握內容熱點。本系統包含:用戶提交文字 → 斷詞統計 → 入庫更新 → 前端渲染三大核心流程。
CREATE TABLE `tags` (
`tag_id` INT PRIMARY KEY AUTO_INCREMENT,
`keyword` VARCHAR(50) UNIQUE NOT NULL COMMENT '關鍵詞',
`weight` INT DEFAULT 1 COMMENT '權重/出現次數',
`link` VARCHAR(256) DEFAULT 'NA' COMMENT '關聯鏈接,預留擴展',
INDEX `idx_weight` (`weight` DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
<form method="post" action="tag_cloud_gen.php">
<textarea name="tag_input" rows="10" cols="60" placeholder="輸入文字,系統將自動提取關鍵詞..."></textarea><br>
<input type="submit" name="submit" value="生成標籤">
</form>
<form method="post" action="show_tag_cloud.php">
<input type="submit" value="查看當前標籤雲">
</form>
<?php
// 現代化 PDO 連接 (替代已棄用 mysql_* 函數)
$pdo = new PDO("mysql:host=localhost;dbname=tagcloud_db;charset=utf8mb4", "root", "");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$string = $_POST['tag_input'] ?? '';
if (empty(trim($string))) exit("請輸入內容");
// 斷詞規則:空格、標點、換行等作為分隔符
$separators = " \t\n\r,;.:'\"!&-`~@#$%^&*()_+={}[]|\\/?><";
$tokens = strtok($string, $separators);
$words = [];
while ($tokens !== false) {
$token = strtolower(trim($tokens));
if (strlen($token) > 1) { // 過濾單字符噪音
$words[$token] = ($words[$token] ?? 0) + 1;
}
$tokens = strtok($separators);
}
// 批量寫入/更新數據庫 (使用事務保證一致性)
try {
$pdo->beginTransaction();
$stmtInsert = $pdo->prepare("INSERT INTO tags (keyword, weight, link) VALUES (?, ?, 'NA')");
$stmtUpdate = $pdo->prepare("UPDATE tags SET weight = weight + ? WHERE keyword = ?");
foreach ($words as $keyword => $weight) {
// 嘗試插入,若主鍵衝突則更新
try {
$stmtInsert->execute([$keyword, $weight]);
} catch (PDOException $e) {
if ($e->getCode() == 23000) { // 1062 Duplicate entry
$stmtUpdate->execute([$weight, $keyword]);
} else { throw $e; }
}
}
$pdo->commit();
echo "處理完成,共 " . count($words) . " 個關鍵詞";
} catch (Exception $e) {
$pdo->rollBack();
echo "錯誤: " . $e->getMessage();
}
?>
<?php
$pdo = new PDO("mysql:host=localhost;dbname=tagcloud_db;charset=utf8mb4", "root", "");
$stmt = $pdo->query("SELECT keyword, weight, link FROM tags ORDER BY weight DESC");
$tags = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($tags)) exit("暫無標籤數據");
// 字體大小映射算法:線性映射到 [12px, 36px] 區間
$weights = array_column($tags, 'weight');
$minW = min($weights);
$maxW = max($weights);
$range = $maxW - $minW ?: 1; // 防止除零
$minFont = 12;
$maxFont = 36;
$factor = ($maxFont - $minFont) / $range;
.tags_container {
width: 800px; margin: 20px auto; padding: 20px;
border: 1px solid #e0e0e0; border-radius: 8px;
background: #fafafa; line-height: 2.5; text-align: center;
font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
}
.tag_link {
display: inline-block; margin: 0 8px 8px 0; padding: 2px 6px;
color: #4a6fa5; text-decoration: none; border-radius: 3px;
transition: all 0.2s ease;
}
.tag_link:hover {
background: #4a6fa5; color: #fff; text-decoration: none;
transform: scale(1.05);
}
<div class="tags_container">
<?php foreach ($tags as $tag):
// 計算字體大小
$size = round($minFont + ($tag['weight'] - $minW) * $factor);
$href = ($tag['link'] != 'NA') ? $tag['link'] : "https://www.google.com/search?q=" . urlencode($tag['keyword']);
?>
<a href="<?= htmlspecialchars($href) ?>"
class="tag_link"
style="font-size: <?= $size ?>px;"
target="_blank">
<?= htmlspecialchars($tag['keyword']) ?>
</a>
<?php endforeach; ?>
</div>
| 環節 | 關鍵點 | 現代化改進建議 |
|---|---|---|
| 斷詞 | strtok 簡單分隔 | 中文場景接入 Jieba/SCWS 分詞組件 |
| 資料庫 | MySQL + 唯一索引 | 高併發改用 Redis 計數器定時落庫 |
| 渲染算法 | 線性映射 | 對數/平方根映射改善長尾詞可見度 |
| 安全性 | 基礎過濾 | 全鏈路 PDO 預處理 + XSS 防護 |