使用for或while循环来处理处理不确定页数的网页数据爬取
本文转载自以下网站: Python For 和 While 循环爬取不确定页数的网页 https://www.makcyun.top/web_scraping_withpython16.html
需要学习的地方
有两种方法。
第一种方式 使用 For 循环配合 break 语句,尾页的页数设置一个较大的参数,足够循环爬完所有页面,爬取完成时,break 跳出循环,结束爬取。
第二种方法 使用 While 循环,可以结合 break 语句,也可以设起始循环判断条件为 True,从头开始循环爬取直到爬完最后一页,然后更改判断条件为 False 跳出循环,结束爬取。
Requests 和 Scrapy 中分别用 For 循环和 While 循环爬取不确定页数的网页。
摘要:Requests 和 Scrapy 中分别用 For 循环和 While 循环爬取不确定页数的网页。
我们通常遇到的网站页数展现形式有这么几种:
第一种是直观地显示所有页数,比如此前爬过的酷安、东方财富网,
文章见:
∞ Scrapy 爬取并分析酷安 6000 款 App,找到良心佳软

第二种是不直观显示网页总页数,需要在后台才可以查看到,比如之前爬过的虎嗅网,文章见:

第三种是今天要说的,不知道具体有多少页的网页,比如豌豆荚:

对于,前两种形式的网页,爬取方法非常简单,使用 For 循环从首页爬到尾页就行了,第三种形式则不适用,因为不知道尾页的页数,所以循环到哪一页结束无法判断。
那如何解决呢?有两种方法。
第一种方式 使用 For 循环配合 break 语句,尾页的页数设置一个较大的参数,足够循环爬完所有页面,爬取完成时,break 跳出循环,结束爬取。
第二种方法 使用 While 循环,可以结合 break 语句,也可以设起始循环判断条件为 True,从头开始循环爬取直到爬完最后一页,然后更改判断条件为 False 跳出循环,结束爬取。
实际案例
下面,我们以 豌豆荚 网站中「视频」类别下的 App 信息为例,使用上面两种方法抓取该分类下的所有 App 信息,包括 App 名称、评论、安装数量和体积。
首先,简要分析下网站,可以看到页面是通过 Ajax 加载的,GET 请求附带一些参数,可以使用 params 参数构造 URL 请求,但不知道一共有多少页,为了确保下载完所有页,设置较大的页数,比如 100页 甚至 1000 页都行。
下面我们尝试使用 For 和 While 循环爬取 。

Requests
▌For 循环
主要代码如下:
| class Get_page(): | 
这里,首先创建了一个 Get_page 类,get_page 方法用于获取 Response 返回的 json 数据,通过 json.cn 网站解析 json 解析后发现需要提取的内容是一段包裹在 data 字段下 content 键中的 html 文本,可以使用 parse_page 方法中的 pyquery 函数进行解析,最后提取出 App 名称、评论、安装数量和体积四项信息,完成抓取。
在主函数中,使用了 if 函数进行条件判断,若 content 不为空,表示该页有内容,则循环爬下去,若为空则表示此页面已完成了爬取,执行 else 分支下的 break 语句结束循环,完成爬取。

爬取结果如下,可以看到该分类下一共完成了全部 41 页的信息抓取。

▌While 循环
While 循环和 For 循环思路大致相同,不过有两种写法,一种仍然是结合 break 语句,一种则是更改判断条件。
总体代码不变,只需修改 For 循环部分:
| page = 2 # 设置爬取起始页数 | 
或者:
| page = 2 # 设置爬取起始页数 | 
结果如下,可以看到和 For 循环的结果是一样的。

我们可以再测试一下其他类别下的网页,比如选择「K歌」类别,编码为:718,然后只需要对应修改主函数中的child_cate_code 即可,再次运行程序,可以看到该类别下一共爬取了 32 页。

由于 Scrapy 中的写法和 Requests 稍有不同,所以接下来,我们在 Scrapy 中再次实现两种循环的爬取方式 。
Scrapy
▌For 循环
Scrapy 中使用 For 循环递归爬取的思路非常简单,即先批量生成所有请求的 URL,包括最后无效的 URL,后续在 parse 方法中添加 if 判断过滤无效请求,然后爬取所有页面。由于 Scrapy 依赖于Twisted框架,采用的是异步请求处理方式,也就是说 Scrapy 边发送请求边解析内容,所以这会发送很多无用请求。
| def start_requests(self): | 
下面,我们选取豌豆荚「新闻阅读」分类下的「电子书」类 App 页面信息,使用 For 循环尝试爬取,主要代码如下:
| def start_requests(self): | 
上面代码很好理解,简要说明几点:
第一、判断当前页是否爬取完成的判断条件改为了 response.body 的长度大于 100。
因为请求已爬取完成的页面,返回的 Response 结果是不为空的,而是有长度的 json 内容(长度为 87),其中 content 键值内容才为空,所以这里判断条件选择比 87 大的数值即可,比如 100,即大于 100 的表示此页有内容,小于 100 表示此页已爬取完成。
| {"state":{"code":2000000,"msg":"Ok","tips":""},"data":{"currPage":-1,"content":""}} | 
第二、当需要从文本中解析内容时,不能直接解析,需要先转换。
通常情况下,我们在解析内容时是直接对返回的 response 进行解析,比如使用 response.css() 方法,但此处,我们的解析对象不是 response,而是 response 返回的 json 内容中的 html 文本,文本是不能直接使用 .css() 方法解析的,所以在对 html 进行解析之前,需要添加下面一行代码转换后才能解析。
| contents = scrapy.Selector(text=contents, type="html") | 
结果如下,可以看到发送了全部 48 个请求,实际上该分类只有 22 页内容,即多发送了无用的 26 个请求。

▌While 循环
接下来,我们使用 While 循环再次尝试抓取,代码省略了和 For 循环中相同的部分:
| def start_requests(self): | 
这里,简要说明几点:
第一、While 循环的思路是先从头开始爬取,使用 parse() 方法进行解析,然后递增页数构造下一页的 URL 请求,再循环解析,直到爬取完最后一页即可,这样 不会像 For 循环那样发送无用的请求。
第二、parse() 方法构造下一页请求时需要利用 start_requests() 方法中的参数,可以 使用 meta 方法来传递参数。
运行结果如下,可以看到请求数量刚好是 22 个,也就完成了所有页面的 App 信息爬取。

以上,就是本文的所有内容,小结一下:
- 在爬取不确定页数的网页时,可以采取 For 循环和 While 循环两种思路,方法大致相同。
- 在 Requests 和 Scrapy 中使用 For 循环和 While 循环的方法稍有不同,因此本文以豌豆荚网站为例,详细介绍了循环构造方法。
使用for或while循环来处理处理不确定页数的网页数据爬取的更多相关文章
- python3下scrapy爬虫(第八卷:循环爬取网页多页数据)
		之前我们做的数据爬取都是单页的现在我们来讲讲多页的 一般方式有两种目标URL循环抓取 另一种在主页连接上找规律,现在我用的案例网址就是 通过点击下一页的方式获取多页资源 话不多说全在代码里(因为刚才写 ... 
- HDU 3746 将字符串的全部字符最少循环2次需要添加的字符数
		Sample Input3aaaabcaabcde Sample Output025 题目大意:给你一个字符串,要求将字符串的全部字符最少循环2次需要添加的字符数.例子:abcabc 已经循环2次,添 ... 
- Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值
		Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值 说到循环遍历,最常见的遍历数组/列表.Map等.但是,在开发过程中,有时需要循环遍历一个对象的所有属性.遍历对象的属性该如何遍历呢?查了 ... 
- perl 循环类选择器 ,爬取内容
		jrhmpt01:/root/lwp/0526# cat 0526.txt <div class="TXD_sy_title"><span class=" ... 
- for循环将字典添加到列表中出现覆盖前面数据的问题
		出现问题: rets = [{'id':1},{"id":2},{"id":3}] context = {} context['count'] = len(re ... 
- 四、Oracle loop循环、while循环、for循环、if选择和case选择、更改读取数据、游标、触发器、存储过程
		数据库的设计(DataBase Design): 针对于用户特定的需求,然后我们创建出来一个最使用而且性能高的数据库! 数据库设计的步骤: 01.需求分析 02.概念结构设计 03.逻辑结构设计 04 ... 
- java的for循环问题的解决,以及安卓中ListView插入数据的问题
		package test.testdemo; import org.springframework.jdbc.core.JdbcTemplate; import com.util.Pub; publi ... 
- 如何使用一次for循环得到数组中第二大的数和第三大的数
		装载声明:http://blog.csdn.net/lxsmk9059/article/details/77920206?locationNum=1&fps=1 ,,,,,,,,}; ]; ] ... 
- (不用循环也可以记录数组里的数)Color the ball --hdu--1556
		题目: N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次 ... 
随机推荐
- URAL 1601. AntiCAPS  (strings)
			1601. AntiCAPS Time limit: 0.5 second Memory limit: 64 MB The blonde Angela has a new whim: internet ... 
- jQery总结01
			1 jQuery 的基本语法结构是什么? 2 $(document).ready() 与 window.onload 有什么区别? 3 如何实现 DOM 对象和 jQuery对象间的转化? 
- thymeleaf公共页面元素抽取
			1.抽取公共片段 使用thymeleaf的th:fragment为样抽取的公共片段命名, 如下把div标签命名为 copy,就可以获取到div整个里的内容<div th:fragment=&qu ... 
- 工具分享3:VMware 10虚拟机、MS-DOS 7.1、安装教程(MS-DOS环境安装)
			VMware 10工具下载地址: 网页下载链接:http://www.xp510.com/xiazai/ossoft/desktools/22610.html MS-DOS .10镜像下载地址: 网页 ... 
- Blender之Property
			目标 [x] 总结Blender插件之属性bpy.props 总结 bpy.props bpy.props模块用来扩展Blender内置数据的属性. 这些函数的结果用于为用Blender注册的类分配属 ... 
- XOJ测试 2016.5.22
			哈哈 我是最先使用XOJ的人之一 膜拜zrt ing 首先是XOJ神奇的界面 还没有建设完的OJ是这个样子的 一共有5道题 这次小测有3道题 是T2T3T4 首先是骑士精神 (BZOJ1085) 上来 ... 
- POJ 1082---->一个神一般的题
			代码只有10行,反正我是看了题解才知道的. 嗯 首先 看到这个题, BFS+一堆判断(什么平年闰年跨年各种乱搞肯定能搞出来,但是Code length就不一定了)... 然后呢 就看到了这个题解 从后 ... 
- JavaScript alert()函数的使用方法
			这里向大家简单介绍一下JavaScript alert()函数的使用,alert--弹出消息对话框,并且alert消息对话框通常用于一些对用户的提示信息. JavaScript alert()函数 a ... 
- C#之经理评分系统
			PM类,几乎全是属性 using System; using System.Collections.Generic; using System.Linq; using System.Text; usi ... 
- Tomcat  程序无问题的情况下页面打开变慢的原因
			看看这写日志的频率就知道我有多闲了.. 前言: 其实关于tomcat,遇到过很多关于“慢”的问题,比如启动慢,比如页面打开慢, 以前太忙也太懒,不愿意花时间分析原因,现在终于肯静下来找原因 环境是ec ... 
