在手机端浏览小说时,有时候开启无图模式发现部分文字加载不出来,还有的不能使用浏览自带的阅读模式进行阅读,也就是无法解析,所以进一步探究原因,最后发现是小说网站设置了字体反爬。
刚开始网上提供的一些案例基本是"58同城"、抖音,还有一个电影网(忘记是啥了)。
基本操作是:
1.通过网页解析下载ttf或者woff文件,然后
from fontTools.ttLib
import TTFont
font = TTFont('**.ttf')
font.saveXML('**.xml')
1
2
3
4
将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':'动'}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import requests
from bs4 import BeautifulSoup
import bs4
import time
#字体反爬
#2021-1-18
#url = "14、名场面_公派婚姻[六零]-在线全免小说网"
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 = "14、名场面_公派婚姻[六零]-在线全免小说网"
#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 = "14、名场面_公派婚姻[六零]-在线全免小说网"#初始url
url,pre_1 = crawl(url)
while(1):
time.sleep(1) #爬取过快防止网站503
url, pre_1 = crawl(url,pre_1)
近期有很多朋友通过私信咨询有关Python学习问题。为便于交流,点击蓝色自己加入讨论解答资源基地
网友评论