记一次爬取xxx网站的经历

本文介绍了一种利用技术手段破解某收费漫画网站的方法,通过分析网站结构、利用未受保护的API接口、模拟新用户访问及签到获取积分,实现免费获取收费漫画资源的过程。

原文地址

http://118.25.172.253/2018/11/24/记一次爬取xxx网站的经历

背景

某天正在用手机上网的时候,不小心点到了一个广告,进到了一个漫画网站(咳咳咳...) 然后我不小心的浏览了几篇漫画,发现还是可以看一下的(手动滑稽^-^)。。

但是,重点来了,这个网站的漫画是收费的,如果想继续看漫画得充值。。

吝啬的我肯定不愿意啦,身为一个程序员,怎么能充钱呢?肯定得用一些技术手段破解啊,拿到我们想要的资源,于是乎,我成功了,为了庆祝一下,谨以此文记录。

网站分析

提示:由于这篇文章的特殊性,我不会将网站的截图放上来的。。

知己知彼,方而百战百胜

想要拿到网站的收费资源,我们得先仔细的了解这个网站。观察它的数据来源,认证方式,从而寻找它的漏洞。

网站地址:aHR0cCUzQS8vZnFhY2MuY29tLw==

上面的地址我加密了一下,这个格式。。怎么解密我就不说了哈。

我们进入上面的网站,进入分类,选漫画,这个页面里面是查询这个网站的所有漫画。打开浏览器控制台,我们可以看到如下接口

/api/cate/1-0-2-2-2 #根据点击量排序查询所有的漫画,最后一个数字是页码

我们将页码当做变量提取出来,对这个链接用java代码封装一下:

    /**
     * 漫画列表爬取---根据点击量
     */
    public static final String COMIC_SPILDER_URL_CLICK="/api/cate/1-0-2-2-%s";
复制代码

随便选一篇漫画进去,在控制台我们可以看到漫画章节的查询接口,接口如下:

/api/chapter_list/110008-1-1-6

同理,我们也对章节查询接口进行封装一下:

   /**
     * 章节爬取链接  第一个参数是漫画ID  第二个参数是页码 第三个参数是每页展示数量
     */
    public static final String CHAPTER_SPILDER_URL="/api/chapter_list/%s-1-%s-%S";
复制代码

上面的两个接口是没有做任何权限的判断的,所以我们可以肆无忌惮的调用

当然,上面的两个接口能拿到漫画和章节,但是章节的详情才是最重要的,我们怎么样才能拿到章节的详情呢?

我们先分析下网站的章节详情数据是怎么样加载的。。

随机点开一个免费章节,打开控制台,看ajax请求。然后吓了一跳,竟然没有ajax请求,章节详情数据不是通过接口形式返回。那么,我们看静态资源请求。然后,会发现这个请求

/read/11000008

分析这个请求,我们不难得知后面的那串数字为章节ID。

这个请求是返回了一个网页,我们点击这个请求,查看返回值如下:

看到这个,我们可以放心一下了。这个请求能将章节的详情页面全部数据返回。我们拿到网页,解析一下就可以拿到关键数据了。。

但是不要高兴的太早,我们打开收费的章节,返回值如下:

划重点:没有钱的用户看章节详情 是看不到什么的,只有钱足够,那么章节详情才会向你吐出数据

先确定好立场,我们充钱是不可能的。那么,我们的账户怎么才能拿到钱呢?我们点击收费的章节,往底部滑动,有一个完成任务获取大量阅币的按钮,我们点击进入

看到那个签到赚50阅币的按钮了吗?我们点击,在控制台看到如下接口:

/api/sign

仔细分析一波,这个接口是让用户每天签到然后送50阅币,每次签到之间必须相隔12小时以上。

看到了这,其实章节详情的解决方案已经出现了:

  • 模拟新用户访问,然后签到获取积分
  • 用这个用户调章节详情接口,获取页面数据

这样的话,我们的问题就变成了,怎么模拟新用户访问,然后签到获取积分了。

收费资源爬取

首先,我们仔细研究一下这个网站怎么存储用户信息的。

打开控制台,可以发现用户信息是存在cookie里面的。

知道用户信息是存储在cookie里,我们还得知道用户是不是自动创建的。

我们将这个网站的cookie全部删除,然后刷新当前页,我们可以发现 用户变了,浏览器里有多了一份cookie

我们在控制台里 查看页面请求,在返回值 头部里可以看到如下:

这个Set-Cookie是服务器向客户端声明存储cookie,以后再向服务器发起请求时,客户端就会自动将cookie放到请求头中。

知道了上面的流程,我们就可以模拟新用户访问,然后签到获取积分了。

步骤:

  1. 请求user/task接口,获取response的'Set-Cookie'的头部信息,解析获取JSESSIONID

这里我做了一些测试,发现这个网站前后端交互是通过session来的,所以这里我们只需获取JSESSIONID 即可。

2.上面获取的jessonId对应了一个新用户的访问,我们再通过请求/api/sign接口进行签到,获取50阅币。

3.进行签到完之后,这个JESSSIONID就有了一次访问收费资源的权限了。我们再访问收费的漫画章节,调用如下接口:/read/10007517

发现返回值吐出了所有的数据

这就是一个完整的破解收费章节的流程。

那我们怎么爬取网站的所有收费章节呢??

  1. 先爬取所有的漫画
  2. 根据漫画爬取到所有的章节

这两步用上面说到的接口直接调用就ok了

  1. 爬取所有的章节。如果章节需要收费,则先模拟新用户访问,然后签到,再拿资源。重复这个流程,就可以获取所有的收费漫画了。

最后

整个网站的爬取源码在这里:

github.com/kingrocy/co…

<think>我们正在讨论的是爬虫代码中的页码问题。根据用户提供的代码片段和引用,页码在爬虫中通常用于处理分页数据。在用户提供的示例代码中,我们看到: 原始用户代码中使用了`for j in range(1,18)`,这意味着他假设该网页有17页(从1到17)?但实际上,他的代码中并没有使用页码来构建不同的URL,而是直接使用了一个固定的URL。 然而,根据引用[2]和引用[3],当爬取分页数据时,我们通常需要构造每一页的URL,而页码就是用来标识每一页的。页码可以出现在URL中作为参数(例如`page=2`),也可以以其他形式出现。 在用户最初的代码中,他并没有在URL中使用页码,而是直接请求了一个固定的URL,然后用循环遍历了表格的行(tr)。他的循环是从1到17,这是因为他在页面上观察到有17行?但实际上,他并没有获取到数据。 现在,我们来回答用户的问题:爬取网页信息代码中涉及的页码是指只有一页页码还是一次爬取一页页码? 在爬虫中,如果网页是分页的,那么每一页都有一个对应的URL(或者通过POST请求携带页码参数)。我们通常是一次爬取一页,然后通过改变页码参数来爬取所有页。 在用户最初的代码中,他并没有使用页码来构建多个URL,而是用一个URL然后循环解析表格的行(他认为有17行)。但事实上,那个URL可能是分页的,也可能不是。而实际上,由于数据是动态加载的,他并没有获取到数据。 在后续的解决方案中,我们使用了新浪的真实数据接口,其中参数包含`page`和`num`(第几页和每页数量)。在那个方案中,我们一次只请求一页的数据,然后如果需要多页,我们可以改变`page`参数的值来获取多页。 因此,我们可以这样总结: 1. 当数据量很大时,网页通常采用分页展示。 2. 爬虫需要识别分页规则(如页码在URL中的体现),然后分别请求每一页。 3. 每一页的请求是独立的,所以一次爬取一页。 在用户最初的代码中,他试图在一个页面(第一页)中获取所有数据(因为他只请求了一次),然后循环解析行。但那个页面是动态加载的,所以没有成功。 在改进的代码中,我们请求了接口,并且可以通过修改`page`参数来获取多页数据(如果需要的话)。例如,如果我们知道总共有多少页,我们可以用一个循环从1到总页数,依次请求每一页。 注意:在改进的代码中,我们只请求了一页(page=1)。如果这个行业分类下有超过40条(因为num=40)数据,那么我们需要请求多页。我们可以先获取第一页,然后从返回数据中解析出总录数,然后计算出总页数。 所以,页码在爬虫中通常用于分页,一次爬取一页。 下面,我们根据改进的代码,展示如何爬取多页: ```python import requests import json import math url = "https://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData" # 设置请求头 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", "Referer": "https://vip.stock.finance.sina.com.cn/mkt/" } # 先请求第一页,获取总录数 params_page1 = { "page": 1, "num": 40, # 每页40条 "sort": "symbol", "asc": 1, "node": "hangye_ZC25", "_s_r_a": "init" } response = requests.get(url, params=params_page1, headers=headers) data_list = json.loads(response.text) # 第一页的数据我们已经拿到 # 接下来,我们需要知道总录数。但是接口返回的只是当前页的数据,并没有总录数。 # 所以我们需要改变策略:不断请求直到返回为空(或者返回的数据条数不足40条) # 另一种方法:观察页面上的总录数显示,但接口没有返回,所以只能逐页爬取直到没有数据 # 我们用一个循环,从第一页开始,直到某一页没有数据为止 page = 1 all_data = [] while True: params = { "page": page, "num": 40, "sort": "symbol", "asc": 1, "node": "hangye_ZC25", "_s_r_a": "init" } response = requests.get(url, params=params, headers=headers) data = json.loads(response.text) if not data: # 如果data为空列表,说明已经没有数据了 break all_data.extend(data) print(f"爬取第{page}页,共{len(data)}条数据") page += 1 # 然后我们输出所有数据 print(f"总共爬取了{len(all_data)}条数据") ``` 注意:上述代码没有处理异常情况,例如网络错误等。 因此,页码在爬虫中通常是一次爬取一页,直到所有页都被爬取完毕。 下面生成相关问题: </think>### 页码在爬虫中的含义与应用 在网页爬取代码中,**页码通常指分页系统中的页面编号**,爬虫需要**逐页爬取**数据而非仅处理单页。具体分析如下: #### 1. 单页爬取模式 当数据量较少时,可能只需爬取单页(如您原始代码中的固定URL): ```python url = 'https://vip.stock.finance.sina.com.cn/mkt/#hangye_ZC25' # 固定单页URL html = requests.get(url) # 仅获取单页数据 ``` - 适用场景:数据总量小于100条,无分页机制 - 缺点:无法获取完整数据集[^2] #### 2. 多页爬取模式(主要应用) 实际项目中99%需要处理分页,典型实现方式: ```python base_url = 'https://xxx.com/data?page={}' # 含页码占位符 for page in range(1, total_pages+1): # 遍历所有页码 current_url = base_url.format(page) # 动态生成每页URL response = requests.get(current_url) # 逐页获取 parse_data(response) # 解析每页数据 ``` - **页码作用**: - 定位分页数据(如 `?page=2`) - 控制爬取范围(`range(1, N)`) - 实现增量爬取录上次终止页码)[^5] #### 3. 页码识别技巧 当页面未明确显示总页数时: 1. 初始请求获取首页数据 2. 解析页面末端的页码导航元素 ```xpath //div[@class="pagination"]/a[last()-1]/text() # 获取末页页码 ``` 3. 若无显式页码,持续爬取直到返回空数据[^2] ### 分页爬虫最佳实践 ```python import requests base_url = "https://api.example.com/data?page={}&size=50" headers = {"User-Agent": "..."} # 引用[4] page = 1 all_data = [] while True: url = base_url.format(page) response = requests.get(url, headers=headers) # 终止条件检测 if not response.json()["items"]: # 数据为空 break # 数据处理 all_data.extend(parse_items(response)) print(f"已爬取第 {page} 页,累计 {len(all_data)} 条") page += 1 ``` ### 关键结论 1. **页码本质**:分页系统的定位标识符 2. **爬取方式**:必须逐页请求(单次仅处理一页) 3. **核心价值**: - 解决大数据集分块加载问题 - 避免触发反爬机制(请求速率控制) - 支持断点续爬[^5]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值