使用lxml.html向HTML文件新增标签后操作未生效的问题咨询
lxml.html操作不生效的原因及解决方案
核心问题点
- 第一个循环已将
row_data中所有节点从DOM树中移除,后续第二个循环修改的都是已脱离DOM的游离节点,修改结果自然不会同步到最终的HTML中 html.tostring()返回的是bytes类型,直接转str并手动移除b'前缀的处理方式极易引发编码错误,且通过字符串替换插入<span>标签的逻辑不稳定,容易误伤正常标签内容Element.set()方法使用错误:lxml的节点set方法入参为(属性名, 属性值),代码中x.set('class="Numbers"', value=x.text_content())属于完全错误的调用,不仅不会正常设置class属性,还会生成非法属性名,且不存在value这个入参
修正方案
优化span插入逻辑(无需删除原节点)
不需要将节点转成字符串做替换,直接操作DOM节点即可完成内容套span的需求:
from lxml.html import builder as E for y in row_data: # 提取原td节点的文本内容 origin_text = y.text or '' # 构建span节点承载内容 span_node = E.SPAN(origin_text) # 清空原td的文本,插入span节点 y.text = '' y.insert(0, span_node)
修正属性设置逻辑
for x in row_data: content = x.text_content() if number.search(content) and not date_pattern.search(content): # 兼容style属性不存在的场景 x.attrib['style'] = x.attrib.get('style', '') + 'color:orange;' # 正确设置class属性 x.set('class', 'Numbers') # 如需给内层span加class,替换为 x[0].set('class', 'Numbers') elif date_pattern.search(content): x.attrib['style'] = x.attrib.get('style', '') + 'color:red;' x.set('class', 'Dates')
特殊场景说明
如果你确实需要替换整个td节点,必须将新生成的节点存入新列表,后续遍历新列表做属性修改:
new_td_list = [] for y in row_data: # 这里用更稳妥的方式生成新td节点 origin_html = html.tostring(y, encoding='unicode') new_html = origin_html.replace('">', '"><span>').replace('</td>', '</span></td>') new_td = html.fromstring(new_html) y.addprevious(new_td) y.getparent().remove(y) new_td_list.append(new_td) # 遍历新的已挂载在DOM中的节点做修改 for x in new_td_list: # 后续属性修改逻辑和上面一致
内容的提问来源于stack exchange,提问作者Shubham Gupta
相关产品推荐
相关产品推荐

