原因
今天下午在抓取一个网页时,发现的网页字体反爬,这种情况一句话总结:即网页文本里的数字与网页上显示的字体不一致。为什么会出现这样的情况呢?原因是开发者在网页文本里引入了改变字体的文件。
然后可以看到,这是网页文本里的数字:
这是网页显示数字:
手段并不是太高明,这个动态网页比,难度还是不大的。
解决办法如下:
在请求完网页下载完网页文本后,找到网页文本里字体的源地址:
然后,把它下载下来并保存:
然后,你需要使用 fontTools这个库, pip install fontTools,使用这个库需要注意地方,就是你本地先要有一份字体文件,然后,你在爬取每个网页的时候,就会下载那个网页独占的字体文件,再与本地的做对比,就能拿到正确的数字:
local 为本地文件, online 为每次下载的文件,这样便能得到正确的数字了。
总的来说,就是爬虫过程中,加入了下载字体文件,并识别字体文件的操作。
下面附上代码:
# !/usr/bin/env python 3.6
# -*- coding: utf-8 -*-
# Author: fcj
# Time: 2019-04-29
# Description: 字体反爬
from fontTools.ttLib import TTFont
import requests
from lxml import etree
import re
def get_html(html_url):
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'
',application/signed-exchange;v=b3',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Connection': 'keep-alive',
'Cookie'',
'DNT': '1',
'Host':',
'Referer':',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
}
content, wof_url = get_content(get_url=html_url, headers=headers)
file_path = get_file(wf_url=wof_url)
online_fonts = TTFont(file_path)
base_fonts = TTFont('D:/3yl1dB.woff')
tmp = exec_wof(online=online_fonts, local=base_fonts)
nums = content.xpath('//div[@class="col-md-1"]//text()')
an = get_ans(nums=nums, tmp=tmp)
return an
def exec_wof(online, local): # 得到对应的数字
num_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
eng_list = ['zero', 'four', 'eight', 'nine', 'five', 'six', 'two', 'seven', 'three', 'one']
uni_list = online.getGlyphNames()[1:]
uni_list.remove('glyph00011')
tmp = {}
for i in range(10):
online_glyph = online['glyf'][uni_list[i]] # 返回的是unicode对应信息的对象
for j in range(10):
base_glyph = local['glyf'][eng_list[j]]
if online_glyph == base_glyph:
tmp[uni_list[i]] = num_list[j]
return tmp
def get_wof(content): # 得到字体url
url = re.findall('\("https.*?"\)', content)
url = str(''.join(url)).replace('"', '').replace(')', '').replace('(', '')
return url
def get_file(wf_url): # 下载保存字体文件
data = requests.get(url=wf_url, verify=False)
r = data.content
name = wf_url.split('/')[-1]
path = 'D:/jiao cheng/'+name
with open(path, 'wb') as f:
f.write(r)
f.close()
return path
def get_ans(nums, tmp): # 得到答案
an = 0
for num in nums:
num = re.findall('[0-9]', ''.join(num))
real_list = []
for n in num:
real_list.append(str(translate_num(str(n), tmp)))
real_num = int(''.join(real_list))
an += real_num
return an
def get_content(get_url, headers): # 下载处理网页
data = requests.get(url=get_url, headers=headers, verify=False)
r = data.content
content = str(r, encoding='utf-8', errors='ignore')
wof_url = get_wof(content=content)
s = etree.HTML(content.replace('<br>', '').replace('\n', '').replace('</br>', '').replace('\t', '').
replace('\xa0', '').replace('\u3000', '').replace('\r', ''))
return s, wof_url
def translate_num(number, tmp):
eng_list = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
number = eng_list[str(number) - 1]
return tmp[number]
if __name__ == '__main__':
ul = '
asn = 0
for index in range(1, 1001):
hl = ul + str(index)
asn += get_html(html_url=hl
print(asn)