HTML+CSS入门 HTML实体编码浅析
沉沙 2018-07-17 来源 : 阅读 1277 评论 0

摘要:本篇教程探讨了HTML实体编码的相关内容,希望阅读本篇文章以后大家有所收获,帮助大家HTML+CSS的入门。

When question comes

var $ = cheerio.load(sres.text);var ans = '';
$('.titlelnk').each(function (index, item) {
  var $item = $(item);
  ans += $item.html() + '<br/><br/>';
});
// 将内容呈现到页面
res.send(ans);

我们让问题再清晰些,试着把爬虫代码稍做修改:

var $ = cheerio.load(sres.text);var ans = [];
$('.titlelnk').each(function (index, item) {
  var $item = $(item);
  ans.push($item.html());
});
// 将内容呈现到页面
res.send(ans);

HTML 实体编码

在 HTML 中,某些字符是预留的,比如不能使用小于号(<)和大于号(>),这是因为浏览器会误认为它们是标签。如果希望正确地显示预留字符,我们必须在 HTML 源代码中使用字符实体(character entities)。当然还另一个重要原因,有些字符在 ASCII 字符集中没有定义,因此需要使用字符实体来表示,比如中文。

字符实体类似这样:

&entity_name;

 

或者

 

&#entity_number;

如需显示小于号,我们必须这样写:< 或 <。前者(实体名)易于记忆,而后者(实体数字)在浏览器中的支持较好。

HTML 中常见的需要替换成字符实体的字符有 4 个,分别是 <、>、& 以及 "。为此,我们可以简单写个 escapeHTML 函数(使得网页上可以正确显示这 4 个字符,而不会被误认为是标签):

function escapeHTML(text) {  
    var replacements= {"<": "<", ">": ">","&": "&", """: """};                      
    return text.replace(/[<>&"]/g, function(character) {  
        return replacements[character];  
    });
}

更多关于 HTML 实体编码的内容可以参考 HTML 字符实体

Solution

不仅是 "<" ">" 这样的能编码,所有字符均能编码,这也是出现 "乱码" 的原因。在文章开头的例子中,其实它把该 target 标签内的所有东西(包括中文)都给编码了。

而最开始的代码(字符串输出)之所以没有 "乱码",完全是因为浏览器自动帮你解码了。(如果存在于 HTML 代码中,会被自动解码)

知道了原因,我们可以从两个方向解决问题。

首先,我们可以不对其内容进行编码。用 text() 方法取代 html() 方法:

$('.titlelnk').each(function (index, item) {
  var $item = $(item);
  ans.push($item.text());
});

很简单并且完美地解决了这个问题。

或者我们关闭 cheerio 中的 .html() 方法 转换实体编码的功能:

var $ = cheerio.load(sres.text, {decodeEntities: false});
$('.titlelnk').each(function (index, item) {
  var $item = $(item);
  console.log($item.html());
});

如果说不能从编码的角度解决,我们可以试着解码。

方法一:

创建空标签,将编码内容用 html() 方法塞入,用 text() 取出,转换过程让第三方完成(当然前提是获取了 $ 对象):

  function htmlDecode(str) {
    var t = $("<div></div>");
    t.html(str);
    return t.text();
  }
 
  var $ = cheerio.load(sres.text);
  var ans = [];
  $('.titlelnk').each(function (index, item) {
    var $item = $(item);
    ans.push(htmlDecode($item.html()));
  });
 
  // 将内容呈现到页面
  res.send(ans);

方法二:

根据编码转换规则,用正则 decode:

function htmlDecode(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;
}
var $ = cheerio.load(sres.text);var ans = [];
$('.titlelnk').each(function (index, item) {
  var $item = $(item);
  ans.push(htmlDecode($item.html()));
});
// 将内容呈现到页面
res.send(ans);

Encode & Decode

事情到此似乎可以告一段落,我们找到了问题的原因,也找到了解决办法。但是,HTML 实体编码,它到底是如何编码的?

我们任意取一条标题:

前端备忘录 — IE 的条件注释

编码后为:

&#x524D;&#x7AEF;&#x5907;&#x5FD8;&#x5F55; &#x2014; IE &#x7684;&#x6761;&#x4EF6;&#x6CE8;&#x91CA;

中文的编码结果开头都是 &#x。试着用 charCodeAt() 取得 "前" 字的 unicode 编码大小,然后将它转成 16 进制,正是 524d !看来和 escape() 相似,又是一次十六进制的转换。

但是英文却没有被转,这点和 escape() 也神似。唯一不同的是 escape 会将空格转为 %20,而 HTML 编码并没有。

而且 HTML 编码甚至会将   自动编码成  ,这也就意味着如果要手写个 HTML 编码函数,需要将所有字符实体的映射都找出来,而且对于 &XXXX 形式的,似乎还要作个校验(确认是实体集还是普通的字符串)。

而 HTML 解码则相对来说简单写,只需将 &#xXXX 进行转换,详细代码可以参考 Solution 一节的正则。

事实上,HTML 编码并不一定要转成十六进制,十进制也可以。还是以 "前" 为例,它的十进制 unicode 码为 21069,完全可以用 前 来代替 前。

最后还有两个客户端的编码、解码函数:

function HtmlEncode(str) {
    var t = document.createElement("div");
    t.textContent ? t.textContent = str : t.innerText = str;
    return t.innerHTML;
}
function HtmlDecode(str) {
    var t = document.createElement("div");
    t.innerHTML = str;
    return t.textContent || t.innerText;
}

真的是吃一堑长一智,以后碰到 "&#x" 开头的一些编码,十有八九是 HTML 的实体编码,再也不用担心了!

Read More:

· html 实体编码问题

· HTML字符实体(Character Entities),转义字符串(Escape Sequence)


本文由职坐标整理并发布,了解更多内容,请关注职坐标WEB前端HTML/CSS频道!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程