日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Python字體反爬教科書級別的網(wǎng)站-貓眼電影

系統(tǒng) 2260 0

一.問題

Python字體反爬教科書級別的網(wǎng)站-貓眼電影_第1張圖片
可以看到,貓眼網(wǎng)電影評分,票房等的數(shù)據(jù)在響應的html中并不是直接提供給你的。這里的xefcf,xef87等數(shù)據(jù),是以‘特殊符號’的形式顯示出來的。
Python字體反爬教科書級別的網(wǎng)站-貓眼電影_第2張圖片
可以發(fā)現(xiàn)這里請求了一個woff字體文件,而xefcf,xef87等數(shù)據(jù)的規(guī)則就是在這其中的。所以我們只需要在請求這個網(wǎng)頁的同時,截去這部分style,然后獲得woff地址,將它下載到本地,進行解析,就可以實現(xiàn)對評分的解密了。

但是再來看下面,當同一部電影的頁面刷新時。
Python字體反爬教科書級別的網(wǎng)站-貓眼電影_第3張圖片
Python字體反爬教科書級別的網(wǎng)站-貓眼電影_第4張圖片
這里的評分編碼改變了,下面請求的woff的url也改變了。所以每次請求電影頁面使用的woff都不是同一個。

在這種情況下,如何才可以實現(xiàn)評分的爬取呢?

二.分步實現(xiàn)

1.頁面爬取

第一步我們需要先將整個html頁面獲取,其中重要的數(shù)據(jù)就是評分所在的那個span,還有woff的url所在的那個style.

這里使用requests獲取網(wǎng)頁內(nèi)容,用BeautifulSoup進行關鍵內(nèi)容解析.

            
              '''
遇到不懂的問題?Python學習交流群:821460695滿足你的需求,資料都已經(jīng)上傳群文件,可以自行下載!
'''
# 請求頭設置
header = {
    'Accept': '*/*;',
    'Connection': 'keep-alive',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'Host': 'maoyan.com',
    'Referer': 'http://maoyan.com/',
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'
}
def web(url):
    db_data = requests.get(url, headers=header)
    # 這里直接將其編碼之前部分替換掉,防止之后使用轉(zhuǎn)義
    soup = BeautifulSoup(db_data.text.replace("&#x",""), 'lxml')
    titles = soup.select(
        'body > div.banner > div > div.celeInfo-right.clearfix > div.movie-stats-container > div > div > span > span')
    wotfs = soup.select('head > style')

    wotflist = str(wotfs[0]).split('\n')
    maoyanwotf就是當前頁面所使用的woff地址了。

     = wotflist[5].replace(' ','').replace('url(\'//','').replace('format(\'woff\');','').replace('\')','')

            
          

此時titles就是一個獲取了評分span的list,當然它只有一個元素。

maoyanwotf就是當前頁面所使用的woff地址了。

2.woff下載

上一步我們得到了maoyanwotf,其中是當前頁面所使用的woff地址,所以接下來就要對這個url進行下載,保存到本地。

            
              # 下載請求電影頁面的woff字體到本地
def downfont(maoyanwotf):
    r = requests.get('http://'+maoyanwotf)
    with open("demo.woff", "wb") as code:
        code.write(r.content)
    font = TTFont("demo.woff")
    font.saveXML('to.xml')

            
          

這樣就下載到了這次請求頁面所用的woff了,保存為demo.woff。

3.字體解析規(guī)則

那么這個to.xml有什么用呢?

這就是我們在每次刷新都會改變woff的情況下,實現(xiàn)爬取的關鍵所在了。

font.saveXML(‘to.xml’)就是將TTFont打開的woff轉(zhuǎn)換為xml的形式,在xml中我們可以直接找到字體的相關數(shù)據(jù),比如一個字符的筆畫信息等。

來看一個字體xml文件的重要內(nèi)容。完整內(nèi)容參考:to.xml

            
                            
                
                
                
                
                
  ....
  
                
                
                
              
                            
                
                                
                  
                    
                    
      ...
      
                    
                  
                  
                
                
  ...
  ...
  
                
                  
                    
                    
        ...
      
                    
                  
                  
                
              
            
          

GlyphOrder 這個標簽中就是這個字體xml包含的字符種類了,glyph00000和x這兩個不用考慮。

glyf 這個標簽中是這些字體的具體坐標畫法,一個TTGlyph對應一個字體,而其中contour標簽的坐標數(shù)據(jù),就是唯一確定這個字體是什么的最好的確定方法。

所以可以得出結論,不管每次請求的woff怎么變,它里面的字符的contour標簽內(nèi)的坐標畫法是不會改變的。

既然如此,我們只需要一個模板,在這個模板中,我們先手動解碼一個充當模板的woff。

如何制作這樣一個模板呢?

我們先來找一個woff和woff生成的xml,woff可以用字體查看器High-Logic FontCreator打開。效果如下。
Python字體反爬教科書級別的網(wǎng)站-貓眼電影_第5張圖片
之后我們將模板xml里面的glyf中TTGlyph標簽的name屬性與打開的woff對應比較,得到這個數(shù)值列表(我這里woff和xml用的不是同一個,所以不要用這個比較!!!)
Python字體反爬教科書級別的網(wǎng)站-貓眼電影_第6張圖片
之后我們就可以根據(jù)glyf中TTGlyph的順序得到解碼數(shù)值的順序,之所以要一一對應,是為了方便之后用下標索引。

            
                num = [8,6,2,1,4,3,0,9,5,7]  #這個值是直接硬編碼進去的。
  data = []
  # 此處以解析xml的方式得到這個模板xml里面contour標簽的內(nèi)容。
  xmlfilepath_temp = os.path.abspath("temp.xml")
  domobj_temp = xmldom.parse(xmlfilepath_temp)
  elementobj_temp = domobj_temp.documentElement
  subElementObj = elementobj_temp.getElementsByTagName("TTGlyph")
  for i in range(len(subElementObj)):
    rereobj = re.compile(r"name=\"(.*)\"")
    find_list = rereobj.findall(str(subElementObj[i].toprettyxml()))
    data.append(str(subElementObj[i].toprettyxml()).replace(find_list[0],'').replace("\n",''))

            
          

最后data里面是glyf中TTGlyph按順序的內(nèi)容,其中當然就是contour了,而它的下表與num中一一對應,也就是說,這時候給你一個contour的坐標內(nèi)容,那就可以在data中查找它的對應下標,根據(jù)這個下標找到num中下標的元素,這個元素就是解碼后的值了!!!

獲得了模板,我們接下來就可以將請求這次頁面時獲得的woff轉(zhuǎn)化為xml進行對應了。

            
              font = TTFont("demo.woff")
font.saveXML('to.xml')

#本次請求下載的字體的contour
new_font = []
xmlfilepath_find = os.path.abspath("to.xml")
domobj_find = xmldom.parse(xmlfilepath_find)
elementobj_find = domobj_find.documentElement
tunicode = elementobj_find.getElementsByTagName("TTGlyph")
for i in range(len(tunicode)):
    th = tunicode[i].toprettyxml()
    report = re.compile(r"name=\"(.*)\"")
    find_this = report.findall(th)
    get_code = th.replace(find_this[0], '').replace("\n", '')
    for j in range(len(data)):
        if not cmp(get_code,data[j]):
            new_font.append(num[j])

            
          

其中get_code就是這次頁面時獲得的字體數(shù)據(jù)的list元素之一了,通過循環(huán)遍歷,最終得到了一個本次xml的對應數(shù)字的list : new_font 。

接下來獲得一個編碼與具體數(shù)字對應的font_list

            
                  font = TTFont("demo.woff")
    font_list = font.getGlyphNames()
    font_list.remove('glyph00000')
    font_list.remove('x')

            
          

此時,有了new_font中的具體數(shù)字和font_list中的編碼值就可以完全解碼這個頁面中因為woff編碼反爬蟲的評分了。

            
              # 匹配
star_woff = re.findall(re.compile(r">(.*)<"), str(titles[0]))[0].replace(';','').split('.')  ;titles[0]是在第一步網(wǎng)頁解析時獲得的評分所在span
for i in star_woff:
    getthis = i.upper()
    for j in range(len(font_list)):
        if not cmp(getthis,font_list[j].replace("uni","")):
            print(new_font[j])

            
          

這樣就會輸出評分的整數(shù)部分和小數(shù)部分了。雖然這里只是輸出了這兩個數(shù)字,但是反爬蟲評分,票房,人數(shù)等數(shù)據(jù)均可以使用前一步的new_font和font_list進行處理,就不再加以闡述了。
Python字體反爬教科書級別的網(wǎng)站-貓眼電影_第7張圖片


更多文章、技術交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 余姚市| 吉林市| 冷水江市| 韩城市| 波密县| 巴彦县| 马关县| 囊谦县| 石阡县| 浠水县| 彰化县| 浏阳市| 闸北区| 且末县| 伊金霍洛旗| 沾化县| 新乡市| 合阳县| 新昌县| 体育| 黄梅县| 拉孜县| 嫩江县| 萨嘎县| 侯马市| 孟津县| 资中县| 攀枝花市| 南陵县| 德庆县| 赞皇县| 石楼县| 千阳县| 全南县| 长兴县| 祁连县| 西华县| 岢岚县| 莒南县| 若尔盖县| 海兴县|