『scrapy爬虫』03. 爬取多个页面(详细注释步骤)

目录

    • 1. 分析网页试着拿到多个页面的url
    • 2. 抓取250个电影
    • 3. start_requests的使用
    • 4. 代码规范
      • 导库的优化
      • 关于重写
      • 最终修改后的代码
    • 总结


欢迎关注 『scrapy爬虫』 专栏,持续更新中
欢迎关注 『scrapy爬虫』 专栏,持续更新中

1. 分析网页试着拿到多个页面的url

看到了一个个a标签对应的几页的页码url
在这里插入图片描述
这是1页到3页,因为是top250,总共10页.每一页就是25个,也对应着url中的参数0,25,50````````

https://movie.douban.com/top250?start=0&filter=
https://movie.douban.com/top250?start=25&filter=
https://movie.douban.com/top250?start=25&filter=

我们的douban.py

import scrapy
from scrapy import Selector

from myscrapy.items import MovieItem


class DoubanSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["movie.douban.com"]# 限制或允许访问的域名列表
    start_urls = ["https://movie.douban.com/top250"] # 起始url

    def parse(self, response):
        myselector=Selector(text=response.text)
        # 拿到了所有的li,也就是所有的电影,每一个li代表一个电影,list_items是由250个电影li组成的list
        list_items=myselector.css("#content > div > div.article > ol > li")
        for list_item in list_items:
            movie_item=MovieItem()#新建类的对象
            # 电影标题的 Selector
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.hd > a > span:nth-child(1)
            movie_item['title']=list_item.css("span.title::text").extract_first() # extract_first()从选择器中提取第一个匹配的数据。
            # 电影评分
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.bd > div > span.rating_num
            movie_item['score']=list_item.css("span.rating_num::text").extract_first()  # extract_first()从选择器中提取第一个匹配的数据。
            # # 电影影评
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.bd > p.quote > span
            movie_item['quato']=list_item.css("span.inq::text").extract_first()  # extract_first()从选择器中提取第一个匹配的数据。

            yield movie_item#把整理得到的数据给管道

        # 单个页面selector
        # content > div > div.article > div.paginator > a:nth-child(3)
        # ::attr(href)表示选取元素的href属性。使用.getall()方法可以获取匹配到的所有元素的href属性值,并将其存储在一个列表中。
        hrefs_list=myselector.css('div.paginator > a::attr(href)')
        for href in hrefs_list:
            url=response.urljoin(href.extract())
            print(url)

cmd运行,可以看到获取了url

scrapy crawl douban

在这里插入图片描述


2. 抓取250个电影

这里要用到scrapy中的request库,注意不是我们之前的requests这一个s的区别很大,不要导错包了.

我们之前不是定义过一个MovieItem类吗?这个request是scrapy内部定义好的,我们在这里传入的url都会和我们前面的start_urls = ["https://movie.douban.com/top250"] # 起始url 一样用于爬虫.

import scrapy
from scrapy import Selector,Request
from myscrapy.items import MovieItem


class DoubanSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["movie.douban.com"]# 限制或允许访问的域名列表
    start_urls = ["https://movie.douban.com/top250"] # 起始url

    def parse(self, response):
        myselector=Selector(text=response.text)
        # 拿到了所有的li,也就是所有的电影,每一个li代表一个电影,list_items是由250个电影li组成的list
        list_items=myselector.css("#content > div > div.article > ol > li")
        for list_item in list_items:
            movie_item=MovieItem()#新建类的对象
            # 电影标题的 Selector
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.hd > a > span:nth-child(1)
            movie_item['title']=list_item.css("span.title::text").extract_first() # extract_first()从选择器中提取第一个匹配的数据。
            # 电影评分
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.bd > div > span.rating_num
            movie_item['score']=list_item.css("span.rating_num::text").extract_first()  # extract_first()从选择器中提取第一个匹配的数据。
            # # 电影影评
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.bd > p.quote > span
            movie_item['quato']=list_item.css("span.inq::text").extract_first()  # extract_first()从选择器中提取第一个匹配的数据。

            yield movie_item#把整理得到的数据给管道

        # 单个页面selector
        # content > div > div.article > div.paginator > a:nth-child(3)
        # ::attr(href)表示选取元素的href属性。使用.getall()方法可以获取匹配到的所有元素的href属性值,并将其存储在一个列表中。
        hrefs_list=myselector.css('div.paginator > a::attr(href)')
        for href in hrefs_list:
            url=response.urljoin(href.extract())
            # print(url)
            # 将 Request 对象加入到爬虫的请求队列中,以便发送请求,相当于对每个页面执行抓取数据
            yield Request(url=url) #注意这个Request是来自scrapy的.   from scrapy import Selector,Request

cmd运行

scrapy crawl douban  -o douban250.csv

在这里插入图片描述


3. start_requests的使用

修复一个bug(为什么250条数据变多了)?
我们的起始页面start_urls = ["https://movie.douban.com/top250"] # 起始url
但是我们知道,页面的规则,因为是第一页比较特殊,省略了参数0,实际上第一页的url应该是https://movie.douban.com/top250?start=0&filter=,这导致我们重复2次爬取了第一页的数据,出现了2次肖申克的救赎
在这里插入图片描述
解决方案1,直接修改起始页面

start_urls = ["https://movie.douban.com/top250"] # 起始url
改为
start_urls = ["https://movie.douban.com/top250?start=0&filter="] # 起始url

优雅方案2,start_requests一开始就设置要解析的url,不爬取页面url,告诉爬虫要爬的页面有哪些

import scrapy
from scrapy import Selector,Request
from myscrapy.items import MovieItem


class DoubanSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["movie.douban.com"]# 限制或允许访问的域名列表
    start_urls = ["https://movie.douban.com/top250"] # 起始url

    def start_requests(self) :
        for page in range(10): #10页
            yield Request(url=f'https://movie.douban.com/top250?start={page*25}&filter=')


    def parse(self, response):
        myselector=Selector(text=response.text)
        # 拿到了所有的li,也就是所有的电影,每一个li代表一个电影,list_items是由250个电影li组成的list
        list_items=myselector.css("#content > div > div.article > ol > li")
        for list_item in list_items:
            movie_item=MovieItem()#新建类的对象
            # 电影标题的 Selector
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.hd > a > span:nth-child(1)
            movie_item['title']=list_item.css("span.title::text").extract_first() # extract_first()从选择器中提取第一个匹配的数据。
            # 电影评分
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.bd > div > span.rating_num
            movie_item['score']=list_item.css("span.rating_num::text").extract_first()  # extract_first()从选择器中提取第一个匹配的数据。
            # # 电影影评
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.bd > p.quote > span
            movie_item['quato']=list_item.css("span.inq::text").extract_first()  # extract_first()从选择器中提取第一个匹配的数据。

            yield movie_item#把整理得到的数据给管道

        # # 单个页面selector
        # # content > div > div.article > div.paginator > a:nth-child(3)
        # # ::attr(href)表示选取元素的href属性。使用.getall()方法可以获取匹配到的所有元素的href属性值,并将其存储在一个列表中。
        # hrefs_list=myselector.css('div.paginator > a::attr(href)')
        # for href in hrefs_list:
        #     url=response.urljoin(href.extract())
        #     # print(url)
        #     # 将 Request 对象加入到爬虫的请求队列中,以便发送请求,相当于对每个页面执行抓取数据
        #     yield Request(url=url) #注意这个Request是来自scrapy的.   from scrapy import Selector,Request

cmd运行

scrapy crawl douban  -o douban250_true.csv

在这里插入图片描述


4. 代码规范

导库的优化

在优化 Python 代码的导入语句时,通常会按照一定的规则和顺序进行排序和分组。这些规则和顺序有助于提高代码的可读性和维护性。以下是一般情况下推荐的导入规则和顺序:

  • 标准库导入:首先导入Python标准库中的模块,每个导入语句占一行。
python
import os
import sys
  • 第三方库导入:接着导入第三方库或框架的模块,每个导入语句占一行。
python
import requests
import pandas as pd

本地应用/模块导入:最后导入项目中的自定义模块或应用程序模块。

python
from myapp import utils
from myapp.models import User
  • 空行分隔:在不同类型的导入之间加入空行,以提高可读性。

  • 按字母顺序排序:可以按照字母顺序对每个导入组进行排序,或者使用工具自动排序。

  • 避免通配符导入:尽量避免使用 from module import * 的方式,应该明确导入需要的内容。

  • 别名处理:合理使用别名来简化长模块名,但不要过度缩写或使用难以理解的别名。用一些约定俗成的别名.

import pandas as pd

可以使用pycharm的快捷整理你的导包书写规范
在这里插入图片描述

关于重写

可以看到警告.
在这里插入图片描述

Signature of method 'DoubanSpider.parse()' does not match signature of the base method in class 'Spider'

这是因为我们的parse继承的DoubanSpider类的scrapy.Spider,我们按住ctrl点击scrapy.Spider前往观察这个被重写的方法,从图中可以看到这几个def都是重写这个spide的方法
在这里插入图片描述

class DoubanSpider(scrapy.Spider):
    def parse(self, response):

可以看到被重写的方法原型
在这里插入图片描述
统一格式

改为下面代码即可消除警告
def parse(self,response, **kwargs):

最终修改后的代码

import scrapy
from scrapy import Selector,Request
from myscrapy.items import MovieItem


class DoubanSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["movie.douban.com"]# 限制或允许访问的域名列表
    start_urls = ["https://movie.douban.com/top250"] # 起始url

    def start_requests(self) :
        for page in range(10): #10页
            yield Request(url=f'https://movie.douban.com/top250?start={page*25}&filter=')


    def parse(self,response, **kwargs):
        myselector=Selector(text=response.text)
        # 拿到了所有的li,也就是所有的电影,每一个li代表一个电影,list_items是由250个电影li组成的list
        list_items=myselector.css("#content > div > div.article > ol > li")
        for list_item in list_items:
            movie_item=MovieItem()#新建类的对象
            # 电影标题的 Selector
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.hd > a > span:nth-child(1)
            movie_item['title']=list_item.css("span.title::text").extract_first() # extract_first()从选择器中提取第一个匹配的数据。
            # 电影评分
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.bd > div > span.rating_num
            movie_item['score']=list_item.css("span.rating_num::text").extract_first()  # extract_first()从选择器中提取第一个匹配的数据。
            # # 电影影评
            # content > div > div.article > ol > li:nth-child(1) > div > div.info > div.bd > p.quote > span
            movie_item['quato']=list_item.css("span.inq::text").extract_first()  # extract_first()从选择器中提取第一个匹配的数据。

            yield movie_item#把整理得到的数据给管道

        # # 单个页面selector
        # # content > div > div.article > div.paginator > a:nth-child(3)
        # # ::attr(href)表示选取元素的href属性。使用.getall()方法可以获取匹配到的所有元素的href属性值,并将其存储在一个列表中。
        # hrefs_list=myselector.css('div.paginator > a::attr(href)')
        # for href in hrefs_list:
        #     url=response.urljoin(href.extract())
        #     # print(url)
        #     # 将 Request 对象加入到爬虫的请求队列中,以便发送请求,相当于对每个页面执行抓取数据
        #     yield Request(url=url) #注意这个Request是来自scrapy的.   from scrapy import Selector,Request

总结

大家喜欢的话,给个👍,点个关注!给大家分享更多计算机专业学生的求学之路!

版权声明:

发现你走远了@mzh原创作品,转载必须标注原文链接

Copyright 2024 mzh

Crated:2024-3-1

欢迎关注 『scrapy爬虫』 专栏,持续更新中
欢迎关注 『scrapy爬虫』 专栏,持续更新中
『未完待续』


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/455247.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

yum安装mysql 数据库tab自动补全

centos7上面没有mysql,它的数据库名字叫做mariadb [rootlocalhost ~]#yum install mariadb-server -y [rootlocalhost ~]#systemctl start mariadb.service [rootlocalhost ~]#systemctl stop firewalld [rootlocalhost ~]#setenforce 0 [rootlocalhost ~]#ss -na…

数字人基础 | 3D手部参数化模型2017-2023

楔子: 2017年年底的泰国曼谷, SIGGRAPH Asia会议上, 来自马普所的 Javier Romero, Dimitrios Tzionas(两人都是 Michael J. Black的学生)发布了事实性的手部参数化模型标准: MANO [1]。 MANO的诞生意味着 Michael J. Black团队在继人体参数化模型 SMPL后, 事实性的将能够表达人…

信息系统项目管理师--沟通管理

IT 项⽬成功有关的最重要的四个因素是:主管层的⽀持、⽤户参与、有经验的项⽬经理和清晰的业务⽬标 项⽬沟通管理是确保及时、正确地产⽣、收集、分发、存储和最终处理项⽬信息所需的过程 项⽬沟通管理由两部分组成:⼀是制定策略,确保沟通对…

GUI编程--PyQt5--QTabWidget

文章目录 组件使用信号样式设置 组件使用 QTabWidget 页签 信号 self._ui Ui_Sub() self._ui.setupUi(right) # 切换tab页 self._ui.tabWidget.currentChanged.connect(self.tab_slot)def tab_slot(self):cur_index self._ui.tabWidget.currentIndex()tab_name self._ui…

微信小程序小案例实战

.wxml: <view class "title">狂飙经典语录 </view> <view class"out"><block wx:if"{{listArr.length}}"> <!-- bloock不会影响排版--><view class"list"><view class"row" wx:…

unicloud delete 删除

delete 删除 unicloud 删除大概分为两种 一种是 通过指定文档ID删除 语法如下 collection.doc(_id).remove()还有一种是条件查找文档然后直接批量删除 语法如下 collection.where().remove()反正总归是先查找到指定数据,然后使用remove()函数删除 示例如下 collection.doc(…

软考高级:需求变更管理过程概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【目标检测经典算法】R-CNN、Fast R-CNN和Faster R-CNN详解系列一:R-CNN图文详解

学习视频&#xff1a;Faster-RCNN理论合集 概念辨析 在目标检测中&#xff0c;proposals和anchors都是用于生成候选区域的概念&#xff0c;但它们在实现上有些许不同。 Anchors&#xff08;锚框&#xff09;&#xff1a; 锚框是在图像中预定义的一组框&#xff0c;它们通常以…

区间异或和异或区间最大值异或区间最小值 --- 题解 --- (字典树好题)

区间异或和异或区间最大值异或区间最小值 &#xff1a; 题目大意&#xff1a; 思路解析&#xff1a; 题目查询的是区间异或和 ^ 最小值 ^ 最大值&#xff0c;如果我们确定了最小值和最大值&#xff0c;[l,r]&#xff0c;假设a[l]是最小值&#xff0c;a[r]是最大值&#xff0c…

【漏洞复现】金和OA viewConTemplate.action RCE漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

【linux中cd指令使用】cd进入与退出路径

【linux中cd指令使用】cd如何进入与退出路径 1、cd进入指定路径&#xff0c;比如我要进入下面这个路径中去运行setup.py文件&#xff0c;如果我不跳转到该路径下直接运行&#xff0c;会报错找不到该文件 cd空格路径&#xff0c;即可跳转到该路径 cd /public2/xxx/tiny-cuda…

【零基础学习05】嵌入式linux驱动中platform与设备树基本实现

大家好,为了进一步提升大家对实验的认识程度,每个控制实验将加入详细控制思路与流程,欢迎交流学习。 今天主要学习一下,基于总线、设备和驱动进行匹配的平台驱动模型,这次将采用设备树的platform设备与驱动的编写方法,目前绝大多数的Linux内核已经支持设备树,这次主要来…

MyBatis-Plus学习记录

目录 MyBatis-Plus快速入门 简介 快速入门 MyBatis-Plus核心功能 基于Mapper接口 CRUD 对比mybatis和mybatis-plus&#xff1a; CRUD方法介绍&#xff1a; 基于Service接口 CRUD 对比Mapper接口CRUD区别&#xff1a; 为什么要加强service层&#xff1a; 使用方式 CR…

LEETCODE3

法一:记忆化递归 int climbStairsRecursive(int n, int* memo) {if (n < 2) {return n;}if (memo[n] > 0) {return memo[n];}memo[n] climbStairsRecursive(n - 1, memo) climbStairsRecursive(n - 2, memo);return memo[n]; }int climbStairs(int n) {int* memo (in…

2061:【例1.2】梯形面积

时间限制: 1000 ms 内存限制: 65536 KB 提交数:201243 通过数: 79671 【题目描述】 在梯形中阴影部分面积是150平方厘米&#xff0c;求梯形面积。 【输入】 (无&#xff09; 【输出】 输出梯形面积&#xff08;保留两位小数&#xff09;。 【输入样例】 &#xff…

redis在微服务领域的贡献,字节跳动只面试两轮

dubbo.registry.addressredis://127.0.0.1:6379 注册上来的数据是这样&#xff0c;类型是hash /dubbo/ s e r v i c e / {service}/ service/{category} 如 /dubbo/com.newboo.sample.api.DemoService/consumers /dubbo/com.newboo.sample.api.DemoService/providers has…

JOSEF约瑟 TQ-100同期继电器 额定直流电压220V 交流电压100V±10V

TQ-100型同期继电器 TQ-100同期继电器 ​ l 应用 本继电器用于双端供电线路的自动重合闸和备用电源自投装置中&#xff0c;以检查线路电压与母线电压的 相位差和幅值差。 2 主要性能 2 1采用进口集成电路和元器件构成&#xff0c;具有原理先进、性能稳定、可靠性高、动作值精…

mysql生成连续的日期

1.代码 例如&#xff1a;生成"2023-03-01"至"2023-03-10"之间的日期 WITH RECURSIVE date_range AS (SELECT "2023-03-01" AS date FROM dualUNION ALLSELECT DATE_ADD(date, INTERVAL 1 DAY) dateFROM date_rangeWHERE DATE_ADD(date, INTER…

windows系统提示msvcp120.dll丢失如何解决,如何找回dll文件?

如果你的电脑出现了关于msvcp120.dll丢失的情况那么大家一定要及时去解决msvcp140.dll丢失的问题&#xff0c;msvcp120.dll丢失可能会导致电脑出现各类的问题&#xff0c;今天就教大家四种关于msvcp120.dll丢失的解决办法&#xff0c;有效的解决msvcp120.dll丢失。 一、msvcp1…

php 对接Bigo海外广告平台收益接口Reporting API

今天对接的是Bigo广告reporting api接口&#xff0c;拉取广告收益回来自己做统计。记录分享给大家 首先是文档地址,进入到BIGO后台就能看到文档地址以及参数&#xff1a; 文档地址&#xff1a;https://www.bigossp.com/guide/sdk/reportingApi/doc?type1 接入这些第三方广告…