0125程式設計-58租房網爬蟲-字型反爬破解
58同城租房網 採用了字型反爬機制,利用字型對頁面上的部分數字(如房價、面積平米數)進行了加密處理。

下面的程式碼包含了爬取房源基本資訊並儲存為檔案的全部程式碼,在mac下執行有效,windows系統需要參照這裡做些必要調整。
以下是抓取房源列表頁面並儲存為多個html檔案,注意更換你的headers內容。
header_str=''' accept: text/html ... user-agent: Mozilla/5.0 ''' #字串轉dict def str2dict(s,s1=';',s2='='): li=s.split(s1) res={} for kv in li: li2=kv.split(s2) if len(li2)>1: res[li2[0]]=li2[1] return res headers=str2dict(header_str,'\n',': ') #每頁儲存為本地html頁面待用 import requests import time #地址為蘇州市 urlstr = 'https://su.58.com/zufang/pn2/?PGTID=0d300008-0000-5965-8ce1-1873463f7758&ClickID={}' def getPages(n, m): for i in range(n, m): print('GETING...', i) url = urlstr.format(i) res = requests.get(url, headers=headers) with open(r'./pages/{}.html'.format(i), 'w') as f: f.write(res.text) time.sleep(1) print('OK!') getPages(9, 10)
以下是用於破解字型反爬加密的程式碼。
from fontTools.ttLib import TTFont import base64 import re import io def getKey(script): try: return re.findall(r"base64,(.*)'\).format", script)[0] except: return None def getFont(key): data = base64.b64decode(key) fonts = TTFont(io.BytesIO(data)) return fonts.getBestCmap() def getDigit(str): d = re.findall(r'(\d+)', str)[0] return int(d) - 1 def getRealValue(script, string): key = getKey(script) fontMap = getFont(key) newMap = dict() #微軟雅黑的對應的編碼 font58 = { '閏': '0x958f', '鵂': '0x9e3a', '麣': '0x9ea3', '餼': '0x993c', '鑶': '0x9476', '龤': '0x9fa4', '齤': '0x9f64', '龥': '0x9fa5', '龒': '0x9f92', '驋': '0x9a4b', } for key in fontMap.keys(): value = getDigit(fontMap[key]) key = hex(key) newMap[key] = value result = '' for char in string: temp = font58[char] value = newMap[temp] result = '%s%d' % (result, value) return int(result)
以下是從本地html檔案讀取資料並解密其中的數字。
from bs4 import BeautifulSoup import os files = os.listdir(r'./pages/') file_li = [r'./pages/' + s for s in files] items = [] for fp in file_li: with open(fp, 'r') as f: html = f.read() soup = BeautifulSoup(html) li = soup.find('ul', 'listUl').find_all('li')[:-1] script = soup.find('head').find_all('script')[-1:] for item in li: title = item.find('h2').text.strip() money = item.find('div', 'money').b.text.strip() money = getRealValue(script[0].text, money) roomtag = item.find('p', 'room strongbox') m2 = roomtag.text.split(' ')[-1:][0].replace('\xa0', '').replace( '㎡', '') m2li = m2.split('.') m2li2 = [] for m in m2li: m2li2.append(str(getRealValue(script[0].text, m))) size = '.'.join(m2li2) items.append(dict( title=title, money=money, size=size, )) print('OK!')
最後是將items物件寫入json檔案並測試讀取。
import json with open('items.json', 'w') as f: f.write(json.dumps(items)) print('Write OK!') with open('items.json', 'r') as f: readItems=json.loads(f.read()) print(readItems[10]) print('Read OK!')
每個人的智慧新時代
如果您發現文章錯誤,請不吝留言指正;
如果您覺得有用,請點喜歡;
如果您覺得很有用,歡迎轉載~
END