网页乱码的分界不在1024字节,做SEO的脚本比浏览器早八千字节就瞎了

网页乱码的分界不在1024字节,做SEO的脚本比浏览器早八千字节就瞎了
张文保 更新 26 分钟阅读 1,172 阅读
本文目录
  1. 那条传了十几年的1024字节规矩,今天还成立吗?
  2. 但同一批字节,工具那边是另一副样子
  3. 实验台是怎么搭的
  4. 规范到底把这个窗口写成了什么?
  5. 把声明推到128 KB,浏览器为什么还认得出来?
  6. 后路一:推倒重来
  7. 后路二:自动检测
  8. UTF-8凭什么能被认出来,GBK就不行
  9. 同一批字节喂给五种工具,谁先瞎掉?
  10. requests的.text:从第一个字节起就没对过
  11. html.parser:第8192字节是它的悬崖
  12. lxml和html5lib:位置上不输浏览器,却栽在不声明上
  13. 只读前1 KB:那条规矩真正的归属
  14. 三个地方都能写编码,到底听谁的?
  15. 把这条链翻译成排查顺序
  16. meta有两种写法,长度差三倍
  17. 121个站的编码声明,都写在什么位置?
  18. 位置分布:绝大多数写得很靠前
  19. 越过1024那条线的8个站
  20. 但这8个站一个都没出事
  21. 顺带三条小观察
  22. 为什么PHP站几乎踩不到这个坑?
  23. 兜底还不止一层
  24. 那么真正会翻车的,是哪一类站?
  25. 迁移期是高发窗口
  26. 抓取管道这一侧的风险,比浏览器那侧高得多
  27. 搜索结果里的表现
  28. 不用查十六进制也行:乱码的形状会告诉你是哪一层错了
  29. 该按什么顺序查,又该怎么配才稳?
  30. 排查:四步,按优先级从高到低
  31. 配置:三条就够
  32. 写脚本时的三条硬规矩
  33. 常见问题解答
  34. 编码声明必须写在前1024字节以内吗?
  35. 响应头和meta都写了编码,但两边不一样,听谁的?
  36. 为什么我用requests抓中文站全是乱码?
  37. 页面完全不写编码声明会怎样?
  38. 用BeautifulSoup抓页面,选哪个解析器不容易踩编码的坑?
  39. 我的站是PHP做的,需要专门配编码吗?
  40. 页面乱码变成一串生僻汉字,和变成方块有什么区别?
  41. 把gb2312改写成GBK会有影响吗?
  42. CDN会不会把编码这件事搞坏?
  43. 怎么确认搜索引擎抓回去的是不是乱码?
  44. 权威参考资料

摘要:保哥搭了个实验台,把编码声明一格一格往后推,推到第131072字节浏览器照样认得出来,中文一个都没花。可同一批字节喂给做SEO常用的那几个Python库,有的在第8192字节就崩了,有的从第一个字节起就没对过。规范里那个1024的数字确实写着,只是它管的不是浏览器最终显示什么,而是预先扫一眼那一步。真正说了算的顺序是:字节顺序标记、HTTP响应头、然后才轮到meta。

那条传了十几年的1024字节规矩,今天还成立吗?

只要搜过网页乱码,八成会撞见这句话:编码声明必须写在HTML的前1024字节以内,否则浏览器就来不及了。这句话有出处,规范里确实有这个数字。

保哥想验一下它今天还准不准,于是在服务器上另起了一个nginx,把编码声明用注释填充一格一格往后推:1000、1024、1030、2048、4096、8192,一直推到131072字节。正文是同一段中文,用GBK编码发出去,声明写gb2312。然后拿真实浏览器一个个打开,读 document.characterSet

结果是全部正确识别,一个字都没乱。128 KB的偏移,是规范那个数字的128倍。

但同一批字节,工具那边是另一副样子

把同样这些页面喂给平时写SEO脚本会用的几个库,画风立刻变了。有的在第8192字节崩掉,有的压根就没对过一次。这就是本篇要处理的那道裂缝:页面在浏览器里好好的,在你的抓取工具里是一堆问号,两边都没坏。

这和head的边界由解析器判定是同一个母题的两半——一个是位置,一个是字节窗口。区别在于,那一篇里浏览器和工具的分歧是结构上的,这一篇里的分歧直接体现成能不能读懂中文。

实验台是怎么搭的

这类问题必须自己造样本,因为现网找不到干净的对照——你没法让别人的站把声明挪一挪再让你测一次。

做法是在服务器上另起一个nginx,只发静态文件,开三个端口,唯一的区别是响应头怎么发:

端口Content-Type用途
第一个裸的text/html,不带charset主实验组,让规范的嗅探算法真正跑起来
第二个text/html; charset=utf-8对照组,测响应头的优先级
第三个text/html; charset=gb2312反向对照组

页面这边生成了50多个静态文件:编码声明的偏移从0一格格推到131072,正文分UTF-8和GBK两套,另外几个专测不声明和字节顺序标记。每个文件里嵌一小段脚本,把 document.characterSet 读出来显示在页面上,这样浏览器最终用了什么编码是它自己报的,不是我猜的。

为什么非得另起一个nginx,而不是在生产站上开个目录,后面那节会讲——那本身就是本篇的一个发现。

规范到底把这个窗口写成了什么?

去翻HTML标准的解析章节,1024出现在一个叫预扫描字节流以确定其编码的小节里。它规定的动作是:在正式解析之前,先拿前面一段字节快速扫一眼,找有没有meta声明;这一段的长度由实现决定,标准给的建议值是1024字节。

关键在于,预扫描只是整个编码嗅探算法里的一步,而且是排在后面的那一步。完整顺序是这样的:

顺序依据说明
1字节顺序标记文件开头那三个字节,优先级最高,谁也盖不过它
2HTTP响应头里的charset服务器说的,压过页面里写的
3预扫描前1024字节找meta就是那条广为流传的规矩
4自动检测或地区默认值前三步都没结果时的兜底

还有一条常被漏掉的:预扫描没找到,不代表事情就结束了。标准明确写了,解析过程中如果后来遇到了一个跟当前编码不一致的meta声明,用户代理可以改变编码——办法是把整个导航算法重跑一遍。这一条就是浏览器能在128 KB之后翻盘的依据。

把声明推到128 KB,浏览器为什么还认得出来?

因为它有两条后路,而工具通常一条都没有。

后路一:推倒重来

预扫描扫不到,浏览器先用猜的编码开始解析;解析到那个meta时发现猜错了,就把已经建好的树全扔掉,换正确的编码从头再解析一遍。用户看到的只是一次略慢的加载,看不到中间那次作废。

这也解释了为什么这条规矩虽然过时了,但把声明写在最前面依然值得做:你省下的是一次整篇重解析。声明在第82字节和在第8万字节,最终显示一样,中间的功夫差着一整轮。

这里得把话说严谨:保哥没有量这次重解析到底多花了几毫秒。实验台的页面只有几KB,量出来的差值淹没在噪声里,没有参考价值。要在真实的几百KB页面上做这个测量,得隔离掉网络、缓存和渲染的干扰,那是另一个题目。所以这里只说机制上多跑了一轮,不给数字——上一篇里那些落点结论是二值的、量得准,性能这一项不是,就别硬凑。

后路二:自动检测

实验台上还放了一组完全不声明编码的页面。UTF-8那一份,浏览器判成UTF-8,中文正常;GBK那一份,浏览器判成UTF-8,中文全成了方块。

页面meta声明HTTP头浏览器判定中文
UTF-8正文UTF-8正常
GBK正文UTF-8乱码
UTF-8正文推到131072UTF-8正常
GBK正文推到131072GBK正常

UTF-8的字节序列有很强的自校验特征,猜错的概率极低,所以现代浏览器对它基本免疫。GBK就没这个待遇——它的字节看上去和一堆别的编码没什么两样,不声明就只能靠蒙。

这张表其实已经把结论给出来了:如果你的站是UTF-8,这一整套机制大概率轮不到你操心;如果站里还有GBK的老页面,声明就是唯一的生命线。

UTF-8凭什么能被认出来,GBK就不行

这不是浏览器偏心,是两种编码的结构不一样。

UTF-8的每个多字节序列都有固定形状:首字节的高位标明这个字符总共几个字节,后续字节的高两位必须是10。一段随机字节要想通篇满足这个约束,概率低到可以忽略。所以扫一遍全文,只要没出现违规组合,判成UTF-8几乎不会错。

GBK就没有这种冗余。它的双字节范围和别的东亚编码大量重叠,同一串字节用GBK、Big5、Shift_JIS解出来都是“看着像字”的结果,只是内容完全不同。老编码页面那笔账里西里尔字母那几套编码是一样的道理——单靠字节分不出来,只能靠声明。

顺带解释一个常见困惑:为什么有的地方写gb2312、有的写GBK,结果好像都一样。因为编码标准里把gb2312这个标签直接映射到了GBK的解码器,两个名字对应同一套实现。写哪个都行,但既然实际能力是GBK,写GBK更诚实。

同一批字节喂给五种工具,谁先瞎掉?

浏览器有后路,脚本没有。保哥把实验台上那批页面原样抓下来,喂给五种最常见的消费方式。

声明位置requests的.texthtml.parserlxmlhtml5lib只读前1 KB
第0字节乱码正常正常正常找得到
第1000字节乱码正常正常正常找得到
第1024字节乱码正常正常正常找不到
第2048字节乱码正常正常正常找不到
第8192字节乱码乱码正常正常找不到
第65536字节乱码乱码正常正常找不到
第131072字节乱码乱码正常正常找不到
完全不声明乱码正常乱码乱码找不到

四列四种败法,值得逐个说。

requests的.text:从第一个字节起就没对过

13组测下来无一例外全是乱码,而且它自报的编码一律是ISO-8859-1。原因是老规矩:HTTP响应头里是text类型但没写charset时,按上古版本的规定默认ISO-8859-1。它完全不看HTML里的meta——那不在它的职责范围内,它只是个HTTP客户端。

这条最值得警惕,因为 r.text 是所有教程里的第一行代码。用它去抓一个没在响应头声明编码的中文站,抓回来的每个字都是错的,而程序不会报任何错。正确写法是把字节交出去,让解析器自己定:

# 会乱码:requests 按 ISO-8859-1 解,完全不看 meta
soup = BeautifulSoup(r.text, 'lxml')

# 正确:把原始字节交给解析器,由它按标准嗅探
soup = BeautifulSoup(r.content, 'lxml')

一个 .text 换成 .content,差别就是整站中文对不对。

html.parser:第8192字节是它的悬崖

Python自带那个解析器在1024之后还撑了很久,一直到8192才崩。保哥把这个边界二分了一遍:

声明起始位置声明结束位置结果
第8100字节第8122字节正常
第8150字节第8172字节正常
第8180字节第8202字节乱码
第8192字节第8214字节乱码

分界卡在8150和8180之间,而 <meta charset="gb2312"> 这串正好22字节:8150加22是8172,还在8192以内;8180加22是8202,出界了。所以它的窗口是8192字节,而且要求整条声明完整落在窗口里,露出去一个字符都不行。

于是三个数字凑齐了,而且互不相同:

  • 规范建议的预扫描窗口:1024 字节
  • Python自带解析器的实际窗口:8192 字节
  • 浏览器实测仍能翻盘的位置:至少 131072 字节

lxml和html5lib:位置上不输浏览器,却栽在不声明上

这两个库对声明位置完全不敏感,推到128 KB照样识别,跟浏览器打平。但页面完全不声明编码时,它们两个都乱,而浏览器正常。差的就是那条自动检测的后路——库不做这件事,因为它们拿到的只是一段字节,没有浏览器那套上下文。

只读前1 KB:那条规矩真正的归属

最后一列模拟的是流式管道:只取前1024字节,用正则找编码声明,找不到就用默认值。这一列的表现完全符合规范那条1024的描述——超过就是找不到。

这一列的存在解释了那条规矩为什么会流传这么久:它准确描述了预扫描这一步,而今天真正只做预扫描、不做重启的,是工具,不是浏览器。规矩没错,只是它管的对象在这十几年里换人了。

三个地方都能写编码,到底听谁的?

实验台开了三个端口,唯一区别是响应头怎么发:一个发裸的text/html不带charset,一个发charset=utf-8,一个发charset=gb2312。同一批文件,三个端口各跑一遍。

响应头文件实际编码meta声明字节顺序标记浏览器判定中文
gb2312UTF-8utf-8(第0字节)GBK乱码
utf-8GBKgb2312(第0字节)UTF-8乱码
gb2312UTF-8gb2312UTF-8正常
GBKgb2312GBK正常

前两行是一组对称的实验:meta写在第0字节,位置不能再靠前了,照样一个字都不算数——响应头一发话,meta就出局。第三行更狠:响应头说gb2312、meta也说gb2312,两边一致,结果那三个字节的标记把两边一起否了。

把这条链翻译成排查顺序

  1. 先看响应头。一条命令的事:curl -sI 你的地址 | grep -i content-type。这里写的是什么,页面里写什么基本无关。
  2. 再看文件头三个字节。有标记就以标记为准,而且它会盖掉响应头编辑器悄悄加上的那三个字节能引发的麻烦不止白屏这一种。
  3. 最后才看meta。前两步都没声明,它才轮得上。

顺带说个反直觉的:现网121个站里带字节顺序标记的是0个。这东西优先级最高,但没人主动用它,它只会在你不知情的时候混进来。

meta有两种写法,长度差三倍

同一件事,HTML里有两种写法:

写法字节数说明
<meta charset="utf-8">22HTML5的短写法
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">68老写法,效果完全相同

两者等价,预扫描都认。但在窗口这件事上,长的那个天生吃亏——它自己就占掉68字节,而且它整条都必须落在窗口里才算数,露出去一个字符就前功尽弃。前面二分出来的那个8192边界,卡的正是声明的结束位置而不是起始位置。

老模板里这两种写法并存的情况很常见,有的还两条都写。两条都写不算错,解析器取先出现的那条,但它平白多占了几十字节的窗口预算。

121个站的编码声明,都写在什么位置?

光有实验台不够,得看看真实世界长什么样。同一批125个域名的首页,抓到并解析成功121个。

位置分布:绝大多数写得很靠前

分位meta charset的字节偏移
最靠前第28字节
四分之一分位第44字节
中位第82字节
四分之三分位第197字节
九成分位第690字节
最靠后第311364字节

九成分位还在690,说明主流做法是把它写在最前面。但尾巴拖得非常长。

越过1024那条线的8个站

站点类型声明位置是规范窗口的几倍
某新闻门户第311364字节304倍
某综合电商第5124字节5倍
某科技媒体第3408字节3.3倍
某鞋类电商第2761字节2.7倍
某邮件营销平台第2012字节2倍
某建站平台第1986字节1.9倍
某体验研究机构第1410字节1.4倍
某搜索资讯站第1212字节1.2倍

8个站,占写了meta那114个站的7%。第一名那个新闻门户尤其离谱,它的 </head> 落在第2398966字节,整个head有2.3 MB,编码声明埋在里面第31万字节的位置。

但这8个站一个都没出事

因为它们的HTTP响应头里全部写了charset=utf-8。按前面那条优先级链,响应头一发话,meta在第几字节根本无所谓。

把这个交叉做完,得到本篇最该记住的一个数字:meta超窗口、同时HTTP头又没声明——这个真正致命的组合,121个站里命中0个。

组合站数
响应头与meta都写了,且两边一致103
响应头与meta都写了,但不一致0
只有响应头,没写meta6
只有meta,响应头没写11
两处都没写1

那103个站里,meta其实一个字都没起作用——它们真正生效的是响应头。而真正靠meta活着的只有11个站,这11个才是需要关心声明位置的。至于两处都没写的那一个,它是个几KB的跳转壳子,正文没有中文,蒙对蒙错都无所谓。

顺带三条小观察

  • 声明的值高度统一:113个站写utf-8,1个写utf8(少了个连字符,标准的编码标签表里两者都认,不影响)。
  • 5个站把 <title> 排在了charset前面,偏移分别是32对85、43对208、50对136、70对149,还有一个是1905对1986。前四个差距很小无关痛痒,最后那个把两者一起推过了1024。
  • 7个站压根没写meta charset,全靠响应头。meta标签体检工具大概率会给它们扣分,可它们一点问题都没有。

为什么PHP站几乎踩不到这个坑?

这个发现是在搭实验台时被迫撞出来的。

保哥一开始用PHP写测试页,代码里明明白白只发了 Content-Type: text/html,不带charset。结果curl一看,响应头是 text/html;charset=UTF-8

查下来是PHP的 default_charset,出厂值就是UTF-8,它会自动往Content-Type里补上。也就是说,只要页面是PHP输出的,编码声明这件事默认就已经被兜住了,你在HTML里写不写、写在第几字节,全都无所谓。

兜底还不止一层

兜底层默认行为怎么确认
PHP的default_charset出厂UTF-8,自动补进响应头php -i | grep default_charset
nginx的charset指令出厂是off,但面板类环境普遍开着查配置里有没有charset那一行
CDN或反向代理各家不同,有的会重写对比源站与边缘的响应头

为了让规范行为真正跑起来,保哥最后是另起了一个nginx、把charset关掉、只发静态文件,才拿到那个裸的 text/html换句话说,今天想在生产环境里复现这个经典坑,得先拆掉两层保险。这也从侧面解释了为什么现网121个站的致命组合是0。

反过来说,风险最高的恰恰是那些没有这两层兜底的场景:纯静态站点直接由CDN发出、对象存储托管的页面、把HTML当附件下发的接口。这些地方响应头里有没有charset,取决于上传时那个Content-Type元数据填了什么,而那个字段经常是空的。

那么真正会翻车的,是哪一类站?

把前面所有条件叠在一起,能筛出一个很窄的画像。同时满足这四条才会出事:

  1. 正文不是UTF-8(在中文语境里,基本等于GBK或GB2312的老页面)
  2. HTTP响应头里没有charset
  3. 没有字节顺序标记
  4. meta声明写得太靠后,或者压根没写

四条同时成立的站确实少,但它有个特点:一旦成立,中招的往往是整站,不是一两个页面。因为这四条全是站级配置。

迁移期是高发窗口

最典型的场景不是“一直这样”,而是“刚改过”。老站从GBK迁到UTF-8的过程中,正文已经转好了,响应头还留着gb2312;或者反过来,静态文件换了服务器,新服务器不发charset了。老编码页面迁移那笔账里最容易漏的就是这一步——大家都盯着文件本身转没转,很少有人回头查响应头。

抓取管道这一侧的风险,比浏览器那侧高得多

把前面那张五工具对照表再看一遍,会发现一件事:浏览器是这条链上唯一有两条后路的角色,其余全靠声明。而今天读你页面的东西里,浏览器占的比例正在下降。

消费方能重启解析吗能自动检测吗
浏览器
搜索引擎的渲染环节用的是浏览器内核,能
只抓HTML不渲染的那一遍看实现,多数不能看实现
各类审计工具、脚本基本不能基本不能
只读前N字节的流式管道不能不能

这张表和抓取与渲染分几步那套模型是叠在一起的:渲染那一遍问题不大,先抓HTML那一遍才是薄弱环节。而先抓的那一遍决定了标题和描述最初被记成什么。

搜索结果里的表现

编码错了,页面标题和描述抓回去就是一串认不出的字符,直接进搜索结果。这类问题的排查特征很鲜明:

  • 浏览器里打开完全正常,因为它有重启解析和自动检测两条后路
  • 抓取工具、第三方审计平台看到的是乱码,因为它们没有
  • 你去问同事,一半人说没问题,一半人说满屏方块,取决于他们用什么打开的

遇到这种各执一词的场面,别急着判断谁看错了。直接把字节调出来看十六进制,是唯一不会骗人的办法——中文字符在UTF-8里是三个字节、在GBK里是两个字节,一眼就能分。

不用查十六进制也行:乱码的形状会告诉你是哪一层错了

实验台上两个方向的错配都跑了一遍,同一句中文,乱出来的样子完全不同。

错配方向乱码形态为什么长这样
UTF-8的字节被当成GBK解一串生僻汉字,例如“淇濆摜鐨勭紪鐮佺”三个字节被切成一个半汉字,每两字节凑出一个真实存在但毫不相干的字
GBK的字节被当成UTF-8解一串方块或问号,例如“����”字节不满足UTF-8的结构约束,解码器只能吐出替换字符

这就是“网页乱码为什么会变成生僻字”这个问题的答案。看见生僻汉字,说明内容是UTF-8而声明说了GBK;看见方块和问号,说明内容是GBK而声明说了UTF-8。方向一眼就能定,剩下的只是去查是响应头写错了还是meta写错了。

还有第三种形态值得一并记住:整页只有中文乱、英文和数字完全正常。这说明编码错配确实存在,因为这两套编码对ASCII范围的处理是一样的。如果连英文都乱了,那多半不是编码问题,该去查是不是文件本身损坏或者被压缩过一次没解开。

顺便,地址栏里的中文是另一笔账,走的是百分号转义那套规则,和页面编码不是同一回事。中文网址的编码看起来相似,排查路径完全不同,别混在一起查。标题里那些特殊符号跨平台显示不一致也是独立的一类,属于字体和字符集支持问题,不是解码错配。

该按什么顺序查,又该怎么配才稳?

排查:四步,按优先级从高到低

  1. 查响应头。curl -sI 看Content-Type有没有charset、写的是什么。有的话,它就是答案,后面几步只是确认一致性。
  2. 查前三个字节。curl -s 地址 | head -c 3 | xxd,出现 efbbbf 就是有标记。它会盖掉响应头。
  3. 查meta的偏移。不只是看写没写,要看写在第几字节。把原始字节存下来搜一次位置即可。
  4. 用两种解析器各跑一遍。结果不一致的地方,就是你的工具链和浏览器分道扬镳的地方。

配置:三条就够

  • 把charset写进响应头,这是唯一真正稳的一条。它优先级高、和页面内容解耦、改一次全站生效。nginx加一行charset指令,PHP站默认就有。
  • meta照旧写,位置尽量靠前。它是响应头缺失时的兜底,也是页面被另存为本地文件之后唯一的依据——那时候响应头已经不存在了。
  • 别主动加字节顺序标记。它优先级最高、最难排查,而且在某些场景会引发别的麻烦。真要保险,靠响应头。

写脚本时的三条硬规矩

  • r.content,不要拿 r.text。这一条能挡掉最多的事故。
  • 别用只读前N字节找声明的写法做全站判断,除非你确定这批站的声明都写在最前面。
  • 如果结论要拿去和浏览器里看到的对齐,记得工具没有重启解析和自动检测这两条后路,差异是系统性的,不是偶发。

常见问题解答

编码声明必须写在前1024字节以内吗?

对浏览器来说不必须。实测把声明推到第131072字节,浏览器照样正确识别,因为它可以推倒重来。但对只做预扫描的工具来说这条仍然成立,而且不同工具的窗口还不一样。写在最前面依然是最省事的做法,它省下的是一次整篇重解析。

响应头和meta都写了编码,但两边不一样,听谁的?

听响应头的。实测里meta写在第0字节都无效,响应头说gb2312就按gb2312解。所以两边不一致时,改meta是没用的,得去改服务器配置。

为什么我用requests抓中文站全是乱码?

大概率是用了 r.text。响应头没写charset时,requests按老规矩默认ISO-8859-1,而且它完全不看HTML里的meta。把 r.text 换成 r.content 交给解析器,问题就没了。

页面完全不写编码声明会怎样?

UTF-8的正文基本没事,浏览器的自动检测认得出来。GBK的正文会被判成UTF-8,中文全花。而且这一档lxml和html5lib也会乱,它们不做自动检测。

用BeautifulSoup抓页面,选哪个解析器不容易踩编码的坑?

在编码这件事上,lxml和html5lib都比Python自带那个强,两者对声明位置都不敏感。自带那个在第8192字节就会崩。但更重要的是喂给它原始字节而不是已经解错的字符串。

我的站是PHP做的,需要专门配编码吗?

基本不用。PHP的default_charset出厂就是UTF-8,会自动往响应头里补charset。真正要留意的是纯静态站点、对象存储托管的页面,还有CDN会不会把响应头改掉。

页面乱码变成一串生僻汉字,和变成方块有什么区别?

方向正好相反。生僻汉字说明内容是UTF-8而被当成了GBK解,三个字节被切成一个半汉字;方块和问号说明内容是GBK而被当成了UTF-8解,字节不满足UTF-8的结构约束只能吐替换字符。看一眼形状就能定方向,不用查十六进制。

把gb2312改写成GBK会有影响吗?

没有。编码标准里gb2312这个标签本来就映射到GBK的解码器,两个名字对应同一套实现。写GBK更贴近实际能力,但改不改都不影响解码结果。

CDN会不会把编码这件事搞坏?

会,而且方向是双向的:有的边缘节点会补上源站没写的charset,有的会把源站写的换掉。判断办法是绕过边缘直连源站再取一次响应头,两边对比。做整站审计时这一项值得单列,因为它改的是全站每一个页面。

怎么确认搜索引擎抓回去的是不是乱码?

不要用浏览器确认,它有两条后路会替页面把问题遮住。用curl拿原始字节,按响应头声明的那个编码去解一次,看中文对不对。直接看响应头这一类工具比在浏览器里点右键有用得多。

权威参考资料

分享到
标签
版权声明

本文标题:《网页乱码的分界不在1024字节,做SEO的脚本比浏览器早八千字节就瞎了》

本文链接:https://zhangwenbao.com/charset-declaration-byte-window-parser-encoding-seo.html

版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交