(入门三)Python爬动态页面之爬小说_skyhyko的博客-程序员宅基地

技术标签: 爬虫  python  Python学习  

前言

动态页面相对于静态页面的解析来说,更加简单直接,因为动态页面返回的ajax数据基本都是json格式或者经过去头或者去尾变成json,根本不需要依赖BeautifulSoup,如下为需要处理的json:

jQuery110208565583287844201_1578312396626({
    "tag": "全部","ptagOneCount": "10","xxx":"yyy" })     

只要找到请求的规律,后续就会水到渠成

分析请求

本次依然以上篇文章中提到的网站为例,该网站可以点击"全文阅读"实现滚动鼠标阅读,很明显是动态加在的,不废话,打开小说页面,点击全文阅读
在这里插入图片描述
按下F12,点击Network,过滤设置为XHR,鼠标往下滚动,拦截到:
在这里插入图片描述
点击Response,可以看到返回的是标准json数据:
在这里插入图片描述
在这里插入图片描述
可以看到,返回的json数据中,章节名为response['data']['chapterName'],文章内容为response['data']['content'],但是文章内容中带有p标签,简单,用re正则去掉!

re.findall('<p>(.*?)</p>', response['data']['content'], re.S)

文章内容解析成功了,如何请求下一章的内容呢?
我们翻回来看一下拦截的Headers,往下翻,可以看到ajax请求的参数:
在这里插入图片描述
再结合网页的网址http://xxx.com/chapter/898410/58676024.html
你会发现bookId就在网址上:url.split('/')[-2],那chapterId呢?此时再连续翻两章,拦截两个包来对比一下,有心的你就会发现,上一章拦截的response['data']['nexCid']下一章Headers请求参数里面的 chapterId,好,下一章的chapterId也知道了,那_:1578574655825这个是个啥呢?对,经验告诉我们这个参数很可能是时间戳,格式化一下看看!
在这里插入图片描述
嗯,的确是时间戳了!
那如何判断最后一章呢,从倒数第二章开始全文阅读,拉到最后,拦截请求,可以看到,最后的**response['data']['nexCid']值为0,就把它作为循环结束的条件。

实现

至此,逻辑非常清楚了:
章节名:response['data']['chapterName']
文章内容:response['data']['nexCid']
下一章请求头的chapterId:response['data']['nexCid']
剩下的就是实现了:

import requests
import os
import re
import time
import json

def spiderBookdynamic(url: str):    
    nexCid = url.split('/')[-1].replace('.html', '')
    bookid = url.split('/')[-2]
    path = 'E:/Ebooks2/' + bookid
    if not os.path.exists(path):
        os.makedirs(path)
    pathAllinOne: str = path + '/' + bookid + '(合并).txt'
    while True:
    	# 13位时间戳
        timestamp = int(round(time.time() * 1000))
        # 构造ajax头
        url = 'http://book.zongheng.com/api/chapter/chapterinfo'
        params = {
    
            'bookId': bookid,
            'chapterId': nexCid,
            '_': timestamp
        }
        res = requests.get(url, params=params)
        res.encoding = 'utf-8'
        response = json.loads(res.text)
        chaptername = '\n' + response['data']['chapterName']+ '\n\n\n'
        content = chaptername + '\n'.join(re.findall('<p>(.*?)</p>', response['data']['content'], re.S))
        nexCid = response['data']['nexCid']

        # 写入章节
        with open(path + '/' + chaptername.strip() + '.txt', 'w') as f:
            f.write(content)
            print("已保存章节:" + chaptername.strip())
        # 写入合并
        with open(pathAllinOne, 'a') as f:
            f.write(content)
		# 最后一章
        if nexCid == 0:
            return

if __name__ == '__main__':
    url = 'http://xxx.com/chapter/898410/58676024.html'
    spiderBookdynamic(url)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013603198/article/details/103916249

智能推荐

centos7.0卸载vscode_ygqq的博客-程序员宅基地_centos vscode 卸载

卸载命令:sudo yum remove code联网状态下安装命令1, sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc2 ,sudo sh -c 'echo -e &quot;[code]\nname=Visual Studio Code\nbaseurl=https://packages.mic...

怎么获取已连接的共享文件夹的用户名和密码?_fegor的博客-程序员宅基地_查看共享用户名和密码

有的时候在公司,我们连接上了一个共享文件夹,一般是IT帮忙设置的,我们并不知道用户名和密码,但是一旦断开想要重新连接,找IT总是麻烦。下面一个工具就可以很好的解决这个问题。下载:注意,微软默认的杀毒软件会阻止打开次文件,临时关闭即可。Recover lost Windows 10/7/8/Vista/XP network passwords (Credentials file)...

在字符串中的数字前面加字符_小贵枝呀的博客-程序员宅基地_在字符串中的数字前面加字符

问题描述:请编写程序,实现以下功能:在字符串中的所有数字字符前加一个$字符。例如,输入 A1B23CD45,输出 A$1B$2$3CD$4$5。一个哥们的解法是:用串S拷贝出另一个串T,对串T从头至尾扫描,对非数字字符原样写入串S,对于数字字符先写一个$符号再写该数字字符,最后,在S串尾加结束标志。使用此方法是牺牲空间,赢得时间。代码如下:#include &amp;lt;stdio.h&amp;g...

Hana数据库,Java连接池_长睡将军的博客-程序员宅基地_hana数据库

Hana 或者其他数据库原生的数据库连接池实现。

vue文件目录详解_曲调响起琴声悠扬的博客-程序员宅基地_vue文件

.husky:husky是一个为git客户端增加hook的工具.vscodebiuld:vite的配置,项目打包时候的配置mock:mock数据node_modules:node的一些基础依赖包,可能还有拓展的安装的别的插件publicsrc:项目的主文件夹 assets:资源文件 components:vue组件 componens 下的**.vue文件就可以具体编写每一个vue, 最后通过router-link 连接给定的path路径,可以调用vue对象 ...

随便推点

明基JoybookP41-C11_普通网友的博客-程序员宅基地

&amp;lt;iframe name=&quot;google_ads_frame&quot; marginwidth=&quot;0&quot; marginheight=&quot;0&quot; src=&quot;http://pagead2.googlesyndication.com/pagead/ads?client=ca-pub-5572165936844014&amp;amp;amp;dt=1204028028375&amp;amp;amp;lmt=1203788092&amp;...

一个开源的实时通信跨平台框架:Socket.IO_weixin_30339969的博客-程序员宅基地

  近期项目涉及到IM功能,使用到一个好用的支持WebSocket的IM开源框架:Socket.IO;它是一个完全由JavaScript实现、基于Node.js、支持WebSocket的协议用于实时通信、跨平台的开源框架,它包括了客户端的JavaScript和服务器端的Node.js。Socket.IO除了支持WebSocket通讯协议外,还支持许多种轮询(Polling)机制以及其它实时通信方...

Java 输出整数的二进制_yfstdio的博客-程序员宅基地_java二进制输出

package org.pcl;import java.util.Scanner;/** * 用户输入一个整数,程序输出该数的二进制 * * @version 1.0 2014-05-05 * @author yifan */public class OutBinary { public static void main(String[] args) { Scann

一位用贞操换取欲望的仙女_Boss_Commander的博客-程序员宅基地

原文地址:一位用贞操换取欲望的仙女作者:游文意   为了唐僧这块肉,白骨精攻了三次。第一次,好妖精,停下阴风,在那山凹里,摇身一变,变做个月貌花容的女儿,说不尽那眉清目秀,齿白唇红,左手提着一个青砂罐儿,右手提着一个绿磁瓶儿,从西向东,径奔唐僧。    只见那行者自南山顶上,摘了几个桃子,托着钵盂,一筋斗,点将回来。睁火眼金睛观看,认得那女子是个妖精,放下钵盂,掣铁棒,望妖精劈脸一下。那

tensorflow生成deeplab v3+的tfrecord的时候报错:Failed to find all Cityscapes modules_古月光军001的博客-程序员宅基地

在网上照着大神的博客用CityScapes的数据集训练deeplab V3+的时候,一步一步照着别人的方法弄,弄到生成tfrecord的时候突然报错:Failed to find all Cityscapes modules。这个错误是从csHelpers.py里面报出来的就是因为from annotation import Annotation这个语句出错,才报的Failed to fi...

rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1179) [_csding11的博客-程序员宅基地

想把hadoop102机器上的环境变量分发给hadoop103和hadoop104,xsync /etc/profile.d/my_env.sh,这里的xsync是自己的分发脚本#!/bin/bash#1. 判断参数个数if [ $# -lt 1 ]then echo Not Enough Arguement! exit;fi#2. 遍历集群所有机器for host in hadoop102 hadoop103 hadoop104do echo =========== $host

推荐文章

热门文章

相关标签