爬取在线全面小说网小说(字体反爬)

本文探讨了针对小说网站的字体反爬策略,通过解析ttf文件并使用fontTools库转换为xml来查看映射关系。在遇到汉字无法直接从ttf文件获取unicode码时,借助FontCreate工具建立映射字典进行替换。提供的代码示例展示了如何处理部分替换汉字,尽管效率较低,但能满足日常需求。文章最后提到,对于经常更新的网站,现有的解决方案可能难以维持,并暗示需要更深入的研究。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小说网字体反爬

小说网址:https://www.tianhuajinshu.com/

在手机端浏览小说时,有时候开启无图模式发现部分文字加载不出来,还有的不能使用浏览自带的阅读模式进行阅读,也就是无法解析,所以进一步探究原因,最后发现是小说网站设置了字体反爬。

在爬取之前查了一些资料:
爬虫:碰见字体反爬如何处理 --程序员大本营
字体反爬的解决方案——突破抖音反爬虫机制
爬虫进阶-- 字体反爬终极解析
百度字体编辑器

刚开始网上提供的一些案例基本是"58同城"、抖音,还有一个电影网(忘记是啥了)。
基本操作是:

1.通过网页解析下载ttf或者woff文件,然后
from fontTools.ttLib 
import TTFont
font = TTFont('**.ttf')
font.saveXML('**.xml')

将ttf文件转换为xml文件方便查看;或者直接在FontCreate工具中查看。

2.在xml文件的cmap中查看映射关系。

其中code是网页中显示的编码,name或许是数字对应的unicode,可通过推测找到映射关系。

被替换了要么是10个阿拉伯数字,要么ttf中直接有汉字对应的unicode码,根本行不通。
最终的效果并不理想,因为不能直接从ttf文件以及fontTools库来解析汉字对应的unicode码,只能通过FontCreate程序来查看map code对应的汉字设置字典进行替换,所幸由于渲染等因素,需要替换的文字有100个,还可以接受,但是网站经常更新的话肯定吃不消,再进一步查找资料:
反爬终极方案总结—字体反爬
看了一下,看来还有很长的路要走,日常需求基本能够满足,用工具也差不多能达到效果,之后有进一步需求再继续学吧。
顺便贴一下简易的代码

#从FontCreate工具得知的映射关系
# txt_dict = {
#             '\ue800':'的','\ue801':'一','\ue802':'是','\ue803':'了','\ue804':'我',
#             '\ue805':'不','\ue806':'人','\ue807':'在','\ue808':'他','\ue809':'有',
#             '\ue80a':'这','\ue80b':'个','\ue80c':'上','\ue80d':'们','\ue80e':'来',
#             '\ue80f':'到','\ue810':'时','\ue811':'大','\ue812':'地','\ue813':'为',
#             '\ue814':'子','\ue815':'中','\ue816':'你','\ue817':'说','\ue818':'生',
#             '\ue819':'国','\ue81a':'年','\ue81b':'着','\ue81c':'就','\ue81d':'那',
#             '\ue81e':'和','\ue81f':'要','\ue820':'她','\ue821':'出','\ue822':'也',
#             '\ue823':'得','\ue824':'里','\ue825':'后','\ue826':'自','\ue827':'以',
#             '\ue828':'会','\ue829':'家','\ue82a':'可','\ue82b':'下','\ue82c':'而',
#             '\ue82d':'过','\ue82e':'天','\ue82f':'去','\ue830':'能','\ue831':'对',
#             '\ue832':'小','\ue833':'多','\ue834':'然','\ue835':'于','\ue836':'心',
#             '\ue837':'学','\ue838':'么','\ue839':'之','\ue83a':'都','\ue83b':'好',
#             '\ue83c':'看','\ue83d':'起','\ue83e':'发','\ue83f':'当','\ue840':'没',
#             '\ue841':'成','\ue842':'只','\ue843':'如','\ue844':'事','\ue845':'把',
#             '\ue846':'还','\ue847':'用','\ue848':'第','\ue849':'让','\ue84a':'道',
#             '\ue84b':'想','\ue84c':'作','\ue84d':'种','\ue84e':'开','\ue84f':'美',
#             '\ue850':'总','\ue851':'从','\ue852':'无','\ue853':'情','\ue854':'己',
#             '\ue855':'面','\ue856':'最','\ue857':'女','\ue858':'但','\ue859':'现',
#             '\ue85a':'前','\ue85b':'些','\ue85c':'所','\ue85d':'同','\ue85e':'日',
#             '\ue85f':'手','\ue860':'又','\ue861':'行','\ue862':'意','\ue863':'动'}
import requests
from bs4 import BeautifulSoup
import bs4
import time
#字体反爬
#2021-1-18
#url = "https://www.tianhuajinshu.com/tian1/41720/F6sex3JAIbH7F.html"
list_1 = [
            '\ue800','\ue801','\ue802','\ue803','\ue804',
            '\ue805','\ue806','\ue807','\ue808','\ue809',
            '\ue80a','\ue80b','\ue80c','\ue80d','\ue80e',
            '\ue80f','\ue810','\ue811','\ue812','\ue813',
            '\ue814','\ue815','\ue816','\ue817','\ue818',
            '\ue819','\ue81a','\ue81b','\ue81c','\ue81d',
            '\ue81e','\ue81f','\ue820','\ue821','\ue822',
            '\ue823','\ue824','\ue825','\ue826','\ue827',
            '\ue828','\ue829','\ue82a','\ue82b','\ue82c',
            '\ue82d','\ue82e','\ue82f','\ue830','\ue831',
            '\ue832','\ue833','\ue834','\ue835','\ue836',
            '\ue837','\ue838','\ue839','\ue83a','\ue83b',
            '\ue83c','\ue83d','\ue83e','\ue83f','\ue840',
            '\ue841','\ue842','\ue843','\ue844','\ue845',
            '\ue846','\ue847','\ue848','\ue849','\ue84a',
            '\ue84b','\ue84c','\ue84d','\ue84e','\ue84f',
            '\ue850','\ue851','\ue852','\ue853','\ue854',
            '\ue855','\ue856','\ue857','\ue858','\ue859',
            '\ue85a','\ue85b','\ue85c','\ue85d','\ue85e',
            '\ue85f','\ue860','\ue861','\ue862','\ue863']
list_2 = [
            '的','一','是','了','我',
            '不','人','在','他','有',
            '这','个','上','们','来',
            '到','时','大','地','为',
            '子','中','你','说','生',
            '国','年','着','就','那',
            '和','要','她','出','也',
            '得','里','后','自','以',
            '会','家','可','下','而',
            '过','天','去','能','对',
            '小','多','然','于','心',
            '学','么','之','都','好',
            '看','起','发','当','没',
            '成','只','如','事','把',
            '还','用','第','让','道',
            '想','作','种','开','美',
            '总','从','无','情','己',
            '面','最','女','但','现',
            '前','些','所','同','日',
            '手','又','行','意','动']

def crawl(url, pre_1=''):
    hd = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                        '(KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
    r = requests.get(url,headers=hd)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    html = r.text
    soup = BeautifulSoup(html, "html.parser")   #解析
    #novel = soup.find('div',"con_top")('a')[2].text #小说名
    chapter = soup.find('h1').string    #小说章节
    print("正在下载章节:",chapter)
    content = soup.find('div', id="txt").text#小说内容
    content_list = list(content)
    #这个地方效率很低,但是不知道怎么处理,以下用的是最简单粗暴的遍历每个字
    length = len(content)
    for i in range(length):
        for j in range(100):
            if content_list[i] == '\u3000':
                content_list[i] = '\n'
            elif content_list[i] == list_1[j]:
                content_list[i]=list_2[j]
    content_s = ''
    content_s = ''.join(content_list)
    #print(content_s[0])
    #print(content_s)
    novel_name = 'novel.txt'
    with open(novel_name, 'a', encoding='utf-8') as f:
        f.write('\n'+chapter+'\n')
        f.write(content_s)
        f.close()
    pre = "https://www.tianhuajinshu.com/tian1/41720/F6sex3JAIbH7F.html"
    #next_url比较特殊,该小说网站比较特别的是一个章节有分几页,如果还在本章节,下一页的url是加上?page= 拼接
    #否则是下一章节的url
    next_url = soup.find('li', 'next')('a')[0].get('href')
    if len(next_url)>10:#换章节
        true_next = next_url
        #pre = next_url
        pre_1 = next_url
    else:#不换章节,拼上?page=
        if pre_1 == '':#第一章
            true_next = pre + next_url#初始url+ ?page=
        else:#非第一章
            true_next = pre_1 + next_url

    if next_url:
        return true_next,pre_1#如果是新章节,那么是正确的,如果是旧章节,返回是相加之后的
    else:
        return False

if __name__=='__main__':
    url = "https://www.tianhuajinshu.com/tian1/41720/F6sex3JAIbH7F.html"#初始url
    url,pre_1 = crawl(url)
    while(1):
        time.sleep(1)   #爬取过快防止网站503
        url, pre_1 = crawl(url,pre_1)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值