首先說(shuō)明欧募,這不是編碼
在使用readability的api提取網(wǎng)頁(yè)內(nèi)容的時(shí)候點(diǎn)這里看-readability-網(wǎng)頁(yè)內(nèi)容提取利器桶略,中文內(nèi)容都是&#x
開(kāi)頭的一堆亂碼似的東西跪呈。但保存成網(wǎng)頁(yè)文件后嚷量,瀏覽器是可以正常顯示的~
故搜索了一下,知乎上有個(gè)回答挺好,在此轉(zhuǎn)一下:
形如
&name;
&#dddd;
&#xhhhh;
的一串字符是 HTML荆几、XML 等 SGML 類(lèi)語(yǔ)言的轉(zhuǎn)義序列(escape sequence)吓妆。它們不是「編碼」。以 HTML 為例伴郁,這三種轉(zhuǎn)義序列都稱(chēng)作 character reference:第一種是 character entity reference,后接預(yù)先定義的 entity 名稱(chēng)蛋叼,而 entity 聲明了自身指代的字符焊傅。
后兩種是 numeric character reference(NCR),數(shù)字取值為目標(biāo)字符的 Unicode code point狈涮;以「&#」開(kāi)頭的后接十進(jìn)制數(shù)字狐胎,以「&#x」開(kāi)頭的后接十六進(jìn)制數(shù)字。
從 HTML 4 開(kāi)始歌馍,NCR 以 Unicode 為準(zhǔn)握巢,與文檔編碼無(wú)關(guān)∷扇矗「中國(guó)」二字分別是 Unicode 字符 U+4E2D 和 U+56FD暴浦,十六進(jìn)制表示的 code point 數(shù)值「4E2D」和「56FD」就是十進(jìn)制的「20013」和「22269」。所以
我給加了空格晓锻,不然網(wǎng)頁(yè)會(huì)自動(dòng)渲染成文字...
&#x 4e2d;&#x 56fd;
&# 20013;&# 22269;
這兩種 NCR 寫(xiě)法都會(huì)在顯示時(shí)轉(zhuǎn)換為「中國(guó)」二字歌焦。NCR 可以用于轉(zhuǎn)義任何 Unicode 字符,而 character entity reference 很受限砚哆,參見(jiàn) HTML 4 和 HTML5 中已有定義的字符列表:
Character entity references in HTML 4
Character entity references in HTML5
另外可以參考這篇文章 使用&#x 3000
等空格實(shí)現(xiàn)最小成本中文對(duì)齊
知道了是什么独撇,現(xiàn)在來(lái)看怎么把它轉(zhuǎn)回成中文呢?
Python實(shí)現(xiàn)
要將16進(jìn)制字符轉(zhuǎn)成中文可以用如下方法
# Pythone3
b'\u4e2d\u6587'.decode('unicode-escape')
# Python2
'\u4e2d\u6587'.decode('unicode-escape')
故需要將&#xhhhh;
做替換躁锁,再用上面的方式進(jìn)行轉(zhuǎn)換纷铣。對(duì)于特殊符號(hào)(如加減乘除),會(huì)顯示為&#xhh
战转,后面只有兩位搜立,在轉(zhuǎn)換之前,需要提前補(bǔ)全槐秧。具體可參看readability-網(wǎng)頁(yè)內(nèi)容提取利器
Java實(shí)現(xiàn)
引用此處:http://xuelianbobo.iteye.com/blog/2155114
package com.xue.tools;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.dom4j.DocumentException;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;
public class Test {
public static void main(String[] args) throws IOException, DocumentException, XPatherException {
// 定義正則表達(dá)式來(lái)搜索中文字符的轉(zhuǎn)義符號(hào)
Pattern compile = Pattern.compile("&#.*?;");
// 測(cè)試用中文字符
String sourceString = "C集團(tuán)天c津大唐國(guó)際盤(pán)山發(fā)電有限責(zé)任公司";
Matcher matcher = compile.matcher(sourceString);
// 循環(huán)搜索 并轉(zhuǎn)換 替換
while (matcher.find()) {
String group = matcher.group();
// 獲得16進(jìn)制的碼
String hexcode = "0" + group.replaceAll("(&#|;)", "");
// 字符串形式的16進(jìn)制碼轉(zhuǎn)成int并轉(zhuǎn)成char 并替換到源串中
sourceString = sourceString.replaceAll(group, (char) Integer.decode(hexcode).intValue() + "");
}
System.out.println(sourceString);
}
}
補(bǔ)充:
后來(lái)想到儒拂,其實(shí)可以把這當(dāng)成html來(lái)解析啊,然后就有了:
text = '&#x 4e2d'
lxml.html.fromstring(text).text