当前位置: 首页 > 科技观察

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

时间:2023-03-17 17:26:59 科技观察

相信大家都用过浏览器的翻译网页功能,比如下图中的英文网页:一键翻译成中文后,会像这样:你可能觉得这个函数很简单,不就是字符串替换吗?那么你可以尝试将下面的HTML片段中

标签下的英文翻译成中文。不要改变其他标签:

如果你想解析日期和时间,你可以使用datetime,通过使用这个库,你可以通过一行代码生成现在时间datetime.datetime.now()这么简单

标签中的datetime和标签中的datetime.datetime.now()不需要翻译.一拍脑袋,立马写了下面几行代码(假设你已经有现成的translate()函数,传入英文,输出中文):fromlxml.htmlimportfromstringsource='''

如果你想解析日期和时间,你可以使用datetime,通过使用这个库,你可以通过一行代码生成现在时间datetime.datetime.now()这太简单了。

'''selector=fromstring(source)text_list=selector.xpath('//p/text()')fortextintext_list:chinese=translate(文)……写到这里,你应该愣了一下。因为你突然发现一个问题,怎么替换中文?不要试图去百度。在今天(2022-06-20)之前,全中文网都找不到解决办法。比较笨的方法是直接用文本替换原来的HTML字符串:fortextintext_list:chinese=translate(text)source=source.replace(text,chinese)但是这样效率很低。因为你必须不断地扫描整个HTML字符串。一般中型网站的HTML有几万行,几十万个字符。每次翻译一小段都需要替换全文,这会花费很长时间。有没有办法只替换当前

标签中的文本?关键问题来了,可以替换,但是如何不影响

标签下的两个子标签呢?确保文本和子标签的相对位置没有改变。如果

标签下只有一段文字,没有子标签,就很简单了,如下图:但是现在的问题是

标签下有三段文字.在每段文本之间插入额外的子标签。我们如何才能替换每段文本,但保持文本的相对顺序,并且不能影响子标签?p.text的写法可以先排除,因为它没有办法指定替换哪几段文字。你之所以觉得这个问题很难解决是因为你有错觉,请看上面的截图,我打印了text_list。打印出来的是一个包含字符串的列表。所以你可能会想。当用lxml编写XPath时,/text()总是返回一个包含字符串的列表。但实际上,返回列表中的元素并不是字符串,而是_ElementUnicodeResult对象。如下图所示:如果不是字符串就简单了,那么我们就可以得到每个文本对象的父标签。然后修改父标签下面的文字。看到这里,你肯定会问,这三个文本节点的父标签不都是一样的

吗?如果你这么认为,那么你就犯了一个错误,认为它是理所当然的。我们用代码看看:其实只有第一段文字的父标签是

。第二段文字的父标签原来是

的子标签。第三段文字的父标签是。等等,如果第二段文字的父标签是,那么datetime中datetime的父标签是什么?它的父标签也是!那么问题来了,的text()文本节点怎么会是datetime和

下的第二段文本呢?事实上,的text()始终是日期时间。如下图所示:那么,

的第二段文字和这个标签是什么关系呢?事实上,这种关系被称为tail。如下图所示:在一个标签中,只有第一段文字才是它真正的文字()。如果标签有子标签,则子标签后面的文字就是子标签的尾部。只是当我们在正则表达式中写/text()时,lxml会帮我们把所有子标签的尾部统计为当前标签的文本。我们可以使用文本节点的.is_text和.is_tail来确定它属于哪种文本。最终运行效果如下图所示: