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

正则,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日

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!