from collections import Counter
stories = [
"水井村推動智慧養殖,也用魚菜共生淨水。",
"水井三寶包含烏龜、白馬與姻緣花。",
"姻緣花承載水井村的地方記憶與祝福。",
]
counter = Counter()
for story in stories:
counter.update(meaningful_tokens(story, tokenizer))
for word, count in counter.most_common(10):
print(word, count)
詞頻高表示在這批語料出現多,不等於對社區最重要。一次只被長者說出的罕見詞,可能反而是珍貴文化線索。
十一、同一詞在幾篇故事出現?
document_frequency = Counter()
for story in stories:
unique_words = set(
meaningful_tokens(story, tokenizer)
)
document_frequency.update(unique_words)
for word, documents in document_frequency.most_common(10):
print(word, "出現在", documents, "篇")
詞頻計算總出現次數;文件頻率計算出現於幾篇文件。兩者回答不同問題,不能混稱「熱門程度」。
十二、顯示關鍵詞所在原句
def find_contexts(stories, keyword):
results = []
for index, story in enumerate(stories, start=1):
sentences = re.split(r"(?<=[。!?])", story)
for sentence in sentences:
sentence = sentence.strip()
if keyword in sentence:
results.append({
"story": index,
"sentence": sentence,
})
return results
for item in find_contexts(stories, "姻緣花"):
print(item)
frequency_top = [
word for word, count in counter.most_common(8)
]
tfidf_top = [word for word, weight in keywords]
comparison = {
"both": sorted(set(frequency_top) & set(tfidf_top)),
"frequency_only": [
word for word in frequency_top if word not in tfidf_top
],
"tfidf_only": [
word for word in tfidf_top if word not in frequency_top
],
}
print(comparison)
for item in root.findall("item"):
item_id = item.get("id")
language = item.get("language")
title = item.findtext("title", default="").strip()
status = item.findtext("status", default="").strip()
print(item_id, language, title, status)
方法
用途
find()
尋找第一個符合的子元素
findall()
取得所有符合元素
findtext()
直接取得第一個符合元素的文字
iter()
走訪目前元素下所有指定節點
五、從檔案安全解析
import xml.etree.ElementTree as ET
from pathlib import Path
def load_xml(path, max_bytes=2_000_000):
path = Path(path)
if not path.is_file():
raise FileNotFoundError(f"找不到XML:{path}")
if path.stat().st_size > max_bytes:
raise ValueError("XML超過教學程式允許大小")
try:
tree = ET.parse(path)
except ET.ParseError as error:
raise ValueError(f"XML格式錯誤:{error}") from error
return tree
def parse_guide_item(item):
item_id = (item.get("id") or "").strip()
language = (item.get("language") or "").strip()
title = item.findtext("title", default="").strip()
status = item.findtext("status", default="").strip()
missing = [
name
for name, value in {
"id": item_id,
"language": language,
"title": title,
"status": status,
}.items()
if not value
]
if missing:
raise ValueError("缺少內容:" + "、".join(missing))
return {
"id": item_id,
"language": language,
"title": title,
"status": status,
}
XML沒有自動幫你驗證業務規則。讀取後仍須確認必要屬性、空白文字、重複ID及可接受的語言代碼。
七、批次處理並隔離錯誤
def parse_guide(root):
records = []
errors = []
used_ids = set()
for index, item in enumerate(root.findall("item"), start=1):
try:
record = parse_guide_item(item)
if record["id"] in used_ids:
raise ValueError(f"重複id:{record['id']}")
used_ids.add(record["id"])
records.append(record)
except ValueError as error:
errors.append({"序號": index, "原因": str(error)})
return records, errors
from pathlib import Path
path = Path("教學資料.bin")
sample = bytes([0, 1, 2, 127, 128, 254, 255])
with path.open("xb") as file:
file.write(sample)
with path.open("rb") as file:
restored = file.read()
print(restored)
print(list(restored))
xb 表示排他建立二進位檔;目標已存在時會拒絕覆蓋,適合保護重要資料。
五、分塊讀取大型照片或錄音
使用 read() 一次讀完整段錄音可能占用大量記憶體。分塊處理能固定每次使用量。
from pathlib import Path
def count_bytes(path, chunk_size=64 * 1024):
total = 0
with Path(path).open("rb") as file:
while chunk := file.read(chunk_size):
total += len(chunk)
return total
print(count_bytes("教學資料.bin"))
六、安全複製:目標存在就停止
from pathlib import Path
def copy_binary(source, target, chunk_size=1024 * 1024):
source = Path(source)
target = Path(target)
if not source.is_file():
raise FileNotFoundError(f"來源不存在:{source}")
target.parent.mkdir(parents=True, exist_ok=True)
with source.open("rb") as input_file:
with target.open("xb") as output_file:
while chunk := input_file.read(chunk_size):
output_file.write(chunk)
return target
# copy_binary("原始媒體/訪談.wav", "備份/訪談.wav")
from pathlib import Path
def binary_inventory(folder):
allowed = {".jpg", ".jpeg", ".png", ".wav", ".mp3", ".pdf"}
records = []
for path in sorted(Path(folder).rglob("*")):
if path.is_file() and path.suffix.lower() in allowed:
records.append({
"相對路徑": str(path.relative_to(folder)),
"大小": path.stat().st_size,
"SHA256": sha256_file(path),
})
return records
# for record in binary_inventory("教學媒體"):
# print(record)
import unicodedata
def clean_transcript(text):
text = unicodedata.normalize("NFC", text)
text = text.replace("\u3000", " ")
lines = [line.strip() for line in text.splitlines()]
return "\n".join(line for line in lines if line)
raw_text = " 阿嬤講:姻緣花開矣。\n\n 這是庄頭的記持。 "
print(clean_transcript(raw_text))
[REMOTE] Heartbeat received RUN_DIAGNOSTIC
[DIAGNOSTIC] fw=V1.0-14,health=100/GOOD,state=IDLE,
track=0,vol=16,rssi=-27,queue=0,jq=0,busy=0,
btn=111111,alert=NONE
[REMOTE] Executed RUN_DIAGNOSTIC | result queued SUCCESS
[REMOTE] Result ACK SUCCESS
診斷資料如何解讀?
health=100/GOOD
設備健康,沒有需要立即處理的異常。
state=IDLE
故事機處於待機狀態。
vol=16
JQ6500目前音量為16。
rssi=-27
Wi-Fi訊號非常良好。
queue=0
沒有尚未同步的離線事件。
jq=0
本次運作尚未發生JQ6500復原。
busy=0
播放器沒有正在播放。
btn=111111
六個按鈕皆為釋放狀態,沒有腳位異常拉低。
alert=NONE
目前沒有作用中的設備告警。
真正關鍵的不是看到 Executed,而是最後收到 Result ACK SUCCESS。這代表「雲端建立命令、設備領取、設備執行、結果回送、伺服器確認」五個環節全部完成。
四、第二階段:從雲端開啟維護模式
Django 建立命令
→
Heartbeat 領取命令
→
設備啟用鎖定
→
結果 ACK 確認
[REMOTE] Heartbeat received MAINTENANCE_ON
[MAINTENANCE] Enabled by cloud
[REMOTE] Executed MAINTENANCE_ON | result queued SUCCESS
[REMOTE] Result ACK SUCCESS
[REMOTE] Heartbeat received MAINTENANCE_OFF
[MAINTENANCE] Disabled by cloud
[REMOTE] Executed MAINTENANCE_OFF | result queued SUCCESS
[REMOTE] Result ACK SUCCESS