本文的文字及圖片來源于網路,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯系我們以作處理,
以下文章來源于早起Python ,作者劉早起
Python爬蟲、資料分析、網站開發等案例教程視頻免費在線觀看
https://space.bilibili.com/523606542
在前幾天針某點評商家搜索頁面的字體反爬給出了解決方案,但是還有一個問題,那就是當時給出的方法是下載對應的woff字體檔案,然后建立加密字體與編碼之間的映射關系來進行破解,
但是有一個問題就是不同頁面的字體檔案,是動態加載的,換句話說就是你在這個頁面建立的映射關系,換一個頁面就不能用了,
那就沒有解決辦法了嗎?其實也不難,或者說對方還是給了很清晰的思考方向,因為,雖然每一個頁面的字體是動態加載的,但是這個動態僅針對字體決議后編碼的變化,字體內部順序是沒有變化的,也就是如下圖所示
每兩個頁面中,僅僅是字體編碼發生了改變,而字體的位置順序并沒有改變,所以我們只需要在決議每一頁的資料之前,先提取頁面中CSS樣式,再從CSS內容中定位到字體檔案存盤鏈接,之后就是請求這一頁對應的字體檔案并決議構造匹配字典,后面的步驟就和上一篇文章一樣了,
那我們開始,目標是爬取某城市指定美食的全部商家資訊,比如定位廣州搜索沙縣小吃,之后爬取全部的搜索頁面,
首先就是構造全部的URL,由于每一頁的URL是有一定規律的,所以這一步很簡單,從第一頁中提取全部頁數然后按照規律添加到url_list中即可,而這個資料沒有被加密
所以這部分代碼可以這樣寫
def get_url(url):
headers = {
"Host": "www.dianping.com",
"Referer":f"{url}",
"User-Agent":ua.random,
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1"
}
r = requests.get(url = url,headers = headers,proxies = get_ip())
soup = BeautifulSoup(r.text)
page_num = int(soup.find_all('a',class_ = 'PageLink')[-1].text)
url_list = [url + f"/p{i+1}" for i in range(page_num)]
return url_list
這部分代碼不難理解構造請求——決議頁面——提取頁數——模擬URL,其中get_ip()必須要回傳一個可以使用的ip,不論你是用免費的還是付費的代理,在這里不做詳細講解,
搞定URL之后,我們來到最關鍵的步驟,寫一個函式,傳進來一個頁面回傳該頁的文字匹配字典,那么第一步就是把字體拿下來,下面四行代碼即可搞定
css_url = "http://" + re.search(r's3plus.meituan.net/(.*?)/svgtextcss/(.*?).css', page.text).group(0) #拿到css檔案
css_value = requests.get(css_url).text
addr_font = "http:" + re.search(r'address(.*?).woff', css_value).group(0).split(',')[-1][5:]
price_font = "http:" + re.search(r'shopNum(.*?).woff', css_value).group(0).split(',')[-1][5:]
簡單來看一下這段代碼,我們傳入一個請求后得到的page后
“
第一行代碼使用正則運算式提取字體所在的css鏈接
第二行代碼使用requests請求css內容
最后兩行代碼使用正則提取woff字體檔案所在URL
”
如果你傳進去的頁面是正常的,那么現在我們就有地址、均價欄位的字體所在URL,下面就可以使用requests將這兩個字體檔案下載并保存在本地,代碼如下
x = requests.get(addr_font).content
with open('addr.woff','wb+') as f:
f.write(x)
x = requests.get(price_font).content
with open('price.woff','wb+') as f:
f.write(x)
現在作業目錄下就有兩個字體檔案,之后就按照上一篇文章介紹的字體加密破解方法操作即可,所以這部分完整代碼如下:
def get_font(page):
'''
接收請求后的頁面
回傳該頁url字體woff檔案對應的兩個字典檔案
'''python
css_url = "http://" + re.search(r's3plus.meituan.net/(.*?)/svgtextcss/(.*?).css', page.text).group(0) #拿到css檔案
css_value = requests.get(css_url).text
addr_font = "http:" + re.search(r'address(.*?).woff', css_value).group(0).split(',')[-1][5:]
price_font = "http:" + re.search(r'shopNum(.*?).woff', css_value).group(0).split(',')[-1][5:]
#下載字體保存到本地
x = requests.get(addr_font).content
with open('addr.woff','wb+') as f:
f.write(x)
x = requests.get(price_font).content
with open('price.woff','wb+') as f:
f.write(x)
#決議字體
font_addr = TTFont('addr.woff')
font1 = font_addr.getGlyphOrder()[2:]
font1 = [font1[i][-4:] for i in range(len(font1))]
font_price = TTFont('price.woff')
font2 = font_price.getGlyphOrder()[2:]
font2 = [font2[i][-4:] for i in range(len(font2))]
font3 = ['1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', '店', '中', '美', '家', '館', '小', '車', '大',
'市', '公', '酒', '行', '國', '品', '發', '電', '金', '心',
'業', '商', '司', '超', '生', '裝', '園', '場', '食', '有',
'新', '限', '天', '面', '工', '服', '海', '華', '水', '房',
'飾', '城', '樂', '汽', '香', '部', '利', '子', '老', '藝',
'花', '專', '東', '肉', '菜', '學', '福', '飯', '人', '百',
'餐', '茶', '務', '通', '味', '所', '山', '區', '門', '藥',
'銀', '農', '龍', '停', '尚', '安', '廣', '鑫', '一', '容',
'動', '南', '具', '源', '興', '鮮', '記', '時', '機', '烤',
'文', '康', '信', '果', '陽', '理', '鍋', '寶', '達', '地',
'兒', '衣', '特', '產', '西', '批', '坊', '州', '牛', '佳',
'化', '五', '米', '修', '愛', '北', '養', '賣', '建', '材',
'三', '會', '雞', '室', '紅', '站', '德', '王', '光', '名',
'麗', '油', '院', '堂', '燒', '江', '社', '合', '星', '貨',
'型', '村', '自', '科', '快', '便', '日', '民', '營', '和',
'活', '童', '明', '器', '煙', '育', '賓', '精', '屋', '經',
'居', '莊', '石', '順', '林', '爾', '縣', '手', '廳', '銷',
'用', '好', '客', '火', '雅', '盛', '體', '旅', '之', '鞋',
'辣', '作', '粉', '包', '樓', '校', '魚', '平', '彩', '上',
'吧', '保', '永', '萬', '物', '教', '吃', '設', '醫', '正',
'造', 