import re
import time
import requests
from lxml import etree
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from fontTools.ttLib import TTFont #导入字体处理模块
# 定义请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}
# 实例化options对象
options = Options()
# 添加experimental_option,禁用自动化扩展,防止被检测到使用了自动化工具进行操作
options.add_experimental_option('excludeSwitches', ['enable-automation'])
# 添加argument, 禁用浏览器自动化特性,防止被检测到使用了自动化工具进行操作
options.add_argument("--disable-blink-features=AutomationControlled")
# 添加argument,忽略证书错误,防止因证书错误导致的访问失败
options.add_argument('ignore-certificate-errors')
# 实例化浏览器对象
driver = webdriver.Chrome(options=options)
driver.get('https://www.qidian.com/rank/yuepiao/')
driver.maximize_window()
# 获取网页html数据
html_text = driver.page_source
# 使用xpath表达式筛选出20本书的名字
html = etree.HTML(html_text)
book_name_list = html.xpath('//h2/a/text()')
# 使用xpath表达式筛选出20本书的月票数
book_ticket_text_list = html.xpath('//p/span/span/text()')
# 定义空列表用于存放还原后的20本书的原始符号
book_ticket_list = []
# 将渲染后的乱码文本还原成网页中看到的原始符号
for book_ticket_text in book_ticket_text_list:
# 将字符串中的每个字符进行还原
converted_data = ''.join('&#{};'.format(ord(b)) for b in book_ticket_text)
# 将还原的每本书的月票原始字符追加到列表中
book_ticket_list.append(converted_data)
# 从网页中筛选出字体链接所在的style标签
font_url_text = html.xpath('//style/text()')[0]
"""
format('eot'); src: url('https://qidian.gtimg.com/qd_anti_spider/qqIQdXrX.woff') format('woff')
"""
# 使用正则表达式来筛选出字体文件的链接
font_re = r"format\('eot'\); src: url\('(.*?)'\) format\('woff'\)"
font_url = re.findall(font_re, font_url_text)[0]
# 发起网络请求获取字体文件的数据
response = requests.get(font_url, headers=headers)
# 将字体数据保存成字体文件
with open('font.woff', 'wb') as file:
file.write(response.content)
# 使用TTFont打开字体文件
font_obj = TTFont('font.woff')
# 从字体文件中提取cmap数据
cmap_dict = font_obj.getBestCmap()
# 定义英文与数字的对应字典
number_dict = {
'one': '1',
'two': '2',
'three': '3',
'four': '4',
'five': '5',
'six': '6',
'seven': '7',
'eight': '8',
'nine': '9',
'zero': '0',
'period': '.',
}
# 将读取出来的cmap数据中的英文单词替换成阿拉伯数字
for i in cmap_dict:
for j in number_dict:
if cmap_dict[i] == j:
cmap_dict[i] = number_dict[j]
for book_name, book_ticket in zip(book_name_list, book_ticket_list):
# 将原始字符中的&#;这三个符号去除
number_list = re.findall(r'\d+', book_ticket)
# 定义一个空字符产用于保存每本书的中月票的每位数
number_str = ''
# 对去除后的原始字符列表进行遍历,得到每位数的十进制值
for number in number_list:
# 从替换后的cmap字典中使用遍历出来的键去取值
num = cmap_dict.get(int(number))
# 将取出来的每位数连接起来
number_str += num
print(f'书籍名称:{book_name} 月票数量:{number_str}')
利用fonttools破解网页字体加密反爬
最新推荐文章于 2024-08-03 19:27:22 发布