处理结果:
关于字体
字体文件里记录有字形索引和字形的映射关系, 保存在字体的 cmap 表里, 有关字体详细资料看下面链接: https://www.cnblogs.com/shenyiyangle/p/10700156.html
乱码原因
我们在浏览器看到乱码是因为网站加载了自定义字体, 字体字形 dindex 和 glphy 映射关系和默认字体的映射不一样, 网站按照自定义字体里的映射关系来表示数据, 而我们抓到的数据用默认字体解析, 因为映射关系不同, 网站的 unicode 索引指向默认字体里的其他字形, 所以我们看到的数据是错的.
解决方法
解决问题需要建一张关系表, 如果字形不变可以让自定义字体的 unicode 索引与默认字符对应, 然后用默认字符替换自定义字体的 unicode 索引, 这样就能在页面上显示正常数据. 关系如下图:
找关系
用到了 TTFont 库, 可以解析字体
- font = requests.get(font_url, headers=header, timeout=30)
- font_name = font_url.split("/")[-1]
- with codecs.open(font_name, 'wb') as f:
- f.write(font.content)
- font_map = TTFont(font_name).getBestCmap()# 用 getBestCmap() 可以得到字体 index 和 glphy 的映射关系
- """{120:'x',
- 57960: 'bgldyy',
- 57971: 'qqdwzl',
- 58817: 'whyhyx',
- 59299: 'wqqdzs',
- 60397: 'zbxtdyc',
- 60633: 'zwdxtdy',
- 60650: 'zrwqqdl',
- 61125: 'bdzypyc',
- 62069: 'sxyzdxn',
- 62669: 'nhpdjl'}"""
font_map 里的就是自定义字体索引和字形的关系, key 是 index,value 表示字形.
unicode 代码就是字体 index 进行十六进制转化后将 0X'替换成'&#x',font_map 里的 index 转换成 unicode 如下:
- font_index = [hex(key).upper().replace('0X', '&#x') +';' for key in font_map.keys()]
- """['x',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '',
- '']"""
上面代码得到了自定义字体的关系, 还需要 unicode 索引和和默认字符的关系, 东方财富网直接写在页面上了.
- font_mapping = json_data['font']['FontMapping']
- font_mapping = {i['code']: str(i['value']) for i in font_map}
- """{'':'7',
- '': '1',
- '': '9',
- '': '3',
- '': '4',
- '': '8',
- '': '2',
- '': '0',
- '': '6',
- '': '5'}
- """replace_dict= {hex(k).upper().replace('0X','&#x') +';': str(font_mapping[hex(k).upper().replace('0X','&#x') +';'])for k in font_map.keys()}
- """{'x':'.',
- '': '7',
- '': '1',
- '': '9',
- '': '3',
- '': '4',
- '': '8',
- '': '2',
- '': '0',
- '': '6',
- '': '5'}"""
- # 最后直接在文章中替换, key 换成 value.
- for k, v in replace_dict.items():
- json_str = json_str.replace(k, v)
- finall_data = JSON.loads(json_str)
结果:
已得到正确数字了.
最后筛选需要的字段筛选数据并将数据存入数据库, 导出数据保存成 CSV 用 Excel 打开结果.
来源: https://www.cnblogs.com/shenyiyangle/p/10702693.html