DEV Community

Cover image for Đếm chữ tiếng Việt và tìm đoạn lặp ý trong bài viết bằng Python
Onic Ai
Onic Ai

Posted on Originally published at onic.vn

Đếm chữ tiếng Việt và tìm đoạn lặp ý trong bài viết bằng Python

Công cụ đếm chữ cho bài tiếng Việt có một vấn đề ít ai nói: bộ đếm của WordPress, Yoast hay Google Docs đếm theo khoảng trắng, nên mỗi tiếng là một chữ. "Tối ưu hình ảnh" là bốn chữ dù chỉ là hai từ. Bài này viết hai tiện ích nhỏ: đếm chữ theo từng phần của bài, và tìm các đoạn có khả năng lặp ý.

Vì sao không đặt mục tiêu số chữ

Hướng dẫn tạo nội dung hữu ích của Google nói rõ họ không có số chữ ưu tiên, và viết theo số chữ là dấu hiệu nội dung viết cho máy. Vì vậy hai tiện ích dưới không dùng để ép bài dài ra, mà để thấy bài đang dài ở đâu và có dài vô ích không.

Đếm chữ theo từng H2

import re
from bs4 import BeautifulSoup

def dem_theo_phan(html: str) -> list:
    soup = BeautifulSoup(html, "html.parser")
    ket_qua, ten, chu = [], "Mở bài", 0
    for el in soup.find_all(["h2", "p", "li", "td"]):
        if el.name == "h2":
            ket_qua.append((ten, chu))
            ten, chu = el.get_text(strip=True), 0
        else:
            chu += len(el.get_text(" ", strip=True).split())  # đếm theo khoảng trắng như WordPress
    ket_qua.append((ten, chu))
    return ket_qua
Enter fullscreen mode Exit fullscreen mode

Kết quả cho thấy ngay khi mở bài chiếm một phần lớn, hoặc một phần lạc đề dài hơn phần chính. Bài "collagen uống lúc nào tốt nhất" có câu trả lời ở đoạn thứ chín là loại lỗi bảng này bắt được: phần đầu dài, phần trả lời ngắn.

Tìm đoạn lặp ý

Lặp ý là hai đoạn nói cùng một điều bằng câu khác. Không cần mô hình ngôn ngữ lớn để bắt trường hợp rõ ràng: so độ trùng của các cụm hai tiếng (bigram) giữa các đoạn là đủ làm bộ lọc đầu tiên.

from itertools import combinations

def bigram(doan: str) -> set:
    tieng = re.findall(r"\w+", doan.lower())
    return {" ".join(tieng[i:i + 2]) for i in range(len(tieng) - 1)}

def doan_nghi_lap(cac_doan: list, nguong: float = 0.35) -> list:
    bg = [bigram(d) for d in cac_doan]
    nghi = []
    for i, j in combinations(range(len(cac_doan)), 2):
        if not bg[i] or not bg[j]:
            continue
        jaccard = len(bg[i] & bg[j]) / len(bg[i] | bg[j])
        if jaccard >= nguong:
            nghi.append((i, j, round(jaccard, 2)))
    return sorted(nghi, key=lambda x: -x[2])
Enter fullscreen mode Exit fullscreen mode

Dùng cụm hai tiếng thay vì từng tiếng vì tiếng Việt có nhiều tiếng lặp tự nhiên ("của", "là", "và"); cụm hai tiếng bám sát ý hơn. Ngưỡng 0,35 là điểm bắt đầu để thử, không phải con số chuẩn. Kết quả chỉ là danh sách cho người biên tập đọc lại, không tự cắt.

Giới hạn

Hai tiện ích không trả lời được câu hỏi quan trọng nhất: bài đã đủ ý người tìm cần chưa. Câu đó cần mở các trang đang top, liệt kê ý từng trang trả lời, rồi so với bài của mình. Bộ đếm chỉ cho biết chữ nằm ở đâu.

Khoảng chữ hợp lý cho 5 loại bài và cách đo độ dài theo đối thủ có trong bài Độ dài bài viết chuẩn SEO trên Onic.vn.


Bài gốc: https://onic.vn/kien-thuc/do-dai-bai-viet-chuan-seo/

Top comments (0)