&#x開頭的是什么編碼?


在 Node 層利用 cheerio 解析網頁時,輸出的中文內容都是以 &#x 開頭的一堆像亂碼一樣的東西,嘗試過各種編碼都無效,而且神奇的是,將這一堆“亂碼”保存成網頁后,通過瀏覽器打開又可以正常顯示。這到底是什么👻??

縮減后的示例代碼如下:

const cheerio = require('cheerio');
const $ = cheerio.load('<div id="content">你好</div>')
console.log($('#content').html()) //&#x4F60;&#x597D;

其實,上面那一堆亂碼一樣的東西,它的學名叫實體編碼 entity code。

下面引用下知乎搜到的答案。

在 HTML 中,某些字符是預留的,例如小於號「<」、大於號「>」等,瀏覽器會將它們視作標簽。如果想要在HTML中顯示這些預留字符,我們就要用到字符實體(character entities)。我們比較熟悉的字符實體有空格「&nbsp;」,小於號「&lt;」,大於號「&gt;」等。這樣的格式比較語義化,容易記憶,但其實字符實體有其他的格式:

&name;
&#dddd;
&#xhhhh;
  1. 這三種轉義方式都稱作 character reference,第一種是 character entity reference,「&」符號后接預先定義好的 entity 名稱。
  2. 后兩種是 numeric character reference,數字取值為目標字符的 Unicode code point;以「&#」開頭的后接十進制數字,「&#x」開頭的后接十六進制數字。

從 HTML4 開始,numeric character reference 以 Unicode 為准,與文檔編碼無關。「你好」二字分別是 Unicode 字符 U+4F60 和 U+597D,十六進制表示的 code point 數值「4F60」和「597D」,同時也就是十進制的「20320」和「22909」。所以

在HTML中輸入

&#x4F60;&#x597D;
&#20320;&#22909;

都會顯示為“你好”。

知道原因后,那么如何解決上述的問題呢?

方法一:使用cheerio提供的屬性

cheerio默認會對entity進行decode,我們只需要關閉該功能即可

const cheerio = require('cheerio');
const $ = cheerio.load('<div id="content">你好</div>', { decodeEntities: false })
console.log($('#content').html()) // 你好

方法二:手動decode

function decode(str) {
    // 一般可以先轉換為標准 unicode 格式(有需要就添加:當返回的數據呈現太多\\\u 之類的時)
    str = unescape(str.replace(/\\u/g, "%u"));
    // 再對實體符進行轉義
    // 有 x 則表示是16進制,$1 就是匹配是否有 x,$2 就是匹配出的第二個括號捕獲到的內容,將 $2 以對應進制表示轉換
    str = str.replace(/&#(x)?(\w+);/g, function($, $1, $2) {
      return String.fromCharCode(parseInt($2, $1? 16: 10));
    });

    return str;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM