开发者社区> 游客2silnuajy47wo> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

一日一技:使用Python翻译HTML中的文本字符串

简介: 一日一技:使用Python翻译HTML中的文本字符串
+关注继续查看

相信大家都用过浏览器的翻译网页功能,例如对于下图这个英文网页:


1.png


一键翻译成中文以后是这样的:


2.png

image.gif

你可能会觉得这个功能很简单,不就是字符串替换吗?那你可以试一试把下面这个HTML片段中的<p>标签下面的英文翻译成中文。其它标签中的不要改动:


<div>
 <p>if you want to parse date and time, your could use <em>datetime</em>, by use this library, you can generate now time by one line code <span>datetime.datetime.now()</span> this is so easy.</p>
</div>


<em>标签中的datetime<span>标签中的datetime.datetime.now()不需要翻译。


你一拍脑袋,马上写出了下面这几行代码(假设你已经有了一个现成的translate()函数,传入英文,输出中文):


from lxml.html import fromstring
source = '''<div>
 <p>if you want to parse date and time, your could use <em>datetime</em>, by use this library, you can generate now time by one line code <span>datetime.datetime.now()</span> this is so easy.</p>
</div>
'''
selector = fromstring(source)
text_list = selector.xpath('//p/text()')
for text in text_list:
    chinese = translate(text)
    ...


当你写到这里,你应该会愣一下。因为你突然发现一个问题,怎么把中文替换回去?


不用尝试去百度了。在今天(2022-06-20)之前,整个中文网络里面,你找不到解决方法。


一个比较笨的办法是直接对原始的HTML字符串进行文本替换:


for text in text_list:
    chinese = translate(text)
    source = source.replace(text, chinese)


但这样做,效率非常低。因为你要不停扫描整个HTML字符串。一般一个中型网站的HTML就有几千上万行,十几二十万个字符。你每翻译一小段就全文替换一次,这个时间会非常漫长。


那有没有办法只对当前这一个<p>标签里面的文本进行替换呢?关键的问题来了,你替换可以,但是怎么才能不影响这个<p>标签下面的两个子标签?要保证文本和子标签的相对位置不改变。


如果<p>标签下面只有一段文本,没有子标签,那么非常简单,如下图所示:


3.png


但现在的问题是,<p>标签下面有三段文本。每段文本之间还插入了其它的子标签。我们怎么样对每一段文本进行替换,但是又保持文本的相对顺序,并且还不能影响子标签?


4.png

image.gif

p.text这种写法首先就可以排除了,因为它没有办法指定替换第几段文本。


你之所以会觉得这个问题很难解决,是因为你有一个错觉,请看上面这张截图,我打印了text_list。打印出来是一个包含字符串的列表。所以你可能会觉得。使用lxml写Xpath的时候,/text()返回的总是包含字符串的列表。


但实际上,返回的列表里面的元素并不是字符串,而是_ElementUnicodeResult对象。如下图所示:


5.png


image.gif

不是字符串就简单了,那么我们可以获取每一个文本对象的父标签。然后修改父标签下面的文本就可以了。



看到这里,你肯定会问,这三个文本节点的父标签,不都是同一个<p>吗?如果你觉得是,那你就犯了想当然的错误。我们用代码来看看:


6.png

image.gif

其实只有第一段文本的父标签是<p>。第二段文本的父标签,竟然是<p>的子标签<em>。第三段文本的父标签,是<span>


等等,如果第二段文本的父标签是<em>,那么<em>datetime</em>里面的datetime的父标签是什么?它的父标签也是<em>!那么问题来了,<em>text()文本节点,怎么可能又是datetime,又是<p>下面的第二段文本呢?


实际上,<em>text()始终都是datetime。如下图所示:



7.png


那么,<p>的第二段文本跟这个<em>标签是什么关系?实际上,这个关系叫做tail。如下图所示:


8.png


在一个标签里面,只有第一段text是它真正的text(),如果这个标签有子标签,那么位于子标签后面的文本,是这个子标签的tail。只不过当我们在正则表达式里面写/text()的时候,lxml会帮我们把所有子标签的tail都算作当前标签的text。


我们可以使用文本节点的.is_text.is_tail来判断它属于哪种文本。最终运行效果如下图所示:


9.png


请关注微信公众号【未闻Code】获取更多精彩文章。 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
史上最全python字符串操作指南!
日常编码中,大家会发现,太多时候我们需要对数据进行处理,而这数据不管是数组、列表、字典,最终都逃不开字符串的处理。 所以今天要来跟大家发散的聊聊字符串!
22 0
史上最全python字符串操作指南
日常编码中,大家会发现,太多时候我们需要对数据进行处理,而这数据不管是数组、列表、字典,最终都逃不开字符串的处理。 所以今天要来跟大家发散的聊聊字符串!
20 0
图解python | 字符串及操作
在Python中,字符串(String)是若干个字符的集合,是最常用的数据类型。就是一个字符串。本文详细讲解字符串的创建、访问、连接、运算、格式化、Unicode字符串和内建函数等知识。
62 0
初学Python——字符串相关操作
Pyhton中字符串的格式化输出在前面已经总结了,接下来介绍一些常用的字符串操作 先定义一个字符变量,以下的操作都以此为例: name=" my name is china " #(首尾有空格) 1.
883 0
Python与R的异同(二):字符串操作
字符串操作的差异 R本身设计初衷主要是用来处理矩阵运算这类数学问题,因此在字符串操作方面比较薄弱。Python并不是专门用来进行数学计算的,没有偏向性,字符串操作优良。
722 0
80
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载