鱼C论坛

 找回密码
 立即注册
查看: 31|回复: 7

关于解决Helvetica格式字体文本的读取问题

[复制链接]
发表于 3 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我在使用drissionpage技术读取网页文本时,Helvetica字体格式的文本读取不了,下面是豆包给出的代码设置,但是未读取成功,请教大神:

from DrissionPage import Chromium,ChromiumOptions

co = ChromiumOptions()
# 1. 禁用远程字体(不下载网页字体)
co.set_argument('--disable-remote-fonts')
# co.set_argument('--disable-web-fonts')
# 2. 强制全局字体优先级:Helvetica → 微软雅黑 → Arial
# 注意:这个参数会让所有网页默认用这个字体栈
co.set_argument('--font-family="Helvetica,Microsoft YaHei,Arial,sans-serif"')
# 3. 强制所有元素都用默认字体(覆盖网页自己的 font-family)
co.set_argument('--force-font-family')

browser = Chromium(addr_or_opts=co)
tab=browser.latest_tab

.........
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 3 小时前 | 显示全部楼层
您好!很高兴为您解答。首先澄清一个关键点:

DrissionPage读取网页文本是直接从HTML DOM结构中提取内容,与浏览器渲染时使用的字体(如Helvetica)完全无关。就算字体设置错误导致文字在屏幕上显示为乱码或空白框,只要文本在HTML中存在,.text.innerText 方法依然能正常获取。

您看到的“Helvetica格式字体文本读取不了”可能另有原因,建议按以下步骤排查:

  • 检查文本是否真实存在于DOM中  
        打开Chrome开发者工具(F12),在Elements面板中找到目标元素,确认其文本内容是否可见。如果已经能看见文字(即便字体渲染异常),DrissionPage就一定能读到。如果看不见,可能是:
        - 文本由JavaScript动态生成(需要等待页面完全加载)
        - 文本存储在伪元素(::before / ::after)的 content 属性中
        - 文本被用 display:none 隐藏(但 .text 仍能获取)
  • 使用DrissionPage直接验证  
        跑一段最简代码,先确保能取出页面任何文本:
       

    1.     from DrissionPage import Chromium
    2.     browser = Chromium()
    3.     tab = browser.latest_tab
    4.     tab.get('你的网址')
    5.     # 尝试获取页面所有文本
    6.     print(tab('tag:body').text)
    7.    
    复制代码

        如果 body 文本为空,问题不在字体,而是页面根本未加载内容(比如需要登录或反爬)。
  • 字体图标或特殊字符情况  
        如果网页使用 iconfont 或 Font Awesome 等字体图标库显示文本(例如 class="fa fa-user"),实际文本是通过CSS content: '\f007' 显示的,DOM中并不存在该字符。此时必须读取 ::beforecontent 值,DrissionPage可以通过 ele.pseudo.before.content 获取。
  • 删除您代码中多余的设置  
        您的设置试图改变浏览器渲染样式,但这不影响文本提取。可以全部去掉,只保留基础启动:
       

    1.     from DrissionPage import Chromium
    2.     browser = Chromium()
    3.     tab = browser.latest_tab
    4.     tab.get(url)
    5.    
    复制代码

        然后直接操作。


结论:Helvetica字体本身与文本能否读取毫无关系。您应该检查网页的真实内容结构,而非字体渲染参数。建议先用开发者工具定位具体元素,再用DrissionPage的定位方法(如 tab.ele('xpath') )精确抓取。

如果还有具体报错或现象,欢迎继续描述!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 3 小时前 | 显示全部楼层
说明下:我所要获取的文本不是唯一目标,同类目标几百个,但是有些文本字体格式不知道怎么回事,是Helvetica格式的。只有这些格式的文本无法读取,其他不是这种字体格式的同类文本都可以获取。并且这些文本网页渲染也是正常的。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 3 小时前 | 显示全部楼层
laocaiye 发表于 2026-05-28 16:41
说明下:我所要获取的文本不是唯一目标,同类目标几百 ...


明白了,您遇到的情况是:**同类型、同结构的文本节点,只有一部分能通过DrissionPage提取,而另一部分(恰好字体是Helvetica)却提取不到,但网页渲染显示正常**。这确实与字体无关,而是因为这些“Helvetica文本”在DOM中的**存储方式**与普通文本不同。以下是几种常见情况及解决方法:

---

## 原因一:文本位于伪元素(::before / ::after)中

很多字体图标库(如Font Awesome、自定义iconfont)将实际字符放在CSS的 `content` 属性中,而DOM节点本身是空的。浏览器渲染时看似文字,但 `.text` 获取不到。

**验证方法**:  
打开开发者工具 → 选中目标元素 → 查看Styles面板中的 `::before` 或 `::after`,看是否有 `content: "xxx"`。

**DrissionPage 提取伪元素 content 的方法**:

  1. ele = tab.ele('你的选择器')
  2. # 获取伪元素 before 的 content
  3. text = ele.pseudo.before.content
  4. # 若使用 after
  5. text = ele.pseudo.after.content
复制代码


示例:
  1. from DrissionPage import Chromium
  2. browser = Chromium()
  3. tab = browser.latest_tab
  4. tab.get('你的网址')
  5. # 假设所有目标元素都在一个父容器中
  6. for item in tab.eles('.class-name-of-items'):
  7.     # 先尝试常规文本
  8.     txt = item.text
  9.     if not txt:
  10.         # 获取伪元素内容
  11.         txt = item.pseudo.before.content
  12.     print(txt)
复制代码


---

## 原因二:文本被“不可见”字符隐藏但实际存在

某些网站使用CSS将文本颜色透明、或使用 `font-size: 0` + `text-indent` 来隐藏原始文本,同时用Helvetica字体显示替代文本。但DOM中依然有内容,`innerText` 可能返回空串。

**解决**:改用 `textContent`(获取所有子文本,不关心CSS渲染)。  
DrissionPage默认 `.text` 类似于 `innerText`。可以改用元素的 `raw_text` 属性获取原始文本。

  1. txt = item.raw_text  # 等同于 textContent
复制代码


---

## 原因三:文本位于SVG、Canvas或MathML中

这类元素不直接是文本节点,需要通过其他方式提取。如果是SVG中的 `<text>` 标签,DrissionPage的 `.text` 通常能获取;如果是Canvas(画布),则需要OCR或另寻方案。

---

## 原因四:Helvetica字体对应的文本实际是图片(或字体图标)

有些网站将部分文字用图片替代,或者用字体图标显示,但为了SEO仍然在HTML中写了隐藏文本(如 `aria-label`)。检查元素看看是否有 `aria-label`、`data-*` 属性。

**提取属性**:
  1. txt = item.attr('aria-label')  # 或 item.attr('data-original-text')
复制代码


---

## 调试建议

1. **输出该元素的HTML结构**,确认文本位置:
  
  1. print(item.html)
复制代码

   观察文本到底在哪里——是直接文本节点、子元素中、还是伪元素中?

2. **用以下代码逐一尝试**,找到真正来源:
  
  1. print('text:', item.text)
  2.    print('raw_text:', item.raw_text)
  3.    print('inner_html:', item.html)
  4.    print('before pseudo:', item.pseudo.before.content)
  5.    print('after pseudo:', item.pseudo.after.content)
复制代码


3. **如果上述均无结果**,可能是文本被JavaScript动态写入或使用Font-Face字体映射了Unicode字符(例如用 `U+E001` 显示特定图标),此时需要监听网络请求或抓取页面渲染后的Canvas。不过前两种可能性最大。

---

## 总结

**Helvetica字体不是原因**。请检查该元素的伪元素、CSS隐藏、或属性存储。使用 `pseudo.before.content` 或 `raw_text` 大概率能解决问题。如果仍无法获取,请贴出那个“不能读取”的元素的HTML源码(可以直接用 `print(item.html)` 输出),我帮您分析。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 3 小时前 | 显示全部楼层
再说明白些,我是想获取网页中不同学员提交的答案,然后和标准答案进行对比。所以说这些学员提交答案的网页元素和格式都是一样的,但是就是不知道有些学生是怎么输入答案的,字体是显示是Helvetica,这些Helvetica格式的文本无法读取成功。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 3 小时前 | 显示全部楼层
laocaiye 发表于 2026-05-28 16:45
再说明白些,我是想获取网页中不同学员提交的答案,然 ...


您描述的“Helvetica字体格式的文本无法读取”实际上是一个表象。在DrissionPage中,提取文本靠的是DOM结构,与CSS渲染无关。既然网页渲染正常,说明这些文本是正常显示的,但可能在DOM中**不是以普通文本节点**存在的。以下是最可能的原因和对应的解决方案:

---

## 原因一:答案文本被作为“字体图标”显示(CSS伪元素content)

有些学生通过富文本编辑器输入了特殊符号或表情,网页可能使用自定义字体(如Font Awesome、iconfont)通过 `::before` 或 `::after` 的 `content` 属性渲染。Helvetica字体可能只是这些图标的替代显示,但实际文本并不在文本节点里。

**验证方法**:
打开Chrome开发者工具,选中任意一个“Helvetica文本”元素,查看Styles面板中是否有 `::before` 或 `::after`,并且 `content` 属性包含类似 `"\f007"` 或中文字符。

**解决方法**:使用DrissionPage读取伪元素内容。

ele = tab.ele('你的选择器')  # 答案元素的定位
# 先尝试取常规文本
txt = ele.text
if not txt:
    # 获取before伪元素的内容
    txt = ele.pseudo.before.content
    # 如果不行再试after
    if not txt:
        txt = ele.pseudo.after.content

---

## 原因二:答案存储在自定义属性中(data-* 或 aria-label)

某些网页框架为了安全或跨域,将真正的答案文本存放在元素的 `data-answer`、`data-value` 或 `aria-label` 属性中,而显示部分使用Helvetica字体的占位符。

**验证方法**:右键检查该元素,查看Attributes中是否有 `data-` 或 `aria-` 开头的属性,其值恰好是您想获取的文本。

**解决方法**:用 `.attr()` 提取。

real_answer = ele.attr('data-answer') or ele.attr('aria-label')

---

## 原因三:答案文本通过JavaScript动态写入(比如input.value)

如果学生答案是在 `<input>` 或 `<textarea>` 等表单元素中,DrissionPage的 `.text` 无法获取其内容。需要通过 `.value` 属性获取。

**验证方法**:检查标签名是否为 input、textarea 或 contenteditable 的div。

**解决方法**:

if ele.tag in ('input', 'textarea'):
    answer = ele.value  # 注意不是 .text
else:
    answer = ele.text

---

## 原因四:答案文本被CSS隐藏(color: transparent 或 font-size: 0)

有些网页为了防爬虫,会将真实文本写在一个非可见元素中,而用另一个可见元素显示噪声文字(如字体Helvetica)。此时需要定位真实文本所在的隐藏元素。

**解决方法**:打印整个容器的html,查看有无 `display:none` 或 `visibility:hidden` 的子元素:

parent = tab.ele('.answer-container')
all_text = parent.raw_text  # 包含所有子文本,包括隐藏的

---

## 调试一招:输出目标元素的完整HTML

在您的循环中,对无法读取的答案元素执行:

print(item.html)

将输出的HTML贴出来,我就能立刻判断文本藏在哪儿。常见模式:

-  `<span class="iconfont">&#xE604;</span>` → 伪元素
-  `<input type="hidden" value="正确答案">` → value属性
-  `<div aria-label="正确答案"> </div>` → aria-label

如果仍无法解决,请直接提供一段这样“Helvetica文本”的HTML源码片段,我帮您精准匹配提取方法。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2 小时前 | 显示全部楼层
刚才采用两种方式复制了网页文本,结果两种方式粘贴在word中显示字体不一样,从正常渲染后网页复制答题框里的文本粘贴到word中后,显示是字体,而打开开发者工具,从网页表中直接复制文本粘贴到word中后显示是monospace格式字体。就是说设置字体映射时,应该加入monospace字体。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层
laocaiye 发表于 2026-05-28 17:16
刚才采用两种方式复制了网页文本,结果两种方式粘贴在 ...


您发现了两个关键现象,这将帮助准确定位问题:

1. **从网页渲染区复制**(答题框可见文本)粘贴到Word,显示**Helvetica字体**。  
2. **从开发者工具(元素面板)复制**相同的文本粘贴到Word,显示**monospace字体**。

这说明:**网页确实渲染了Helvetica字体,但DOM中存储的文本是普通的Unicode字符**,开发者工具用monospace字体只是代码查看习惯,与内容无关。两份文本本质应是相同的,除非有隐藏字符合并问题。

---

## 核心结论

**字体映射(如加入monospace)与DrissionPage提取文本毫无关系。** 您无法读取的文本肯定不在DrissionPage的 `.text` 能够获取的位置。我们需要从DOM结构入手。

---

## 可能的原因(根据您的描述,逐一排查)

### 1. 答题框是 `<input>` 或 `<textarea>` 元素
这类元素的 `.text` 属性为空,文本存储在 `.value` 中。

**验证方法**:检查元素标签名:  
  1. print(item.tag)   # 如果返回 'input' 或 'textarea'
复制代码

**解决方法**:改用 `.value`。  
  1. answer = item.value   # 而非 item.text
复制代码


### 2. 答题框是 `contenteditable` 的 `<div>`
有些网页用可编辑的div代替textarea,文本在 `.innerText` 或 `.textContent` 中。DrissionPage的 `.text` 通常能获取,但若div内部有复杂子元素(如span、br)可能丢失部分文本。  
**尝试**:  
  1. answer = item.raw_text   # 等同于 textContent
复制代码


### 3. 文本在 Shadow DOM 中
如果答题框使用了Web Component,文本藏在 shadow-root 中,普通的选择器无法穿透。  
**检测**:`print(item.html)` 查看是否包含 `#shadow-root`。  
**解决**:使用 `ele.sr()` 方法进入shadow root后再提取。

### 4. 文本通过JavaScript动态写入,但DrissionPage抓取时尚未加载
您已经看到渲染正常,说明页面已完全加载。但DrissionPage获取文本时可能过早。尝试增加等待:  
  1. tab.wait.load_complete()
复制代码

或针对单个元素等待:  
  1. item = tab.wait.ele('选择器', timeout=10)
复制代码


### 5. 答案文本被放在 `aria-label` 或 `data-*` 属性中
这种设计常见于富文本编辑器(如Quill、TinyMCE),真正的文本存储在自定义属性中,显示的是渲染后的HTML。  
**尝试**:  
  1. answer = item.attr('aria-label') or item.attr('data-text') or item.attr('value')
复制代码


---

## 立即调试:打印元素的完整HTML

在您的循环中,对**无法读取的Helvetica文本元素**执行以下代码,并将输出贴出来(注意隐藏敏感信息):

  1. ele = tab.ele('你的定位表达式')  # 替换为具体选择器
  2. print('Tag:', ele.tag)
  3. print('Value:', ele.value)      # 先试试这个
  4. print('Raw_text:', ele.raw_text)
  5. print('InnerHTML:', ele.html)
  6. print('Attr aria-label:', ele.attr('aria-label'))
  7. print('Attr data-*:', ele.attr('data-text'))  # 常见自定义属性
复制代码


有了这段输出,我可以立刻判断文本藏在哪里。大概率是 **`.value`** 或 **`.raw_text`** 就能解决。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2026-5-28 19:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表