python字体反爬求助
一个python小菜鸟,在起点中文网上爬取月票数据,遇到了字体反爬,弄了好久才勉强弄出来了,麻烦大佬们给点建议,有更简单的方法分享下,救救孩子啊啊啊{:1_889:}import re
import requests
from fontTools.ttLib import TTFont
from lxml import etree
if __name__ == '__main__':
url_ = 'https://www.qidian.com/rank/yuepiao/'
headers_ = {
'Cookie': 'e1=%7B%22pid%22%3A%22qd_P_rank_01%22%2C%22eid%22%3A%22qd_C45%22%2C%22l1%22%3A5%7D; e2=%7B%22pid%22%3A%22qd_P_rank_01%22%2C%22eid%22%3A%22qd_C46%22%2C%22l1%22%3A5%7D; newstatisticUUID=1653031883_243064998; _csrfToken=SqNQc9cnJezKvfEbUcq8hUVBBpkKKZnStUjihiGS; fu=317266460; _gid=GA1.2.102240006.1653031887; e1=%7B%22pid%22%3A%22qd_p_qidian%22%2C%22eid%22%3A%22qd_A16%22%2C%22l1%22%3A3%7D; e2=%7B%22pid%22%3A%22qd_p_qidian%22%2C%22eid%22%3A%22qd_A16%22%2C%22l1%22%3A3%7D; _yep_uuid=437ba5a1-9bf2-cf11-e031-4198b9b208d2; _gat_gtag_UA_199934072_2=1; _ga_FZMMH98S83=GS1.1.1653183720.5.1.1653183739.0; _ga_PFYW0QLV3P=GS1.1.1653183720.5.1.1653183739.0; _ga=GA1.2.1828961077.1653031887',
'Referer': 'https://www.qidian.com/rank/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36',
'connection': 'close'
}
response_ = requests.get(url_,headers=headers_)
str_data = response_.text
# 把拿到的数据转换为xpath能够转化的数据
html_obj = etree.HTML(str_data)
# 解析书名
title_list = html_obj.xpath('//h2/a/text()')
# 解析月票数据,用xpath无法解析,考虑使用正则
ticket_list = re.findall(r'</style><span class=".+?">(.*?)</span></span>月票</p>',str_data)
# print(ticket_list)
# 提取字体的url,用xapth不能直接获取,需要进一步用正则
res_ = html_obj.xpath('//style/text()')
# print(res_)
font_url = re.findall("format\('eot'\); src: url\('(.*?)'\) format\('woff'\)",res_)
# print(font_url)
# 发送请求,获取字体加密文件
font_response = requests.get(font_url,headers=headers_)
# 保存获取到的字体加密文件
with open('font_data.woff', 'wb') as f:
f.write(font_response.content)
# 解析字体加密文件
font_obj = TTFont('font_data.woff')
# 转换为能看懂的格式xml
font_obj.saveXML('font_data.xml')
# 获取其中的加密映射表
camp_dict = font_obj.getBestCmap()
# print(camp_dict)
# 创建一个英文和数字匹配的字典,与加密数字匹配
dict_number = {'one':'1','two':'2','three':'3','four':'4','five':'5','six':'6','seven':'7','eight':'8','nine':'9','zero':'0','preiod':'.',}
for i in camp_dict:
for j in dict_number:
if camp_dict == j:
camp_dict = dict_number
# print(camp_dict)
# 因为我们在网页中拿到的加密有特殊字符混在其中,先去掉特殊字符
for i in enumerate(ticket_list):
new_ticket_list = re.findall('\d+',i)
ticket_list] = new_ticket_list
# print(ticket_list)
# 去掉特殊字符后与得到的映射表匹配出数字
for i in ticket_list:
for j in enumerate(i):
for n in camp_dict:
if j == str(n):
i] = camp_dict
# print(ticket_list)
# 把拿到的列表中子列表的引号去掉
ultimately_ticket_list = []
for i in ticket_list:
j = ''
for k in i:
j += k
ultimately_ticket_list.append(j)
# print(ultimately_ticket_list)
rank_list = dict(zip(title_list,ultimately_ticket_list))
print(rank_list) 我怀疑你是过来秀技术的哈哈 cdsgg 发表于 2022-5-22 13:05
我怀疑你是过来秀技术的哈哈
比较同意{:1_907:} cdsgg 发表于 2022-5-22 13:05
我怀疑你是过来秀技术的哈哈
哈哈,并没有,发帖只是为了和大家讨论学习,寻找不同的方法。没有一丝丝秀的意思{:1_906:} XiaoZouYu 发表于 2022-5-22 15:50
哈哈,并没有,发帖只是为了和大家讨论学习,寻找不同的方法。没有一丝丝秀的意思
我有一个例子 你可以参考一下 区长 发表于 2022-5-22 14:10
比较同意
真的没有啦:dizzy: XiaoZouYu 发表于 2022-5-22 15:50
哈哈,并没有,发帖只是为了和大家讨论学习,寻找不同的方法。没有一丝丝秀的意思
def get_page_show_ret(mystr, bs64_str):
font = TTFont(BytesIO(base64.decodebytes(bs64_str.encode())))
# 可用于58 等字体加密的反爬爬取
c = font['cmap'].tables.ttFont.tables['cmap'].tables.cmap
ret_list = []
for char in mystr:
decode_num = ord(char)
if decode_num in c:
num = c
num = int(num[-2:]) - 1
ret_list.append(num)
else:
ret_list.append(char)
ret_str_show = ''
for num in ret_list:
ret_str_show += str(num)
return ret_str_show cdsgg 发表于 2022-5-22 15:52
def get_page_show_ret(mystr, bs64_str):
font = TTFont(BytesIO(base64 ...
感谢感谢,借鉴了{:1_918:} 666666,很好,学习了
页:
[1]