爬蟲「Python」:解決網絡爬蟲遇到的字體包.ttf識別問題

在寫網絡爬蟲時,經常遇到頁面顯示正常的文字,在查看源碼時出現空白或者亂碼的情況,這就是運用字體包 .ttf 反爬機制,這裏簡單瞭解一下 .ttf 文件

目錄

一、問題

二、TTF文件 

三、解決

(一)過程分析

(二)代碼


一、問題

這裏我已實際爬蟲過程中遇到的情況爲例,首先頁面顯示內容如下圖1

圖1:網頁與控制檯顯示

這裏即使我們嘗試爬取網頁內容,結果仍然是響應內容顯示異常,如圖2

圖2:爬取得到的內容

這就是 .ttf 在這裏起到的反爬作用

二、TTF文件 

TTF(TrueTypeFont)是 Apple 公司和 Microsoft 公司共同推出的字體文件格式,隨着 windows 的流行,已經變成最常用的一種字體文件表示方式。

那麼 .ttf 是怎麼在網頁顯示中起作用的呢?方法如下:

  • 首先在 <style> 標籤中添加:
@font-face {
    font-family: "myfont";
    src: url('.ttf文件url');
}
  • 然後在需要顯示的地方添加:
<span style="font-family:myfont"></span>

這裏 是需要顯示字的映射編碼

這裏推薦一個“百度字體編輯器”:http://fontstore.baidu.com/static/editor/index.html,可在線查看 .ttf 文件,效果如下圖3

圖3:百度字體編輯器

所以我們只需要將“字”與“編碼”匹配即可替換文本中的符號

三、解決

(一)過程分析

給出需要解決的文檔:

【最滿意】駕駛非常舒服,做工飾非常棒,指導價22.86趕換代非常合適,7.4折,贈送全車龍膜,行車記錄儀,前熱,夠用,雙11看車,交定金,等20天超難熬,12月初車到,始貼裝飾,等到1月纔去牌子,切順利,車能非常,換擋快,速快,飾簡單又失去科技感,該功能全部都,20款,國、鑰匙進入,鑰匙,耳摺疊,耳熱,定速巡航,換擋撥片,太牛簡直,這個車而舒服,夠用【最不滿意】前期速穩,慢點,其他都,鑰匙點老氣,輪胎韓泰米【爲什麼選擇這款車】給媳婦買,優惠,奧迪做工,行駛穩定【空間】挺寬,夠用,前舒服轎跑感覺,運座椅,布,但舒服,熱,老快【動力】夠用夠用,腳就奔起,提速老快?還穩,幾秒就100,感覺老給力【操控】舒服,穩定,尤其轉彎,坑,老舒服,濾相細膩【油耗】200塊錢95,半個月,班,夠用,還跑兩次新區,可以可以【舒適性】沒毛病,前後都,舒服,勁,尤其座椅,各種方向調節,舒服,我喜歡半躺,衝勁,累【外觀】帥,錯,經典,18寸輪,黑頂,S3進氣【內飾】看,連接方便,出風口紅色漂亮,屏幕也【性價比】合適,同價位我知道,該哪款車可以這個配置,就也沒奧迪駕駛感受,折扣肯定夠用,配置絕對可以,

首先我們需要下載與該文檔對應的 .ttf 文件,記住,大多數的網站每次頁面的 .ttf不同的

1. .txt 文件. ttf 文件放到一個文件夾下:

 2. 通過如下代碼解析字庫文件:

# 解析字體庫
font = TTFont('.ttf文件路徑')

# 讀取字體的映射關係
uni_list = font['cmap'].tables[0].ttFont.getGlyphOrder()

# 轉換格式
utf_list = [eval(r"u'\u" + x[3:] + "'") for x in uni_list[1:]]

通過執行,我們可以獲取字體的映射關係

['\uedec', '\ued38', '\uec85', '\uecd7', '\uec23', '\uec75', '\uedb6', '\ued02', '\ued54', '\ueca1', '\uede1', '\uec3f', '\ued80', '\uedd1', '\ued1e', '\uec6b', '\uecbc', '\uedfd', '\ued4a', '\ued9b', '\uece8', '\ued3a', '\uec86', '\uedc7', '\uec25', '\ued65', '\uecb2', '\ued04', '\uec50', '\ueca2', '\uede3', '\ued30', '\ued81', '\uecce', '\uec1b', '\uec6c', '\uedad', '\uedff', '\ued4b', '\uec98', '\uecea', '\uec36', '\ued77', '\uedc9', '\ued15', '\ued67', '\uecb4', '\uedf4', '\uec52', '\ued93', '\uecdf', '\ued31', '\uec7e', '\uecd0', '\uec1c', '\ued5d', '\uedaf', '\uecfb', '\uec48', '\uec9a', '\uedda', '\uec38', '\ued79', '\uecc5', '\ued17', '\uec64', '\ueda4', '\uedf6', '\ued43', '\ued94', '\uece1', '\uec2e', '\uec7f', '\uedc0', '\ued0d', '\ued5e', '\uecab', '\uecfd', '\uec49', '\ued8a', '\ueddc', '\ued28', '\uecc7', '\uee07', '\uec65', '\ueda6', '\uecf2', '\ued44', '\uec91', '\uec2f']

3. 藉助百度字體編輯器,我們可以將上述字符匹配到我們熟悉的文字(需要手動匹配,對於較多的爬蟲量,確實有些複雜,讀者可以考慮將圖片發送到百度圖像識別接口來獲取對應文字),結果如下:

# 被替換的字體的列表
word_list = [u'着', u'機', u'好', u'九', u'左', u'路', u'遠', u'上', u'動', u'門',
                 u'副', u'檔', u'真', u'了', u'小', u'短', u'實', u'盤', u'大', u'壞', u'空',
                 u'右', u'五', u'油', u'軟', u'是', u'二', u'外', u'十', u'得', u'泥', u'地',
                 u'呢', u'音', u'控', u'保', u'手', u'光', u'啓', u'四', u'養', u'七', u'不',
                 u'冷', u'味', u'的', u'矮', u'一', u'只', u'低', u'孩', u'有', u'來', u'和',
                 u'高', u'燈', u'自', u'耗', u'開', u'身', u'多', u'內', u'三', u'下', u'量',
                 u'硬', u'長', u'雨', u'八', u'排', u'皮', u'很', u'過', u'更', u'響', u'少',
                 u'坐', u'當', u'裏', u'比', u'加', u'六', u'近', u'無', u'性', u'中', u'問',
                 u'級', u'公', u'電']

4. 然後執行替換,即可:

# 遍歷需要被替換的字符
for i in range(len(utf_list)):
    text = text.replace(utf_list[i], word_list[i])

效果如下:

【最滿意】駕駛非常舒服,做工內飾非常棒,指導價22.86趕上小換代非常合適,7.4折,贈送全車龍膜,行車記錄儀,前排加熱,夠用了,雙11看車,交了定金,等了20天超級難熬,12月初車到,開始貼裝飾,等到了1月纔去上牌子,一切順利,車的性能非常好,換擋快,加速快,內飾簡單又不失去科技感,該有的功能全部都有,20款,國六、無鑰匙進入,無鑰匙啓動,電耳摺疊,電耳加熱,定速巡航,換擋撥片,太牛了簡直,這個車小而舒服,夠用【最不滿意】前期加速很穩,慢一點,其他都好,鑰匙有點老氣,輪胎韓泰不是米【爲什麼選擇這款車】給媳婦買的,優惠大,奧迪做工好,行駛穩定【空間】挺寬的,坐着夠用,前排很舒服有轎跑的感覺,運動座椅,布的,但是很舒服,電加熱,老快了【動力】夠用夠用,一腳就奔起,提速老快了?還穩當,幾秒就上100,感覺老給力了【操控】舒服,穩定,尤其轉彎,過坑,老舒服了,過濾的相當細膩【油耗】200塊錢95油,開了半個月,上下班,夠用不,還跑了兩次新區,可以可以了【舒適性】沒毛病,前排後排都坐了,舒服,得勁,尤其電動座椅,各種方向調節,真的舒服,我喜歡半躺開,小衝勁一上來,不累【外觀】帥,真不錯,經典,18寸大輪,黑頂,S3進氣【內飾】好看,手機連接方便,出風口紅色漂亮,小屏幕也好【性價比】合適,同價位我不知道,該有哪款車可以有這個多的配置,就是有也沒有奧迪的駕駛感受,折扣肯定夠用,配置絕對可以,

總體來說,整個過程相對而言不算太難,但是對於大批量的爬蟲而言確有很多不足。 

(二)代碼

這裏直接給出全部代碼:

from fontTools.ttLib import TTFont


def parse_ttf(download_path, mouth_id):
    # 解析字體庫
    font = TTFont(download_path + mouth_id + '.ttf')

    # 讀取字體的映射關係
    uni_list = font['cmap'].tables[0].ttFont.getGlyphOrder()

    # 轉換格式
    utf_list = [eval(r"u'\u" + x[3:] + "'") for x in uni_list[1:]]

    return utf_list


def replace(utf_list, text):
    # 被替換的字體的列表
    word_list = [u'着', u'機', u'好', u'九', u'左', u'路', u'遠', u'上', u'動', u'門',
                 u'副', u'檔', u'真', u'了', u'小', u'短', u'實', u'盤', u'大', u'壞', u'空',
                 u'右', u'五', u'油', u'軟', u'是', u'二', u'外', u'十', u'得', u'泥', u'地',
                 u'呢', u'音', u'控', u'保', u'手', u'光', u'啓', u'四', u'養', u'七', u'不',
                 u'冷', u'味', u'的', u'矮', u'一', u'只', u'低', u'孩', u'有', u'來', u'和',
                 u'高', u'燈', u'自', u'耗', u'開', u'身', u'多', u'內', u'三', u'下', u'量',
                 u'硬', u'長', u'雨', u'八', u'排', u'皮', u'很', u'過', u'更', u'響', u'少',
                 u'坐', u'當', u'裏', u'比', u'加', u'六', u'近', u'無', u'性', u'中', u'問',
                 u'級', u'公', u'電']

    # 遍歷需要被替換的字符
    for i in range(len(utf_list)):
        text = text.replace(utf_list[i], word_list[i])

    return text


def read_txt(download_path, mouth_id):
    with open(download_path + mouth_id + '.txt', 'r') as f:
        text = f.read()

    return text


if __name__ == '__main__':
    # id
    my_mouth_id = '01dzk6s7st68wk6d9p6wv00000'

    # 保存路徑
    my_download_path = r'../../../data/mouth_data/'

    # 解析ttf文件
    my_utf_list = parse_ttf(my_download_path, my_mouth_id)

    # 讀取原文檔
    old_text = read_txt(my_download_path, my_mouth_id)

    # 替換爲新文檔
    new_text = replace(my_utf_list, old_text)

    print(new_text)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章