1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        使用Python翻譯HTML中的文本字符串

        共 2924字,需瀏覽 6分鐘

         ·

        2022-06-29 13:45

        相信大家都用過(guò)瀏覽器的翻譯網(wǎng)頁(yè)功能,例如對(duì)于下圖這個(gè)英文網(wǎng)頁(yè):

        一鍵翻譯成中文以后是這樣的:

        你可能會(huì)覺(jué)得這個(gè)功能很簡(jiǎn)單,不就是字符串替換嗎?那你可以試一試把下面這個(gè)HTML片段中的<p>標(biāo)簽下面的英文翻譯成中文。其它標(biāo)簽中的不要改動(dòng):

        <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>標(biāo)簽中的datetime<span>標(biāo)簽中的datetime.datetime.now()不需要翻譯。

        你一拍腦袋,馬上寫(xiě)出了下面這幾行代碼(假設(shè)你已經(jīng)有了一個(gè)現(xiàn)成的translate()函數(shù),傳入英文,輸出中文):

        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)
            ...

        當(dāng)你寫(xiě)到這里,你應(yīng)該會(huì)愣一下。因?yàn)槟阃蝗话l(fā)現(xiàn)一個(gè)問(wèn)題,怎么把中文替換回去?

        不用嘗試去百度了。在今天(2022-06-20)之前,整個(gè)中文網(wǎng)絡(luò)里面,你找不到解決方法。

        一個(gè)比較笨的辦法是直接對(duì)原始的HTML字符串進(jìn)行文本替換:

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

        但這樣做,效率非常低。因?yàn)槟阋煌呙枵麄€(gè)HTML字符串。一般一個(gè)中型網(wǎng)站的HTML就有幾千上萬(wàn)行,十幾二十萬(wàn)個(gè)字符。你每翻譯一小段就全文替換一次,這個(gè)時(shí)間會(huì)非常漫長(zhǎng)。

        那有沒(méi)有辦法只對(duì)當(dāng)前這一個(gè)<p>標(biāo)簽里面的文本進(jìn)行替換呢?關(guān)鍵的問(wèn)題來(lái)了,你替換可以,但是怎么才能不影響這個(gè)<p>標(biāo)簽下面的兩個(gè)子標(biāo)簽?要保證文本和子標(biāo)簽的相對(duì)位置不改變。

        如果<p>標(biāo)簽下面只有一段文本,沒(méi)有子標(biāo)簽,那么非常簡(jiǎn)單,如下圖所示:

        但現(xiàn)在的問(wèn)題是,<p>標(biāo)簽下面有三段文本。每段文本之間還插入了其它的子標(biāo)簽。我們?cè)趺礃訉?duì)每一段文本進(jìn)行替換,但是又保持文本的相對(duì)順序,并且還不能影響子標(biāo)簽?

        p.text這種寫(xiě)法首先就可以排除了,因?yàn)樗鼪](méi)有辦法指定替換第幾段文本。

        你之所以會(huì)覺(jué)得這個(gè)問(wèn)題很難解決,是因?yàn)槟阌幸粋€(gè)錯(cuò)覺(jué),請(qǐng)看上面這張截圖,我打印了text_list。打印出來(lái)是一個(gè)包含字符串的列表。所以你可能會(huì)覺(jué)得。使用lxml寫(xiě)Xpath的時(shí)候,/text()返回的總是包含字符串的列表。

        但實(shí)際上,返回的列表里面的元素并不是字符串,而是_ElementUnicodeResult對(duì)象。如下圖所示:

        不是字符串就簡(jiǎn)單了,那么我們可以獲取每一個(gè)文本對(duì)象的父標(biāo)簽。然后修改父標(biāo)簽下面的文本就可以了。

        看到這里,你肯定會(huì)問(wèn),這三個(gè)文本節(jié)點(diǎn)的父標(biāo)簽,不都是同一個(gè)<p>嗎?如果你覺(jué)得是,那你就犯了想當(dāng)然的錯(cuò)誤。我們用代碼來(lái)看看:

        其實(shí)只有第一段文本的父標(biāo)簽是<p>。第二段文本的父標(biāo)簽,竟然是<p>的子標(biāo)簽<em>。第三段文本的父標(biāo)簽,是<span>。

        等等,如果第二段文本的父標(biāo)簽是<em>,那么<em>datetime</em>里面的datetime的父標(biāo)簽是什么?它的父標(biāo)簽也是<em>!那么問(wèn)題來(lái)了,<em>text()文本節(jié)點(diǎn),怎么可能又是datetime,又是<p>下面的第二段文本呢?

        實(shí)際上,<em>text()始終都是datetime。如下圖所示:

        那么,<p>的第二段文本跟這個(gè)<em>標(biāo)簽是什么關(guān)系?實(shí)際上,這個(gè)關(guān)系叫做tail。如下圖所示:

        在一個(gè)標(biāo)簽里面,只有第一段text是它真正的text(),如果這個(gè)標(biāo)簽有子標(biāo)簽,那么位于子標(biāo)簽后面的文本,是這個(gè)子標(biāo)簽的tail。只不過(guò)當(dāng)我們?cè)谡齽t表達(dá)式里面寫(xiě)/text()的時(shí)候,lxml會(huì)幫我們把所有子標(biāo)簽的tail都算作當(dāng)前標(biāo)簽的text。

        我們可以使用文本節(jié)點(diǎn)的.is_text.is_tail來(lái)判斷它屬于哪種文本。最終運(yùn)行效果如下圖所示:

        往期推薦
        1、這不會(huì)又是一個(gè)Go的BUG吧?
        2、Python處理辦公自動(dòng)化的10大場(chǎng)景!
        3、一次Python爬蟲(chóng)實(shí)戰(zhàn),解決反爬問(wèn)題!
        4、13個(gè)Python必備的知識(shí),建議收藏!
        5、這幾個(gè) Python 小游戲,上班摸魚(yú)我能玩一天 | 內(nèi)附源碼
        點(diǎn)擊關(guān)注公眾號(hào),閱讀更多精彩內(nèi)容
        瀏覽 54
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            久久国产免费电影 | 国产精品久久久乱弄 | 国产精品久久久久久久美女直播 | 巨胸被触手整的狂喷奶水 | 中国免费一级无码成人片 | hugeboobs欧美巨大乳 | 国精产品一区一区三区mba下载 | 成人国产精品秘 电影 | 女s羞辱女m丨vk | 久9精品|