DEV Community

Cover image for Kiểm tra FAQPage JSON-LD có khớp nội dung hiển thị không bằng Python
Onic Ai
Onic Ai

Posted on Originally published at onic.vn

Kiểm tra FAQPage JSON-LD có khớp nội dung hiển thị không bằng Python

Từ 7/5/2026, kết quả FAQ không còn xuất hiện trên Google Search, theo trang cập nhật tài liệu Google Search Central. Nhiều website vẫn giữ FAQPage, và điều đó không gây hại nếu schema hợp lệ và khớp nội dung. Vấn đề là "khớp nội dung" hay bị phá vỡ: sửa câu trả lời trên trang mà quên sửa schema, hoặc plugin và theme cùng sinh hai khối. Bài này viết một script bắt các lỗi đó.

Cấu trúc FAQPage tối giản

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Bà bầu uống collagen được không?",
      "acceptedAnswer": { "@type": "Answer", "text": "Câu trả lời đúng như trên trang." }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

FAQPage có thể đứng riêng hoặc nằm trong @graph cùng các kiểu khác, nên script phải duyệt cả hai dạng.

Script

import json, re
from bs4 import BeautifulSoup

def chuan_hoa(s: str) -> str:
    return re.sub(r"\s+", " ", BeautifulSoup(s, "html.parser").get_text()).strip().lower()

def tim_faqpage(node):
    if isinstance(node, list):
        for n in node:
            yield from tim_faqpage(n)
    elif isinstance(node, dict):
        if node.get("@type") == "FAQPage":
            yield node
        for v in node.values():
            if isinstance(v, (dict, list)):
                yield from tim_faqpage(v)

def kiem_tra_faq(html: str) -> list:
    soup = BeautifulSoup(html, "html.parser")
    loi, khoi = [], []
    for s in soup.find_all("script", type="application/ld+json"):
        try:
            khoi += list(tim_faqpage(json.loads(s.string or "")))
        except json.JSONDecodeError as e:
            loi.append(("json_loi", str(e)))
    if len(khoi) > 1:
        loi.append(("nhieu_khoi_faqpage", len(khoi)))
    for s in soup.find_all("script"):
        s.decompose()
    chu_trang = chuan_hoa(str(soup))
    for faq in khoi:
        for q in faq.get("mainEntity", []):
            hoi = chuan_hoa(q.get("name", ""))
            dap = chuan_hoa(q.get("acceptedAnswer", {}).get("text", ""))
            if hoi not in chu_trang:
                loi.append(("cau_hoi_khong_hien_tren_trang", hoi))
            if dap and dap[:80] not in chu_trang:
                loi.append(("cau_tra_loi_lech", hoi))
    return loi
Enter fullscreen mode Exit fullscreen mode

Các lỗi script bắt

  • nhieu_khoi_faqpage: một trang chỉ nên có một khối FAQPage. Hay gặp khi đã dùng khối FAQ của Yoast hoặc Rank Math rồi còn chèn thêm JSON-LD tự viết.
  • cau_hoi_khong_hien_tren_trang: schema có câu hỏi mà người đọc không thấy.
  • cau_tra_loi_lech: so 80 ký tự đầu của câu trả lời đã chuẩn hóa, đủ để bắt trường hợp sửa trên trang mà quên sửa schema.

Chạy trên nhiều trang

Chạy script qua danh sách URL trang sản phẩm còn bắt được một lỗi khác: cùng một bộ câu hỏi giống hệt trên hàng trăm trang. Gom tất cả name theo URL rồi đếm tần suất là thấy ngay. Bộ câu hỏi chung về giao hàng, đổi trả nên chuyển về một trang chính sách riêng.

Sau khi sửa, kiểm tra cú pháp bằng Schema Markup Validator của schema.org. Phần chọn câu hỏi từ câu người tìm thật và các mốc Google thay đổi kết quả FAQ có trong bài FAQ Schema là gì trên Onic.vn.


Bài gốc: https://onic.vn/kien-thuc/faq-schema-la-gi/

Top comments (0)