巴小迪 2021-09-22 15:54 采纳率: 75%
浏览 87
已结题

正则,xpath,bs4匹配

正则

在字体反爬过程中,解析页面时,使用正则表达式可以匹配到网页源码中的字体代码,如下所示:

print(re.findall(r'<span class="day font".*?>(.*?)</span>', rsp.text)[0])  # 结果:&#xe412&#xf359&#xf359/天

Xpath

而使用xpath解析,得到的却是Unicode字符串列表:

html = etree.HTML(rsp.text)
res = html.xpath('//span[@class="day font"]/text()')  # ['\ue412\uf359\uf359/天']

遍历结果为乱码:

print(res[0])  # 结果:/天

bs4

使用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而得不到字体代码啊?

  • 写回答

1条回答 默认 最新

  • 咕泡-三木 2021-09-22 16:58
    关注

    一、本质原因是Unicode在HTML中和Python中的不同表示方法

    以unicode e412为例
    在HTML中

    <p>
    &#xe412 
    </p>
    

    在python中

    '\ue412'
    

    以上代码表达了同一个意思:unicdeo中的e412字符
    然后在浏览器渲染(html)和打印的时候(python),会渲染出e412所代表的字符,也就是说:
    源码中显示e412,显示时显示字符

    二、再来看一下问题中描述的现象

    etree和bs4 做的事情

    1. 它们会闭合各种标签,构造完整对称的HTML
    2. 解析HTML,构造为对象,并提供各种选择器方法

    在这个过程中,它们会将HTML语法表达的字符,改为python语法表达的字符,以便解析和输出

    lxml.etree 中的解析器可以立即处理 unicode 字符串
    在将 XML/HTML 数据传递到解析器之前,您通常应该避免将手动转换为 unicode
    --- by lxml 官网

    也就是说 &#xe412 会被替换为 \ue412 (这样显示效果才一样)


    那么问题来了:为什么使用正则就不会这样呢?
    因为&xxxx 是HTML的语法,正则根本就识别不出来这是在表示unicode,当然就忽略了
    如果它知道这个是表示unicode,说不定会有所作为。。。

    三、如何不进行替换?

    可能你想在etree和bs4 做元素定位 之后,拿到一个可以在浏览器显示的版本,有两种思路:

    1. 让lxml忽略的unicode的处理 (理论上可行,但是没有找到相关说明)
    2. 将内容重新处理为HTML语法的表达方式 (\uxx替换为 &xxx

    代码示例

    from lxml import etree
    
    raw_html = "<p>&#xe412&#xf359&#xf359/天</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/&#5929   
    

    如果帮助,还请点击【采纳】,支持一下

    参考链接:

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 10月2日
  • 已采纳回答 9月24日
  • 创建了问题 9月22日

悬赏问题

  • ¥15 腾讯IOA系统怎么在文件夹里修改办公网络的连接
  • ¥15 filenotfounderror:文件是存在的,权限也给了,但还一直报错
  • ¥15 MATLAB和mosek的求解问题
  • ¥20 修改中兴光猫sn的时候提示失败
  • ¥15 java大作业爬取网页
  • ¥15 怎么获取欧易的btc永续合约和交割合约的5m级的历史数据用来回测套利策略?
  • ¥15 有没有办法利用libusb读取usb设备数据
  • ¥15 为什么openeluer里面按不了python3呢?
  • ¥15 关于#matlab#的问题:训练序列与输入层维度不一样
  • ¥15 关于Ubuntu20.04.3LTS遇到的问题:在安装完CUDA驱动后,电脑会进入卡死的情况,但可以通过键盘按键进入安全重启,但重启完又会进入该情况!