爬虫2_起点中文网字体反爬
今天讲一下起点中文网的列表页爬取,准备爬取的是小说书名、图片url、详情页url、作者、字数、分类及状态。
爬取网址:https://www.qidian.com/all
分析url
翻页至第二页、第三页,发现url上只有page=x这一个在改变,所以url的循环就很容易写出
def main():"""起点中文网列表页只能爬5页:return:"""for i in range(1, 6):q = QiDianZhongWenWang()url = f"https://www.qidian.com/all?orderId=&style=1&pageSize=20&siteid=1&pubflag=0&hiddenField=0&page={i}"q.get_page(url)
分析源码
- 通过F12查看渲染后的代码和Ctrl+U查看源码发现两处代码是一致的,可以判断起点中文网没有使用js渲染。(我用的是Chrome浏览器,各个浏览器查看源码的方式可能不同)
- 可以看到起点中文网的列表页每一页有20个item,分别放在每一个
<li>
标签里面
- 我们可以看到网页正常显示小说字数,但是渲染后的代码在应该显示数字的地方却是一个个方框。
- 我们Ctrl+U查看一下源代码发现对应位置的方框变成了unicode,我们可以看到这里有一个
<span>
标签,其中的class属性是一个很奇怪的字符串,在<span>
前面有一个<style>
我们看一下里面的内容。
- 可以看到这个
<style>
里面显示出了一个font文件的下载路径,而且仔细看一下代码可以发现之前<span>
里的奇怪的字符串也出现在了这个<style>
里面。
解密
- 我们直接访问上图红框划出的url,下载font文件,然后打开百度字体编辑器(http://fontstore.baidu.com/static/editor/index.html)查看一下字体的对应关系。
- 可以看数字和英文单词相对应,所以我们先写一个字典出来表示它们的对应关系。
woff_map = {"one": "1","two": "2","three": "3","four": "4","five": "5","six": "6","seven": "7","eight": "8","nine": "9","zero": "10","period": ".",}
- 然后我们用fonttools来看一下font文件里面的映射关系。
font = TTFont("./UJdXseZx.woff")
print(font.getBestCmap()){100285: 'period', 100287: 'eight', 100288: 'three', 100289: 'five', 100290: 'seven', 100291: 'zero', 100292: 'nine', 100293: 'one', 100294: 'four', 100295: 'six', 100296: 'two'}
- 打印出来了一堆数字,和源码里的数字有些一样,我们比对下,可以发现是匹配的。
- 所以接下来就是将font文件里面的映射进行修改,将每个键拼接成
&#xxxxxx;
的样子,值就是对应的数字字符。 - 最后根据对应关系将html里面的加密数字进行解密就可以爬取需要的信息了。
完整代码
"""
字体加密,起点中文网
F12发现每个作品的字数处都是方框,而查看源码又是加密
发现多次出现一个span,里面有个url:'https://qidian.gtimg.com/qd_anti_spider/zLIyWHRL.ttf'
https://qidian.gtimg.com/qd_anti_spider/wsKKYIJi.woff
与字数的span的class相同,下载下来,放到百度字体编辑器里面查看对应关系
发现对应关系就是数字的单词
"""import reimport pymongo
import redis
import requests
from fake_useragent import UserAgent
from fontTools.ttLib import TTFont, BytesIO
from lxml import etree
from retrying import retryclass QiDianZhongWenWang(object):def __init__(self):"""通过百度字体编辑器查找对应关系,初始化连接mongodb以及redis"""self.woff_map = {"one": "1","two": "2","three": "3","four": "4","five": "5","six": "6","seven": "7","eight": "8","nine": "9","zero": "10","period": ".",}self.client = pymongo.MongoClient()self.db = self.client['起点中文网']self.mongo_conn = self.db['novel']self.redis_conn = redis.StrictRedis(host="localhost", port=6379, db=1)def add_novel(self, novel_s):"""将循环好十次的self.novel_s存入mongo并清空:return:"""self.mongo_conn.insert_many(novel_s)def get_proxy(self):"""弹出一个代理并拼接成一个字典进行返回:return:"""proxy = str(self.redis_conn.spop("http_proxy", 1))return {"http": "http://" + proxy,}@retry(stop_max_attempt_number=3)def get_woff(self, res_text):"""接受Response.text,查找当前页面的字体文件路径,下载解析获得映射,并进行字典的键值对更换,返回的是源代码数字的对应关系字典:return:"""html = etree.HTML(res_text)style = html.xpath("//span/style[1]/text()")[0]woff_url = re.findall("format\('eot'\); src: url\('(.*?)'\) format\('woff'\)", style)[0]headers = {"User-Agent": UserAgent().random,}woff = requests.get(url=woff_url, headers=headers, proxies=self.get_proxy()) # 下载ttf字体文件font = TTFont(BytesIO(woff.content)) # 然后通过BytesIO转化为内存文件,使用TTFont处理cmap = font.getBestCmap() # 获取映射# 把每一个映射对应的英文单词替换成数字字符for k in cmap.keys():cmap[k] = self.woff_map[cmap[k]]# 将cmap的键进行替换for k in cmap.keys():value = cmap.pop(k)cmap["&#" + str(k) + ";"] = valuereturn cmapdef parse_page(self, html):"""将获得的response.text传给get_woff获取字体映射,再对html进行字体替换:param html::return:"""cmap = self.get_woff(html)for k, v in cmap.items():if k in html:html = html.replace(k, v)return etree.HTML(html)@retry(stop_max_attempt_number=3)def get_page(self, url):"""获取url爬取页面,将返回的response.text传给parse_page进行解密,获得解密后的html再进行xpath获取信息:param url::return:"""headers = {"User-Agent": UserAgent().random,}res = requests.get(url=url, headers=headers, proxies=self.get_proxy())parsed_html = self.parse_page(res.text) # 这里返回的是已经进行过解密的htmlitem_s = parsed_html.xpath("//div[@class='all-book-list']//li") # 这边获取的是20个itemnovel_s = []for item in item_s:novel = {}novel['title'] = item.xpath(".//h4/a/text()")[0]novel['img'] = "http:" + item.xpath(".//a/img/@src")[0]novel['href'] = "https:" + item.xpath("./div/a/@href")[0]novel['author'] = item.xpath(".//p[@class='author']/a[1]/text()")[0]novel['count'] = item.xpath(".//p[@class='update']/span/span/text()")[0]novel['type'] = item.xpath(".//p[@class='author']/a[2]/text()")[0]novel['status'] = item.xpath(".//p[@class='author']/span/text()")[0]novel_s.append(novel)self.add_novel(novel_s)def main():"""起点中文网列表页只能爬5页:return:"""for i in range(1, 6):q = QiDianZhongWenWang()url = f"https://www.qidian.com/all?orderId=&style=1&pageSize=20&siteid=1&pubflag=0&hiddenField=0&page={i}"q.get_page(url)if __name__ == '__main__':main()
总结
- 起点中文网使用的是字体加密,只要找到字体文件然后进行解析就可以,算是很简单的加密方式。
- 完整代码里面用到了代理IP池,在爬虫学习日记1_自建代理IP池里我有记录如何创建自己的免费代理IP池。
- 列表页只能爬取5页,没有想到办法去爬取更多,如果有朋友愿意分享一下方法,感激不尽。
- 本次使用到的知识点:
– requests
– redis
– mongodb
– fontTools
– lxml - 写的不好还请各位海涵,欢迎各位在底下留言或私信,谢谢。
爬虫2_起点中文网字体反爬相关推荐
- 爬取起点中文网字体反爬取
参考文章:https://www.jianshu.com/p/fbc99cf4d557 个人比较喜欢看小说,于是乎想爬取小说网站--起点中文网,在爬取定位过程中遇到了反爬取,咨询了我旁边的前端大神,说 ...
- 起点中文网 字体反爬技术 网页可以显示数字字母 网页代码是乱码或空格
我接过一段代码 # -*- coding: utf-8 -*- """ Created on Tue Mar 23 14:38:01 2021@author: xinyi ...
- pythonttf字体反爬虫_Python爬虫---汽车之家字体反爬
本篇文章给大家带来的内容是关于Python爬虫---汽车之家字体反爬,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 目标网站:汽车之家 目标网址:https://club.autoh ...
- 爬虫之遇到woff字体反爬
本篇博文的主题就是处理字体反爬,其实这种网上已经很多了,只是这次有点不一样,处理方式变化了点,记录一下. 以python3.7为基础 直接干货: 网站是json数据返回的: 这个网站有个好玩的地方,直 ...
- web爬虫——某电影网站字体反爬
某电影网站字体反爬 爱好学习及分享,若文章侵权,优先联系本人删帖处理. 几个关键点 base字体文件分析 打开目标网页,找到woff文件链接 下载该woff文件,并在字体编辑器里打开 记录下数字与字符 ...
- Python爬虫进阶之起点中文网字体反扒保姆级教程!!!
文章目录 1.网页查看 2.网页爬取代码 3.字体反扒研究 4.完整代码 本次字体反扒实验的网站是起点中文网 GlidedSky字体反扒详解 建议先看完本章 1.网页查看
- 爬虫实战——起点中文网小说的爬取
首先打开起点中文网,网址为:https://www.qidian.com/ 本次实战目标是爬取一本名叫<大千界域>的小说,本次实战仅供交流学习,支持作者,请上起点中文网订阅观看. 我们首先 ...
- pythonttf字体反爬虫_利用Python采集起点中文网小说,并解决字体反爬的问题
个人比较喜欢看小说,于是乎想利用Python爬取小说网站--起点中文网,在Python编程爬取定位过程中遇到了Python反爬虫,咨询了我旁边的前端大神,说下方法 当前页面接口返回的html源码 当前 ...
- 爬get接口_网络字体反爬之起点中文小说
前几天跟同事聊到最近在看什么小说,想起之前看过一篇文章说的是网络十大水文,就想把起点上的小说信息爬一下,搞点可视化数据看看.这段时间正在看爬虫框架-pyspider,觉得这种网站用框架还是很方便的,所 ...
最新文章
- flex java socket通信
- linux yum 安装mysql_Linux下使用yum安装MySQL
- 010_mod_fastdfs.conf配置详情
- sql数据库简单增删改查
- 手把手教你使用FineUI开发一个b/s结构的取送货管理信息系统(附源码+视频教程(第6节))...
- 电脑显示屏亮度怎么调_金合光电丨深圳led显示屏厂家为您诠释行业专业术语
- java类初始化_Java的类/实例初始化过程
- 【小程序项目分享】多功能抽签分组系统
- ExtJs6第二弹-- 学会查看ExtJs api文档
- mac 修改hosts不生效问题
- Screw 整合Oracle 报错异常信息oracle.jdbc.driver.T4CConnection.isValid(I)Z
- 智商情商哪个重要_智商和情商哪个更重要 一辩辩词
- 1016: 委派任务*
- 2022 lineCTF WEB复现WriteUp
- win10家庭版用户实现远程桌面解决办法
- _parameter;@param,refid是什么意思?
- WAP手机安全上网防病毒攻略
- 注册表计算机性能设置怎么应用,教你几招怎么玩注册表
- 使用vue完成点击鼠标产生小心心特效
- OpenGL可视化入门:体绘制(VRT)
热门文章
- 深入理解Linux启动过程 0号进程,1号进程
- 百度识图上线,体验以图搜图
- Python快速复制粘贴ins数据,采集网站内视频内容
- jquery 遍历java对象,js/jquery遍历对象和数组的方法分析【forEach,map与each方法】...
- 基于MATLAB的线性规划:linprog用法
- 广告公司到底干什么的?欣奥诚分享
- 合成 群组聊天头像,C# 版本 和 js 版本
- 画动漫人物眼睛怎么上色
- 班得瑞 Bandari 《班得瑞13张专辑全收藏》【APE+CUE/百度网盘地址】
- 使用Excel VBA制作成绩统计图----(嵌入模式)