
作者:Python進(jìn)階者
來源:Python爬蟲與數(shù)據(jù)挖掘
今天給大家?guī)砀韶?,JS逆向。
網(wǎng)站的反爬措施有很多,例如:js反爬、ip反爬、css反爬、字體反爬、驗證碼反爬、滑動點(diǎn)擊類驗證反爬等等,今天我們通過爬取某招聘來實戰(zhàn)學(xué)習(xí)字體反爬。
小編已加密:
aHR0cHM6Ly93d3cuc2hpeGlzZW5nLmNvbS8= 出于安全原因,我們把網(wǎng)址通過base64編碼了,大家可以通過base64解碼把網(wǎng)址獲取下來。
字體反爬:一種常見的反爬技術(shù),是網(wǎng)頁與前端字體文件配合完成的反爬策略,最早使用字體反爬技術(shù)的有58同城、汽車之家等等,現(xiàn)在很多主流的網(wǎng)站或APP也使用字體反爬技術(shù)為自身的網(wǎng)站或APP增加一種反爬措施。
字體反爬原理:通過自定義的字體來替換頁面中某些數(shù)據(jù),當(dāng)我們不使用正確的解碼方式就無法獲取正確的數(shù)據(jù)內(nèi)容。
在HTML中通過@font-face來使用自定義字體,如下圖所示:
其語法格式為:
@font-face{ font-family:"名字"; src:url('字體文件鏈接'); url('字體文件鏈接')format('文件類型')
}
字體文件一般是ttf類型、eot類型、woff類型,woff類型的文件運(yùn)用比較廣泛,所以大家一般碰到的都是woff類型的文件。
以woff類型文件為例,其內(nèi)容是怎樣的呢,又是以什么編碼方式使得數(shù)據(jù)與代碼一一對應(yīng)的呢?
我們以某招聘網(wǎng)站的字體文件為例,進(jìn)入百度字體編譯器并打開字體文件,如下圖所示:
隨機(jī)打開一個字體,如下圖所示:
可以發(fā)現(xiàn)字體6放在一個平面坐標(biāo)里面,根據(jù)平面坐標(biāo)的每個點(diǎn)來得出字體6的編碼,這里就不解釋如何得出字體6的編碼了。
如何解決字體反爬呢?
首先映射關(guān)系可以看作為字典,大致有兩種常用的方法:
第一種:手動把一組編碼和字符的對應(yīng)關(guān)系提取出來并用字典的形式展示,代碼如下所示:
replace_dict={ '0xf7ce':'1', '0xf324':'2', '0xf23e':'3',
....... '0xfe43':'n',
} for key in replace_dict:
數(shù)據(jù)=數(shù)據(jù).replace(key,replace_dict[key])
首先定義字體與其對應(yīng)的代碼一一對應(yīng)的字典,再通過for循環(huán)把數(shù)據(jù)一一替換。
注意:這種方法主要適用于字體映射少的數(shù)據(jù)。
第二種:首先下載網(wǎng)站的字體文件,再把字體文件轉(zhuǎn)換為XML文件,找到里面的字體映射關(guān)系的代碼,通過decode函數(shù)解碼,然后將解碼的代碼組合成一個字典,再根據(jù)字典內(nèi)容將數(shù)據(jù)一一替換,由于代碼比較長,這里就不寫示例代碼了,待會在實戰(zhàn)演練中會展示這種方法的代碼。
好了,字體反爬就簡單講到這里,接下來我們正式爬取某招聘網(wǎng)站。
首先進(jìn)入某招聘網(wǎng)并打開開發(fā)者模式,如下圖所示:
這里我們看到代碼中只有生字不能正常函數(shù),而是用來代碼來替代,初步判定為使用了自定義的字體文件,這時就要找到字體文件了,那么字體文件在哪里找呢,首先打開開發(fā)者模式,并點(diǎn)擊Network選項,如下圖所示:
一般情況下,字體文件放在Font選卡中,我們發(fā)現(xiàn)這里一共有5個條目,那么哪個是自定義字體文件的條目呢,當(dāng)我們每次點(diǎn)擊下一頁的時候,自定義字體文件就會執(zhí)行一次,這時我們只需要點(diǎn)擊網(wǎng)頁中的下一頁即可,如下圖所示:
可以看到多了一個以file開頭的條目,這時可以初步判定該文件為自定義字體文件,現(xiàn)在我們把它下載下來,下載方式很簡單,只需要把file開頭的條目的URL復(fù)制并在網(wǎng)頁上打開即可,下載下來后在百度字體編譯器打開,如下圖所示:
這時發(fā)現(xiàn)打開不了,是不是找錯了字體文件,網(wǎng)站提示說不支持這種文件類型,那么我們把下載的文件后綴改為.woff在打開試試,如下圖所示:
這時就成功打開了。
找到自定義字體文件了,那么我們該怎么利用呢?這時我們先自定義方法get_fontfile()來處理自定義字體文件,然后在通過兩步來把字體文件中的映射關(guān)系通過字典的方式展示出來。
首先自定義字體文件更新頻率是很高的,這時我們可以實時獲取網(wǎng)頁的自定義字體文件來防止利用了之前的自定義字體文件從而導(dǎo)致獲取數(shù)據(jù)不準(zhǔn)確。首先觀察自定義字體文件的url鏈接:
https://www.xxxxxx.com/interns/iconfonts/file?rand=0.2254193167485603 https://www.xxxxxx.com/interns/iconfonts/file?rand=0.4313944100724574 https://www.xxxxxx.com/interns/iconfonts/file?rand=0.3615862774301839
可以發(fā)現(xiàn)自定義字體文件的URL只有rand這個參數(shù)發(fā)生變化,而且是隨機(jī)的十六位小于1的浮點(diǎn)數(shù),那么我們只需要構(gòu)造rand參數(shù)即可,主要代碼如下所示:
def get_fontfile(): rand=round(random.uniform(0,1),17)
url=f'https://www.xxxxxx.com/interns/iconfonts/file?rand={rand}' response=requests.get(url,headers=headers).content with open('file.woff','wb')as f:
f.write(response)
font = TTFont('file.woff')
font.saveXML('file.xml')
首先通過random.uniform()方法來控制隨機(jī)數(shù)的大小,再通過round()方法控制隨機(jī)數(shù)的位數(shù),這樣就可以得到rand的值,再通過.content把URL響應(yīng)內(nèi)容轉(zhuǎn)換為二進(jìn)制并寫入file.woff文件中,在通過TTFont()方法獲取文件內(nèi)容,通過saveXML方法把內(nèi)容保存為xml文件。xml文件內(nèi)容如下圖所示:
該字體.xml文件一共有4589行那么多,哪個部分才是字體映射關(guān)系的代碼部分呢?
首先我們看回在百度字體編碼器的內(nèi)容,如下圖所示:
漢字人對應(yīng)的代碼為f0e2,那么我們就在字體.xml文件中查詢?nèi)说拇a,如下圖所示:
可以發(fā)現(xiàn)一共有4個結(jié)果,但仔細(xì)觀察每個結(jié)果都相同,這時我們可以根據(jù)它們代碼規(guī)律來獲取映射關(guān)系,再通過解碼來獲取對應(yīng)的數(shù)據(jù)值,最后以字典的形式展示,主要代碼如下所示:
with open('file.xml') as f: xml = f.read() keys = re.findall('', xml) values = re.findall('', xml) for i in range(len(values)): if len(values[i]) < 4: values[i] = ('u00' + values[i]).encode('utf-8').decode('unicode_escape') else: values[i] = ('u' + values[i]).encode('utf-8').decode('unicode_escape')
word_dict = dict(zip(keys, values))
首先讀取file.xml文件內(nèi)容,找出把代碼中的code、name的值并分別設(shè)置為keys鍵,values值,再通過for循環(huán)把values的值解碼為我們想要的數(shù)據(jù),最后通過zip()方法合并為一個元組并通過dict()方法轉(zhuǎn)換為字典數(shù)據(jù),運(yùn)行結(jié)果如圖所示:
在上一步中,我們成功把字體映射關(guān)系轉(zhuǎn)換為字典數(shù)據(jù)了,接下來開始發(fā)出網(wǎng)絡(luò)請求來獲取數(shù)據(jù),主要代碼如下所示:
def get_data(dict,url):
response=requests.get(url,headers=headers).text.replace('&#','0') for key in dict: response=response.replace(key,dict[key])
XPATH=parsel.Selector(response)
datas=XPATH.xpath('//*[@id="__layout"]/div/div[2]/div[2]/div[1]/div[1]/div[1]/div') for i in datas: data={ 'workname':i.xpath('./div[1]/div[1]/p[1]/a/text()').extract_first(), 'link':i.xpath('./div[1]/div[1]/p[1]/a/@href').extract_first(), 'salary':i.xpath('./div[1]/div[1]/p[1]/span/text()').extract_first(), 'place':i.xpath('./div[1]/div[1]/p[2]/span[1]/text()').extract_first(), 'work_time':i.xpath('./div[1]/div[1]/p[2]/span[3]/text()').extract_first()+i.xpath('./div[1]/div[1]/p[2]/span[5]/text()').extract_first(), 'company_name':i.xpath('./div[1]/div[2]/p[1]/a/text()').extract_first(), 'Field_scale':i.xpath('./div[1]/div[2]/p[2]/span[1]/text()').extract_first()+i.xpath('./div[1]/div[2]/p[2]/span[3]/text()').extract_first(), 'advantage': ','.join(i.xpath('./div[2]/div[1]/span/text()').extract()), 'welfare':','.join(i.xpath('./div[2]/div[2]/span/text()').extract())
}
saving_data(list(data.values()))
首先自定義方法get_data()并接收字體映射關(guān)系的字典數(shù)據(jù),再通過for循環(huán)將字典內(nèi)容與數(shù)據(jù)一一替換,最后通過xpath()來提取我們想要的數(shù)據(jù),最后把數(shù)據(jù)傳入我們自定義方法saving_data()中。
數(shù)據(jù)已經(jīng)獲取下來了,接下來將保存數(shù)據(jù),主要代碼如下所示:
def saving_data(data): db = pymysql.connect(host=host, user=user, password=passwd, port=port, db='recruit')
cursor = db.cursor()
sql = 'insert into recruit_data(work_name, link, salary, place, work_time,company_name,Field_scale,advantage,welfare) values(%s,%s,%s,%s,%s,%s,%s,%s,%s)' try:
cursor.execute(sql,data)
db.commit() except:
db.rollback()
db.close()
好了,程序已經(jīng)寫得差不多了,接下來將編寫代碼運(yùn)行程序,主要代碼如下所示:
if __name__ == '__main__':
create_db()
get_fontfile() for i in range(1,3):
url=f'https://www.xxxxxx.com/interns?page={i}&type=intern&salary=-0&city=%E5%85%A8%E5%9B%BD' get_data(get_dict(),url)
好了,學(xué)習(xí)字體反爬并爬取某招聘就講到這里了?。?!
數(shù)據(jù)分析咨詢請掃描二維碼
若不方便掃碼,搜微信號:CDAshujufenxi
LSTM 模型輸入長度選擇技巧:提升序列建模效能的關(guān)鍵? 在循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)家族中,長短期記憶網(wǎng)絡(luò)(LSTM)憑借其解決長序列 ...
2025-07-11CDA 數(shù)據(jù)分析師報考條件詳解與準(zhǔn)備指南? ? 在數(shù)據(jù)驅(qū)動決策的時代浪潮下,CDA 數(shù)據(jù)分析師認(rèn)證愈發(fā)受到矚目,成為眾多有志投身數(shù) ...
2025-07-11數(shù)據(jù)透視表中兩列相乘合計的實用指南? 在數(shù)據(jù)分析的日常工作中,數(shù)據(jù)透視表憑借其強(qiáng)大的數(shù)據(jù)匯總和分析功能,成為了 Excel 用戶 ...
2025-07-11尊敬的考生: 您好! 我們誠摯通知您,CDA Level I和 Level II考試大綱將于 2025年7月25日 實施重大更新。 此次更新旨在確保認(rèn) ...
2025-07-10BI 大數(shù)據(jù)分析師:連接數(shù)據(jù)與業(yè)務(wù)的價值轉(zhuǎn)化者? ? 在大數(shù)據(jù)與商業(yè)智能(Business Intelligence,簡稱 BI)深度融合的時代,BI ...
2025-07-10SQL 在預(yù)測分析中的應(yīng)用:從數(shù)據(jù)查詢到趨勢預(yù)判? ? 在數(shù)據(jù)驅(qū)動決策的時代,預(yù)測分析作為挖掘數(shù)據(jù)潛在價值的核心手段,正被廣泛 ...
2025-07-10數(shù)據(jù)查詢結(jié)束后:分析師的收尾工作與價值深化? ? 在數(shù)據(jù)分析的全流程中,“query end”(查詢結(jié)束)并非工作的終點(diǎn),而是將數(shù) ...
2025-07-10CDA 數(shù)據(jù)分析師考試:從報考到取證的全攻略? 在數(shù)字經(jīng)濟(jì)蓬勃發(fā)展的今天,數(shù)據(jù)分析師已成為各行業(yè)爭搶的核心人才,而 CDA(Certi ...
2025-07-09【CDA干貨】單樣本趨勢性檢驗:捕捉數(shù)據(jù)背后的時間軌跡? 在數(shù)據(jù)分析的版圖中,單樣本趨勢性檢驗如同一位耐心的偵探,專注于從單 ...
2025-07-09year_month數(shù)據(jù)類型:時間維度的精準(zhǔn)切片? ? 在數(shù)據(jù)的世界里,時間是最不可或缺的維度之一,而year_month數(shù)據(jù)類型就像一把精準(zhǔn) ...
2025-07-09CDA 備考干貨:Python 在數(shù)據(jù)分析中的核心應(yīng)用與實戰(zhàn)技巧? ? 在 CDA 數(shù)據(jù)分析師認(rèn)證考試中,Python 作為數(shù)據(jù)處理與分析的核心 ...
2025-07-08SPSS 中的 Mann-Kendall 檢驗:數(shù)據(jù)趨勢與突變分析的有力工具? ? ? 在數(shù)據(jù)分析的廣袤領(lǐng)域中,準(zhǔn)確捕捉數(shù)據(jù)的趨勢變化以及識別 ...
2025-07-08備戰(zhàn) CDA 數(shù)據(jù)分析師考試:需要多久?如何規(guī)劃? CDA(Certified Data Analyst)數(shù)據(jù)分析師認(rèn)證作為國內(nèi)權(quán)威的數(shù)據(jù)分析能力認(rèn)證 ...
2025-07-08LSTM 輸出不確定的成因、影響與應(yīng)對策略? 長短期記憶網(wǎng)絡(luò)(LSTM)作為循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)的一種變體,憑借獨(dú)特的門控機(jī)制,在 ...
2025-07-07統(tǒng)計學(xué)方法在市場調(diào)研數(shù)據(jù)中的深度應(yīng)用? 市場調(diào)研是企業(yè)洞察市場動態(tài)、了解消費(fèi)者需求的重要途徑,而統(tǒng)計學(xué)方法則是市場調(diào)研數(shù) ...
2025-07-07CDA數(shù)據(jù)分析師證書考試全攻略? 在數(shù)字化浪潮席卷全球的當(dāng)下,數(shù)據(jù)已成為企業(yè)決策、行業(yè)發(fā)展的核心驅(qū)動力,數(shù)據(jù)分析師也因此成為 ...
2025-07-07剖析 CDA 數(shù)據(jù)分析師考試題型:解鎖高效備考與答題策略? CDA(Certified Data Analyst)數(shù)據(jù)分析師考試作為衡量數(shù)據(jù)專業(yè)能力的 ...
2025-07-04SQL Server 字符串截取轉(zhuǎn)日期:解鎖數(shù)據(jù)處理的關(guān)鍵技能? 在數(shù)據(jù)處理與分析工作中,數(shù)據(jù)格式的規(guī)范性是保證后續(xù)分析準(zhǔn)確性的基礎(chǔ) ...
2025-07-04CDA 數(shù)據(jù)分析師視角:從數(shù)據(jù)迷霧中探尋商業(yè)真相? 在數(shù)字化浪潮席卷全球的今天,數(shù)據(jù)已成為企業(yè)決策的核心驅(qū)動力,CDA(Certifie ...
2025-07-04CDA 數(shù)據(jù)分析師:開啟數(shù)據(jù)職業(yè)發(fā)展新征程? ? 在數(shù)據(jù)成為核心生產(chǎn)要素的今天,數(shù)據(jù)分析師的職業(yè)價值愈發(fā)凸顯。CDA(Certified D ...
2025-07-03