Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Python爬虫实战】Scrapy 翻页攻略从入门到精通的完整教程

【Python爬虫实战】Scrapy 翻页攻略从入门到精通的完整教程

作者头像
易辰君
发布于 2024-12-25 02:22:25
发布于 2024-12-25 02:22:25
36700
代码可运行
举报
文章被收录于专栏:CSDNCSDN
运行总次数:0
代码可运行

前言

Scrapy 是一个强大的网页爬虫框架,广泛用于从网站中抓取数据。在使用 Scrapy 进行数据抓取时,翻页请求是常见的需求。本文将详细介绍 Scrapy 发起翻页请求的原理与实现方式,包括如何通过 Scrapy 框架进行翻页请求、如何自定义请求参数,以及如何处理多页面的数据提取。

一、翻页请求的基本思路

要提取所有页面的数据,最直接的方式就是通过翻页请求,访问每一页的 URL 并提取数据。通常在爬取网页时,页面内容会分为多个分页,每一页显示部分数据,用户可以点击 "下一页"(或 "后页")来加载下一部分内容。

(一)使用 requests 模块实现翻页

requests 模块中,进行翻页的操作大致是这样:

  1. 获取下一页的 URL 地址。通过分析网页,提取下一页的链接。
  2. 发起 HTTP 请求,例如调用 requests.get(url),访问下一页的数据。

这种方式简单直观,但它的缺点是每次翻页都需要手动解析并发起请求。

(二)Scrapy 实现翻页的思路

Scrapy 实现翻页请求的思路与 requests 模块类似,但它的实现更加高效和灵活。Scrapy 使用异步请求,可以并发发起多个请求,同时对请求进行调度与管理。其实现逻辑如下:

  1. 获取下一页的 URL 地址。通过解析当前页面,获取下一页的 URL 地址。
  2. 构造请求,将翻页请求传递给 Scrapy 引擎进行处理。

二、Scrapy 实现翻页请求的步骤

(一)实现翻页请求的基本方法

实现 Scrapy 翻页请求的基本步骤如下:

  1. 确定翻页 URL 地址:通过解析页面源代码,确定下一页的 URL 地址。通常,翻页 URL 会带有类似 ?page=2&start=25 的查询参数。
  2. 构造翻页请求:使用 scrapy.Request(url, callback) 来创建一个新的请求,将其传递给引擎。callback 用来指定处理响应的函数。
  3. 交给 Scrapy 引擎处理:使用 yield scrapy.Request(url, callback) 将翻页请求交给 Scrapy 引擎进行调度和执行。

(二)代码实现示例

以爬取某电影 网站Top100 为例,学习如何实现翻页请求。

假设我们已经获取了第一页的数据,接下来就需要实现翻页的逻辑。以下是实现翻页请求的代码示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import scrapy

class DoubanSpider(scrapy.Spider):
    name = "douban"
    start_urls = ['https://xxxxxx']

    def parse(self, response):
        # 提取当前页面的电影数据
        ol_list = response.xpath('//ol[@class="grid_view"]/li')
        for ol in ol_list:
            item = {}
            item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()
            item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()
            item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()
            yield item

        # 提取下一页的链接
        next_url = response.xpath("//a[text()='后页>']/@href").extract_first()
        if next_url:
            next_url = response.urljoin(next_url)  # 拼接完整的 URL
            yield scrapy.Request(next_url, callback=self.parse)

在这段代码中,parse 方法首先提取当前页面的电影数据,然后查找并拼接下一页的 URL 地址。如果下一页存在,就创建一个新的请求,通过 yield scrapy.Request(next_url, callback=self.parse) 递归地发起翻页请求。

(三)Scrapy 请求的常用参数

Scrapy 的 Request 对象有多个参数,可以帮助我们定制请求的行为,常用的参数有:

  • url:请求的 URL 地址。
  • callback:指定响应处理函数。
  • method:指定请求的方法,默认为 GET
  • headers:请求头,通常用来设置 User-Agent 或 Referer 等。
  • meta:传递数据给下一个回调函数,用于跨请求传递数据。
  • dont_filter:如果设置为 True,则 Scrapy 不会过滤重复的请求。

例如,我们可以通过 meta 来传递当前页面的数据,或者使用 dont_filter=True 来防止 Scrapy 过滤掉已请求的 URL。


三、处理翻页请求的优化方法

(一)重写 start_requests 方法

在上面的示例中,我们使用了 start_urls 来启动爬虫,但如果需要更复杂的翻页逻辑,例如分页的页码是动态生成的,或者 URL 中包含参数,我们可以重写 start_requests 方法,手动生成请求。

例如,假设页面的翻页 URL 是通过 start=25 来表示页码,每 25 条数据一页,我们可以如下编写 start_requests 方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def start_requests(self):
    for i in range(10):  # 假设我们需要爬取 10 页
        url = f'https://xxxxxxx/top250?start={i * 25}&filter='
        yield scrapy.Request(url, callback=self.parse)

通过这种方式,我们可以自定义分页 URL,避免手动解析 HTML 中的翻页链接。

(二)使用 meta 参数在不同解析函数中传递数据

有时候,我们需要将一些数据从一个解析函数传递到另一个解析函数。Scrapy 提供了 meta 参数,可以用来在请求之间传递数据。

例如,在爬取电影详细信息时,我们可能需要从列表页抓取每个电影的基本信息,然后跳转到详情页。我们可以通过 meta 参数传递数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def parse(self, response):
    for ol in response.xpath('//ol[@class="grid_view"]/li'):
        item = {}
        item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()
        item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()
        detail_url = ol.xpath('.//div[@class="hd"]/a/@href').extract_first()
        yield scrapy.Request(detail_url, callback=self.parse_detail, meta={'item': item})

def parse_detail(self, response):
    item = response.meta['item']
    # 进一步抓取详情页的内容
    item['director'] = response.xpath('//span[text()="导演:"]/following-sibling::text()').extract_first()
    yield item

在上面的代码中,parse 方法将每个电影的基本信息保存在 item 字典中,并将其传递到 parse_detail 函数中,进行进一步的数据提取。

四、其他注意事项

(一)处理请求头与代理

为了避免被网站封禁,我们通常需要设置请求头中的 User-Agent,以及使用代理 IP。Scrapy 可以通过修改 settings.py 文件中的配置来设置这些信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
ROBOTSTXT_OBEY = False  # 如果不需要遵守 robots.txt,可以设置为 False

(二)请求过滤与重复请求

Scrapy 会默认过滤已访问的 URL 地址,如果希望在某些情况下允许重复请求,可以通过 dont_filter=True 来禁用 URL 过滤。例如,翻页请求通常会重复访问相同的 URL,需要禁用过滤:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
yield scrapy.Request(next_url, callback=self.parse, dont_filter=True)

五、总结

Scrapy 提供了一种高效而灵活的方式来处理翻页请求。通过 scrapy.Request 对象,我们可以轻松地发送请求并处理响应。同时,Scrapy 还提供了强大的数据传递机制(如 meta 参数)和优化手段(如重写 start_requests 方法),使得分页抓取的实现更加灵活和高效。掌握这些技巧,对于编写高效、稳定的爬虫是非常有帮助的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
编程篇(002)-js实现一个打点计时器
1、从 start 到 end(包含 start 和 end),每隔 100 毫秒 console.log 一个数字,每次数字增幅 1 2、返回的对象中需要包含一个 cancel 方法,用于停止定时操作 3、第一个数需要立即输出
齐丶先丶森
2022/05/12
1.9K0
Web前端学习 第3章 JavaScript基础教程17 计时器方
计时器方法可以实现在指定的时间过后,单次或重复调用函数的功能,setTimeout可以实现函数在指定毫秒数后单次执行,setInterval可以实现函数在指定毫秒数后重复执行,语法如下所示:
学习猿地
2020/06/17
1.6K0
Web前端学习 第3章 JavaScript基础教程17 计时器方
你所不知道的setTimeout
JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成。它们向任务队列添加定时任务。初始接触它的人都觉得好简单,实时上真的如此么?这里记载下,一路对其使用姿势变迁的历程。 1, setTimeout()基础 setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。 var timerId = setTimeout(func|code, de
晚晴幽草轩轩主
2018/03/27
1.9K0
关于JavaScript计时器的知识学习
推特上大约一半的回答都是错误的。答案并不是 V8(或者虚拟机)!!虽然“JavaScript”计时器” 很出名,但是 setTimeout 和 setInterval 函数并不是 ECMAScript 规范或者任何 JavaScript 引擎实现。定时器由浏览器实现,在不同浏览器中的实现也会有所不同,Node.js 也实现了自己的定时器。
coder_koala
2020/12/17
1.7K0
关于JavaScript计时器的知识学习
仅用18行JavaScript构建一个倒数计时器
因此,事不宜迟,这里介绍了如何仅用18行JavaScript来制作自己的倒计时时钟。
Lemon黄
2020/06/04
3.1K0
仅用18行JavaScript构建一个倒数计时器
实战|仅用18行JavaScript构建一个倒数计时器
有时候,你会需要构建一个 JavaScript 倒计时时钟。你可能会有一个活动、一个销售、一个促销或一个游戏。你可以用原生的 JavaScript 构建一个时钟,而不是去找一个插件。尽管有很多很棒的时钟插件,但是使用原生 JavaScript 可以带来以下好处:
张张
2020/09/18
4.4K0
实战|仅用18行JavaScript构建一个倒数计时器
经典JS闭包面试题
大部分人都会做错的经典JS闭包面试题 目录 由工作中演变而来的面试题 JS中有几种函数 创建函数的几种方式 三个fun函数的关系是什么? 函数作用域链的问题 到底在调用哪个函数? 后话 由工作中演变而来的面试题 这是一个我工作当中的遇到的一个问题,似乎很有趣,就当做了一道题去面试,发现几乎没人能全部答对并说出原因,遂拿出来聊一聊吧。 先看题目代码: function fun(n,o) { console.log(o) return { fun:function(m){ return
逸鹏
2018/04/09
1.7K0
经典JS闭包面试题
2016.05 第三周 群问题分享
HTML+CSS 一个div里面有个img标签,div的高度由img撑开;img的兄弟级有个div要使内层div的高度等于外层div的高度,除了用JS实现,还能怎么实现? 2016.05.16~2016.06.20 核心概念 flex、position、display 参考答案 结构: <div class="wrap"> <img src="h5_course.jpg" alt="HTML5学堂"> <div>HTML5</div> </div> 设置多栏多列布局display
HTML5学堂
2018/03/13
1.1K0
js中settimeout()的用法详解_低噪放工作原理
setTimeout与setInterval是JavaScript引擎提供的两个定时器方法,分别用于函数的延时执行和循环调用。前者的主要思想是通过一个定时器,让函数在计时结束后再执行;后者则是每隔一定的时间,就启动一次函数的执行。
全栈程序员站长
2022/11/09
1.8K0
js中settimeout()的用法详解_低噪放工作原理
🥬 🐶的uniapp学习之🦌 【计时器】
我这里使用的是npm安装。如果是纯的uniapp项目,是没有包管理器package.json的,更没有node_modules的。
用户4793865
2023/01/12
1.7K0
js内置对象---计时器对象
js内置对象---计时器对象 一、计时器对象简介 二、一次性计时器 1. 一次性计时器的写法 2. 清除计时器 三、循环计时器 1. 一次性计时器的写法 2. 清除计时器 四、帧计时器 1. 设置兼容性 2. 移除计时器 五、把一次性计时器写成循环计时器 1. 写法 2. 移除计时器 六、三个计时器的区别 一、计时器对象简介 计时器对象分类 计时器对象分为一次性计时器,循环计时器,帧计时器(跟电脑的刷新频率有关) 二、一次性计时器 计时器的参数有string||function delay ms ms—延迟
IT工作者
2022/03/29
2.5K0
javaScript学习笔记(一)js基础
JavaScript是目前web开发中不可缺少的脚本语言,js不需要编译即可运行,运行在客户端,需要通过浏览器来解析执行JavaScript代码。
全栈程序员站长
2022/09/15
2.8K0
javaScript学习笔记(一)js基础
37个JavaScript基本面试问题和解答(建议收藏)
1、使用typeof bar ===“object”来确定bar是否是一个对象时有什么潜在的缺陷?这个陷阱如何避免?
用户1272076
2019/03/26
3.1K0
前端必备,25个最基本的JavaScript面试问题及答案
1.使用 typeof bar === "object" 来确定 bar 是否是对象的潜在陷阱是什么?如何避免这个陷阱?
用户5997198
2019/08/09
9880
【Node.js】全局可用变量、函数和对象
在Node.js中提供了一些全局可用的变量、函数和对象,全局就是不需要进行模块加载,可以直接使用的。其中包括全局作用域的函数和对象。也包括不在全局作用域,而在每个模块作用域都存在的变量、函数和对象,在全局可用,但不是golbal对象的属性。
颜颜yan_
2023/02/19
2.7K0
【Node.js】全局可用变量、函数和对象
JavaScript 严格模式
严格模式是 ECMAScript5 (ES5)发布的语言新特性。使用严格模式可以限制 JavaScript 的一些语言特性,使用严格模式可以去除在书写代码时的一些“骚操作”(有些特性在严格模式下是不可用的),使代码更严谨整洁。
多云转晴
2020/02/17
1K0
settime和setinterval_setinterval是异步还是同步
setTimeout和setInterval的语法相同。它们都有两个参数,一个是将要执行的代码字符串,还有一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将执行那段代码。
全栈程序员站长
2022/11/09
8230
「查缺补漏」送你 54 道 JavaScript 面试题
. VS = 操作符优先级 let a = {n : 1}; let b = a; a.x = a = {n: 2}; console.log(a.x) console.log(b.x) 输出是什么呢? 真的想明白了吗? 答案 undefined { n : 2} 你真的了解作用域吗 var a = 0, b = 0; function A(a) {
童欧巴
2020/12/15
1.1K0
前端js手写题经常忘,记录一下
使用时间戳的节流函数会在第一次触发事件时立即执行,以后每过 wait 秒之后才执行一次,并且最后一次触发事件不会被执行
helloworld1024
2022/09/23
1K0
[Python实战]你也能写的计时器程序
上次,公众号介绍了如何使用 Pyqt5 制作猜数游戏界面,并介绍了如何在 Pycharm 中使用 Qt Designer 生成 UI 文件。这次,我们要学习如何写一个简单的计时器程序。
用户2870857
2019/12/23
1.9K0
[Python实战]你也能写的计时器程序
推荐阅读
相关推荐
编程篇(002)-js实现一个打点计时器
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验