XiaoZouYu 发表于 2022-5-22 12:34

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

我怀疑你是过来秀技术的哈哈

区长 发表于 2022-5-22 14:10

cdsgg 发表于 2022-5-22 13:05
我怀疑你是过来秀技术的哈哈

比较同意{:1_907:}

XiaoZouYu 发表于 2022-5-22 15:50

cdsgg 发表于 2022-5-22 13:05
我怀疑你是过来秀技术的哈哈

哈哈,并没有,发帖只是为了和大家讨论学习,寻找不同的方法。没有一丝丝秀的意思{:1_906:}

cdsgg 发表于 2022-5-22 15:50

XiaoZouYu 发表于 2022-5-22 15:50
哈哈,并没有,发帖只是为了和大家讨论学习,寻找不同的方法。没有一丝丝秀的意思

我有一个例子 你可以参考一下

XiaoZouYu 发表于 2022-5-22 15:51

区长 发表于 2022-5-22 14:10
比较同意

真的没有啦:dizzy:

cdsgg 发表于 2022-5-22 15:52

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

XiaoZouYu 发表于 2022-5-22 15:56

cdsgg 发表于 2022-5-22 15:52
def get_page_show_ret(mystr, bs64_str):
    font = TTFont(BytesIO(base64 ...

感谢感谢,借鉴了{:1_918:}

feiyu361 发表于 2022-5-23 11:17

666666,很好,学习了
页: [1]
查看完整版本: python字体反爬求助