今天讲一下起点中文网的列表页爬取,准备爬取的是小说书名、图片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_起点中文网字体反爬相关推荐

  1. 爬取起点中文网字体反爬取

    参考文章:https://www.jianshu.com/p/fbc99cf4d557 个人比较喜欢看小说,于是乎想爬取小说网站--起点中文网,在爬取定位过程中遇到了反爬取,咨询了我旁边的前端大神,说 ...

  2. 起点中文网 字体反爬技术 网页可以显示数字字母 网页代码是乱码或空格

    我接过一段代码 # -*- coding: utf-8 -*- """ Created on Tue Mar 23 14:38:01 2021@author: xinyi ...

  3. pythonttf字体反爬虫_Python爬虫---汽车之家字体反爬

    本篇文章给大家带来的内容是关于Python爬虫---汽车之家字体反爬,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 目标网站:汽车之家 目标网址:https://club.autoh ...

  4. 爬虫之遇到woff字体反爬

    本篇博文的主题就是处理字体反爬,其实这种网上已经很多了,只是这次有点不一样,处理方式变化了点,记录一下. 以python3.7为基础 直接干货: 网站是json数据返回的: 这个网站有个好玩的地方,直 ...

  5. web爬虫——某电影网站字体反爬

    某电影网站字体反爬 爱好学习及分享,若文章侵权,优先联系本人删帖处理. 几个关键点 base字体文件分析 打开目标网页,找到woff文件链接 下载该woff文件,并在字体编辑器里打开 记录下数字与字符 ...

  6. Python爬虫进阶之起点中文网字体反扒保姆级教程!!!

    文章目录 1.网页查看 2.网页爬取代码 3.字体反扒研究 4.完整代码 本次字体反扒实验的网站是起点中文网 GlidedSky字体反扒详解 建议先看完本章 1.网页查看

  7. 爬虫实战——起点中文网小说的爬取

    首先打开起点中文网,网址为:https://www.qidian.com/ 本次实战目标是爬取一本名叫<大千界域>的小说,本次实战仅供交流学习,支持作者,请上起点中文网订阅观看. 我们首先 ...

  8. pythonttf字体反爬虫_利用Python采集起点中文网小说,并解决字体反爬的问题

    个人比较喜欢看小说,于是乎想利用Python爬取小说网站--起点中文网,在Python编程爬取定位过程中遇到了Python反爬虫,咨询了我旁边的前端大神,说下方法 当前页面接口返回的html源码 当前 ...

  9. 爬get接口_网络字体反爬之起点中文小说

    前几天跟同事聊到最近在看什么小说,想起之前看过一篇文章说的是网络十大水文,就想把起点上的小说信息爬一下,搞点可视化数据看看.这段时间正在看爬虫框架-pyspider,觉得这种网站用框架还是很方便的,所 ...

最新文章

  1. flex java socket通信
  2. linux yum 安装mysql_Linux下使用yum安装MySQL
  3. 010_mod_fastdfs.conf配置详情
  4. sql数据库简单增删改查
  5. 手把手教你使用FineUI开发一个b/s结构的取送货管理信息系统(附源码+视频教程(第6节))...
  6. 电脑显示屏亮度怎么调_金合光电丨深圳led显示屏厂家为您诠释行业专业术语
  7. java类初始化_Java的类/实例初始化过程
  8. 【小程序项目分享】多功能抽签分组系统
  9. ExtJs6第二弹-- 学会查看ExtJs api文档
  10. mac 修改hosts不生效问题
  11. Screw 整合Oracle 报错异常信息oracle.jdbc.driver.T4CConnection.isValid(I)Z
  12. 智商情商哪个重要_智商和情商哪个更重要 一辩辩词
  13. 1016: 委派任务*
  14. 2022 lineCTF WEB复现WriteUp
  15. win10家庭版用户实现远程桌面解决办法
  16. _parameter;@param,refid是什么意思?
  17. WAP手机安全上网防病毒攻略
  18. 注册表计算机性能设置怎么应用,教你几招怎么玩注册表
  19. 使用vue完成点击鼠标产生小心心特效
  20. OpenGL可视化入门:体绘制(VRT)

热门文章

  1. 深入理解Linux启动过程 0号进程,1号进程
  2. 百度识图上线,体验以图搜图
  3. Python快速复制粘贴ins数据,采集网站内视频内容
  4. jquery 遍历java对象,js/jquery遍历对象和数组的方法分析【forEach,map与each方法】...
  5. 基于MATLAB的线性规划:linprog用法
  6. 广告公司到底干什么的?欣奥诚分享
  7. 合成 群组聊天头像,C# 版本 和 js 版本
  8. 画动漫人物眼睛怎么上色
  9. 班得瑞 Bandari 《班得瑞13张专辑全收藏》【APE+CUE/百度网盘地址】
  10. 使用Excel VBA制作成绩统计图----(嵌入模式)