首先打开起点中文网,网址为:https://www.qidian.com/

  本次实战目标是爬取一本名叫《大千界域》的小说,本次实战仅供交流学习,支持作者,请上起点中文网订阅观看。

  我们首先找到该小说的章节信息页面,网址为:https://book.qidian.com/info/3144877#Catalog

  

  点击检查,获取页面的html信息,我发现每一章都对应一个url链接,故我们只要得到本页面html信息,然后通过Beautifulsoup,re等工具,就可将所有章节的url全部得到存成一个url列表然后挨个访问便可获取到所有章节内容,本次爬虫也就大功告成了!

  按照我的想法,我用如下代码获取了页面html,并在后端输出显示,结果发现返回的html信息不全,包含章节链接的body标签没有被爬取到,就算补全了headers信息,还是无法获取到body标签里的内容,看来起点对反爬做的措施不错嘛,这条道走不通,咱们换一条。

import requestsdef get():url = 'https://book.qidian.com/info/3144877#Catalog'req = requests.get(url)print(req.text)if __name__ == '__main__':get()

既然这个页面是动态加载的,故可能应用ajax与后端数据库进行了数据交互,然后渲染到了页面上,我们只需拦截这次交互请求,获取到交互的数据即可。

打开网页https://book.qidian.com/info/3144877#Catalog,再次右键点击检查即审查元素,因为是要找到数据交互,故点击network里的XHR请求,精确捕获XHR对象,我们发现一个url为https://book.qidian.com/ajax/book/category?_csrfToken=1iiVodIPe2qL9Z53jFDIcXlmVghqnB6jSwPP5XKF&bookId=3144877的请求返回的response是一个包含所有卷id和章节id的json对象,这就是我们要寻找的交互数据。

通过如下代码,便可获取到该json对象

import requests
import randomdef random_user_agent():list = ['Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36','Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/44.0.2403.155 Safari/537.36','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36','Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36','Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36','Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36']seed = random.randint(0, len(list)-1)return list[seed]def getJson():url = 'https://book.qidian.com/ajax/book/category?_csrfToken=BXnzDKmnJamNAgLu4O3GknYVL2YuNX5EE86tTBAm&bookId=3144877'headers = {'User-Agent': random_user_agent(),'Referer': 'https://book.qidian.com/info/3144877','Cookie': '_csrfToken=BXnzDKmnJamNAgLu4O3GknYVL2YuNX5EE86tTBAm; newstatisticUUID=1564467217_1193332262; qdrs=0%7C3%7C0%7C0%7C1; showSectionCommentGuide=1; qdgd=1; lrbc=1013637116%7C436231358%7C0%2C1003541158%7C309402995%7C0; rcr=1013637116%2C1003541158; bc=1003541158%2C1013637116; e1=%7B%22pid%22%3A%22qd_P_limitfree%22%2C%22eid%22%3A%22qd_E01%22%2C%22l1%22%3A4%7D; e2=%7B%22pid%22%3A%22qd_P_free%22%2C%22eid%22%3A%22qd_A18%22%2C%22l1%22%3A3%7D'}res = requests.get(url=url, params=headers)json_str = res.textprint(json_str)if __name__ == '__main__':getJson()

  

  在小说的章节信息页面里我发现有分卷阅读,点击进入后发现该页面包含该卷的所有章节内容,且每一个分卷阅读的前半段url都是https://read.qidian.com/hankread/3144877/,变得只是该卷的id号,例如第一卷初来乍到的id为8478272,故阅读整个第一卷内容的链接为https://read.qidian.com/hankread/3144877/8478272。故我们只需要在上述json对象里截取所有卷id,便可以爬取整本了!

  爬取效果如下:

  完整代码如下:

import requests
import re
from bs4 import BeautifulSoup
from requests.exceptions import *
import random
import json
import time
import os
import sysdef random_user_agent():list = ['Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36','Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML like Gecko) Chrome/44.0.2403.155 Safari/537.36','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36','Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36','Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36','Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36']seed = random.randint(0, len(list)-1)return list[seed]def getJson():url = 'https://book.qidian.com/ajax/book/category?_csrfToken=BXnzDKmnJamNAgLu4O3GknYVL2YuNX5EE86tTBAm&bookId=3144877'headers = {'User-Agent': random_user_agent(),'Referer': 'https://book.qidian.com/info/3144877','Cookie': '_csrfToken=BXnzDKmnJamNAgLu4O3GknYVL2YuNX5EE86tTBAm; newstatisticUUID=1564467217_1193332262; qdrs=0%7C3%7C0%7C0%7C1; showSectionCommentGuide=1; qdgd=1; lrbc=1013637116%7C436231358%7C0%2C1003541158%7C309402995%7C0; rcr=1013637116%2C1003541158; bc=1003541158%2C1013637116; e1=%7B%22pid%22%3A%22qd_P_limitfree%22%2C%22eid%22%3A%22qd_E01%22%2C%22l1%22%3A4%7D; e2=%7B%22pid%22%3A%22qd_P_free%22%2C%22eid%22%3A%22qd_A18%22%2C%22l1%22%3A3%7D'}try:res = requests.get(url=url, params=headers)if res.status_code == 200:json_str = res.textlist = json.loads(json_str)['data']['vs']response = {'VolumeId_List': [],'VolumeNum_List': []}for i in range(len(list)):json_str = json.dumps(list[i]).replace(" ", "")volume_id = re.search('.*?"vId":(.*?),', json_str, re.S).group(1)volume_num = re.search('.*?"cCnt":(.*?),', json_str, re.S).group(1)response['VolumeId_List'].append(volume_id)response['VolumeNum_List'].append(volume_num)return responseelse:print('No response')return Noneexcept ReadTimeout:print("ReadTimeout!")return Noneexcept RequestException:print("请求页面出错!")return Nonedef getPage(VolId_List, VolNum_List):'''通过卷章Id找到要爬取的页面,并返回页面html信息:param VolId_List: 卷章Id列表:param VolNum_List: 每一卷含有的章节数量列表:return:'''size = len(VolId_List)for i in range(size):path = 'C://Users//49881//Projects//PycharmProjects//Spider2起点中文网//大千界域//卷' + str(i + 1)mkdir(path)url = 'https://read.qidian.com/hankread/3144877/'+VolId_List[i]print('\n当前访问路径:'+url)headers = {'User-Agent': random_user_agent(),'Referer': 'https://book.qidian.com/info/3144877','Cookie': 'e1=%7B%22pid%22%3A%22qd_P_hankRead%22%2C%22eid%22%3A%22%22%2C%22l1%22%3A3%7D; e2=%7B%22pid%22%3A%22qd_P_hankRead%22%2C%22eid%22%3A%22%22%2C%22l1%22%3A2%7D; _csrfToken=BXnzDKmnJamNAgLu4O3GknYVL2YuNX5EE86tTBAm; newstatisticUUID=1564467217_1193332262; qdrs=0%7C3%7C0%7C0%7C1; showSectionCommentGuide=1; qdgd=1; e1=%7B%22pid%22%3A%22qd_P_limitfree%22%2C%22eid%22%3A%22qd_E01%22%2C%22l1%22%3A4%7D; e2=%7B%22pid%22%3A%22qd_P_free%22%2C%22eid%22%3A%22qd_A18%22%2C%22l1%22%3A3%7D; rcr=3144877%2C1013637116%2C1003541158; lrbc=3144877%7C52472447%7C0%2C1013637116%7C436231358%7C0%2C1003541158%7C309402995%7C0; bc=3144877'}try:res = requests.get(url=url, params=headers)if res.status_code == 200:print('第'+str(i+1)+'卷已开始爬取:')parsePage(res.text, url, path, int(VolNum_List[i]))else:print('No response')return Noneexcept ReadTimeout:print("ReadTimeout!")return Noneexcept RequestException:print("请求页面出错!")return Nonetime.sleep(3)def parsePage(html, url, path, chapNum):'''解析小说内容页面,将每章内容写入txt文件,并存储到相应的卷目录下:param html: 小说内容页面:param url: 访问路径:param path: 卷目录路径:return: None'''if html == None:print('访问路径为'+url+'的页面为空')returnsoup = BeautifulSoup(html, 'lxml')ChapInfoList = soup.find_all('div', attrs={'class': 'main-text-wrap'})alreadySpiderNum = 0.0for i in range(len(ChapInfoList)):sys.stdout.write('\r已爬取{0}'.format('%.2f%%' % float(alreadySpiderNum/chapNum*100)))sys.stdout.flush()time.sleep(0.5)soup1 = BeautifulSoup(str(ChapInfoList[i]), 'lxml')ChapName = soup1.find('h3', attrs={'class': 'j_chapterName'}).span.stringChapName = re.sub('[\/:*?"<>|]', '', ChapName)if ChapName == '无题':ChapName = '第'+str(i+1)+'章 无题'filename = path+'//'+ChapName+'.txt'readContent = soup1.find('div', attrs={'class': 'read-content j_readContent'}).find_all('p')for item in readContent:paragraph = re.search('.*?<p>(.*?)</p>', str(item), re.S).group(1)save2file(filename, paragraph)alreadySpiderNum += 1.0sys.stdout.write('\r已爬取{0}'.format('%.2f%%' % float(alreadySpiderNum / chapNum * 100)))def save2file(filename, content):with open(r''+filename, 'a', encoding='utf-8') as f:f.write(content+'\n')f.close()def mkdir(path):'''创建卷目录文件夹:param path: 创建路径:return: None'''folder = os.path.exists(path)if not folder:os.makedirs(path)else:print('路径'+path+'已存在')def main():response = getJson()if response != None:VolId_List = response['VolumeId_List']VolNum_List = response['VolumeNum_List']getPage(VolId_List, VolNum_List)else:print('无法爬取该小说!')print("小说爬取完毕!")if __name__ == '__main__':main()

  

转载于:https://www.cnblogs.com/lovewhale1997/p/11319688.html

爬虫实战——起点中文网小说的爬取相关推荐

  1. 爬虫实战入门级教学(数据爬取->数据分析->数据存储)

    爬虫实战入门级教学(数据爬取->数据分析->数据存储) 天天刷题好累哦,来一期简单舒适的爬虫学习,小试牛刀(仅供学习交流,不足之处还请指正) 文章讲的比较细比较啰嗦,适合未接触过爬虫的新手 ...

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

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

  3. 爬虫实战2(上):爬取豆瓣影评

       这次我们将主要尝试利用python+requsets模拟登录豆瓣爬取复仇者联盟4影评,首先让我们了解一些模拟登录相关知识补充.本文结构如下: request模块介绍与安装 get与post方式介 ...

  4. 爬虫实战2(下):爬取豆瓣影评

       上篇笔记我详细讲诉了如何模拟登陆豆瓣,这次我们将记录模拟登陆+爬取影评(复仇者联盟4)实战.本文行文结构如下: 模拟登陆豆瓣展示 分析网址和源码爬取数据 进行面对对象重构 总结   一.模拟登陆 ...

  5. 多线程爬虫实战--彼岸图网壁纸爬取

    多线程爬虫实战–彼岸图网壁纸爬取 普通方法爬取 import requests from lxml import etree import os from urllib import requesth ...

  6. python3爬虫实战:requests库+正则表达式爬取头像

    python3爬虫实战:requests库+正则表达式爬取头像 网站url:https://www.woyaogexing.com/touxiang/qinglv/new/ 浏览网页:可以发现每个图片 ...

  7. 链家网页爬虫_爬虫实战1-----链家二手房信息爬取

    经过一段机器学习之后,发现实在是太枯燥了,为了增添一些趣味性以及熟练爬虫,在之后会不定时的爬取一些网站 旨在熟悉网页结构--尤其是HTML的元素,ajax存储,json:熟练使用pyspider,sc ...

  8. python游戏辅助lol_Python爬虫实战,60行代码爬取英雄联盟全英雄全皮肤,找寻曾今那些被删除的绝版皮肤...

    学了一周多的爬虫课后终于按捺不住了,小编决定自己手动编写爬虫程序,刚好LJ在鼓励学员分享成果,优秀作品有奖励,就把自己用Python编程爬取各大游戏高清壁纸的过程整理了出来进行投稿,与大家一起分享. ...

  9. 爬虫2_起点中文网字体反爬

    今天讲一下起点中文网的列表页爬取,准备爬取的是小说书名.图片url.详情页url.作者.字数.分类及状态. 爬取网址:https://www.qidian.com/all 分析url 翻页至第二页.第 ...

最新文章

  1. 设计模式:迭代器模式(Iterator Pattern)
  2. delphi 运行外部程序函数winexec WinExecAndWait32 CreateProcess
  3. 相亲对象能有多油腻......
  4. b tree和b+tree_B TREE实施
  5. python+OpenCV图像处理(十二)车牌定位中对图像的形态学组合操作处理
  6. antd新增一行页码不正确_antd-Table@4.x对rowKey属性的重构
  7. 如何给对方邮箱发照片_朋友圈如何发心形拼图九宫格照片?
  8. theano学习指南5(翻译)- 降噪自动编码器
  9. Easy make - emake
  10. C++ 鼠标乱动整人代码
  11. Linux 内存管理:DAX(Direct Access)机制的作用及实现原理
  12. tar打包文件如何排除文件夹
  13. 8uftp,如何实现8uftp使用
  14. 日文發音中的PTK法則
  15. 海外手机号码正则匹配
  16. 网易传媒Go语言探索
  17. 如何修改vue的网页图标
  18. 码农和CTO的差距到底在哪?
  19. 色调、色相、饱和度、对比度、亮度
  20. 智能电视的未来在哪儿

热门文章

  1. 达梦数据库-插入单引号‘和双引号‘‘
  2. 智能芯片之三维内存 概念
  3. wps一直显示正在备份怎么办_wps怎么设置和取消自动备份功能
  4. 本地搭建Agriculture_KnowledgeGraph农业知识图谱环境时遇到的问题及解决办法
  5. 视频教程-系统集成项目管理工程师5天修炼-软考
  6. torch.load received a zip file
  7. php riak,PHP-Riak:快速获取多个项目
  8. 可禁用计算机服务,Windows 10系统下哪些服务可以关闭?
  9. 举个栗子!Tableau技巧(38):快速插入个性化背景
  10. 基于CKEditor网页富文本编辑工具转PDF文件的技术预研分析报告