在字体反爬过程中,解析页面时,使用正则表达式可以匹配到网页源码中的字体代码,如下所示:
print(re.findall(r'<span class="day font".*?>(.*?)</span>', rsp.text)[0]) # 结果:/天
而使用xpath解析,得到的却是Unicode字符串列表:
html = etree.HTML(rsp.text)
res = html.xpath('//span[@class="day font"]/text()') # ['\ue412\uf359\uf359/天']
遍历结果为乱码:
print(res[0]) # 结果:/天
使用bs4解析,输出的也是乱码,如下所示:
soup = BeautifulSoup(rsp.text, 'lxml')
sal = soup.select('span.day.font') # [<span class="day font" data-v-98c756d6="">/天</span>]
print(sal[0].text) # 结果:/天
若在bs4下继续使用正则匹配,匹配结果也是Unicode字符串列表,遍历输出也是乱码
那么问题来了:请问,都是从源代码中解析,为什么后两种解析方式得到的是Unicode而得不到字体代码啊?
以unicode e412
为例
在HTML中
<p>

</p>
在python中
'\ue412'
以上代码表达了同一个意思:unicdeo中的e412字符
然后在浏览器渲染(html)和打印的时候(python),会渲染出e412所代表的字符,也就是说:
源码中显示e412,显示时显示字符
etree和bs4 做的事情
在这个过程中,它们会将HTML语法表达的字符,改为python语法表达的字符,以便解析和输出
lxml.etree 中的解析器可以立即处理 unicode 字符串
在将 XML/HTML 数据传递到解析器之前,您通常应该避免将手动转换为 unicode
--- by lxml 官网
也就是说 
会被替换为 \ue412
(这样显示效果才一样)
那么问题来了:为什么使用正则就不会这样呢?
因为&xxxx
是HTML的语法,正则根本就识别不出来这是在表示unicode,当然就忽略了
如果它知道这个是表示unicode,说不定会有所作为。。。
可能你想在etree和bs4 做元素定位 之后,拿到一个可以在浏览器显示的版本,有两种思路:
\uxx
替换为 &xxx
)代码示例
from lxml import etree
raw_html = "<p>/天</p>" # 原始HTML内容
html = etree.HTML(raw_html)
x = html.xpath("//p/text()")[0] # 获取内容 (unicode)
print(x) # 展示unicode字符
print(x.encode("unicode-escape").decode()) # 转为Python中unicode语法
print(x.encode("unicode-escape").decode().replace("\\u", "&#")) # 转为HTML中unicode语法
输出结果,注意字符串中的汉字也被转为了unicode代码:
/天
\ue412\uf359\uf359/\u5929
&#e412&#f359&#f359/ᜩ
如果帮助,还请点击【采纳】,支持一下
参考链接: