当前位置: 首页 > news >正文

掌握Scrapy数据建模与请求技巧

scrapy数据建模与请求

学习目标:

  1. 应用scrapy项目中建模

  2. 应用构造Request对象,并发送请求

  3. 应用meta参数在不同解析函数中传递数据

数据建模

通常在做项目的过程中,在items.py中进行数据建模

为什么建模

  1. 定义item即提前规划好那些字段要抓取,防止手误,因为定义好之后,在运行过程中,系统会自动检查

  2. 配合注释一起可以清晰的知道要抓取那些字段,没有定义的字段不能抓取,在目标字段少的时候可以使用字典代替

  3. 使用scrapy的一些特定组件需要item做支持,如scrapy的ImagesPipeline管道类

如何建模

在items.py文件中定义要提取的字段:

import scrapy
​
class Day01Item(scrapy.Item):# define the fields for your item here like:# 老师的名字name = scrapy.Field()# 老师的级别title = scrapy.Field()# 老师的介绍desc = scrapy.Field()

然后下面进行讲解怎么使用,但是我们建模完后通常不会在这个文件中使用,回去项目文件中使用,这里解决是为了讲解

class Day01Item(scrapy.Item):# define the fields for your item here like:# 老师的名字name = scrapy.Field()# 老师的级别title = scrapy.Field()# 老师的介绍desc = scrapy.Field()
​
if __name__ == '__main__':# 实例化对象item = Day01Item()item['name'] = 'hui函数'item['title'] = '高手'item['desc'] = '一个真正学习的程序员'print(item)print(type(item))# 打印结果# {'desc': '一个真正学习的程序员', 'name': 'hui函数', 'title': '高手'}# <class '__main__.Day01Item'>

这里可以由代码看出来,我们的item打印出来的数据和字典一模一样,但是它不属于字典,由type可以看出

前面不是说了,如果手误打错了,系统会自动进行检查吗?那么,下面就可以试一下,将item的name打成nama看看会发生什么

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
​
import scrapy
​
​
class Day01Item(scrapy.Item):# define the fields for your item here like:# 老师的名字name = scrapy.Field()# 老师的级别title = scrapy.Field()# 老师的介绍desc = scrapy.Field()
​
if __name__ == '__main__':# 实例化对象item = Day01Item()item['nama'] = 'hui函数'item['title'] = '高手'item['desc'] = '一个真正学习的程序员'print(item)print(type(item))"""Traceback (most recent call last):File "C:\Users\Desktop\python爬虫\scrapy_day01\day01\day01\items.py", line 21, in <module>item['nama'] = 'hui函数'~~~~^^^^^^^^File "C:\Users\AppData\Local\Programs\Python\Python312\Lib\site-packages\scrapy\item.py", line 98, in __setitem__raise KeyError(f"{self.__class__.__name__} does not support field: {key}")
KeyError: 'Day01Item does not support field: nama'
​"""

由上面的报错结果可以看出,系统会提示我们name写错了

如何使用模板类

模板类定义好后需要在爬虫中导入并且实例化,之后使用的方法和使用字典相同

示例:

  1. 首先,我们来到上一次写的抓取某网站老师信息的案例,将我们的模板类导入到spider的爬虫文件里面,然后实例化对象

    import scrapy
    # 导入模型类
    from ..items import Day01Item
    ​
    class ItcastSpider(scrapy.Spider):name = "itcast"allowed_domains = ["itcast.cn"]start_urls = ["https://www.itheima.com/teacher.html"]
    ​def parse(self, response):# 实例化模板对象item_data_dict = Day01Item()# 获取数据data_list = response.xpath("//*/div[@class='li_txt']")print('获取到数量为:',len(data_list))for data_item in data_list:name = data_item.xpath("./h3/text()").extract_first()title = data_item.xpath("./h4/text()").extract_first()desc = data_item.xpath("./p/text()").extract_first()print(f'老师的名字:{name},级别:{title},介绍:{desc}')item_data_dict['name'] = nameitem_data_dict['title'] = titleitem_data_dict['desc'] = desc# 返回到pipeline.py文件yield item_data_dict
  2. 由于这里的item_data_dict不属于字典,所以我们要进入管道文件,将我们返回的数据转换为字典数据进行保存

    from itemadapter import ItemAdapter
    ​
    import json
    class Day01Pipeline:def __init__(self):self.file = open('itcast.txt','w')
    ​def process_item(self, item, spider):# 将数据转换为字典类型item = dict(item)# 序列化为json格式json_data = json.dumps(item,ensure_ascii=False)# 写入文件self.file.write(json_data)# 返回引擎return item
    ​def __del__(self):self.file.close()

开发流程总结

  1. 创建项目

    scrapy startproject 项目名
  2. 明确目标

    在items.py文件中进行建模

  3. 创建爬虫

    • 创建爬虫

      scrapy genspider 爬虫名 允许的域名
    • 完成爬虫

      修改start_urls
      检查修改allowed_domains
      编写解析方法
  4. 保存数据

    在pipeline.py文件中对数据进行处理的管道

    在settings.py文件中注册启用管道

翻页请求的思路

我们爬取数据的时候不可能只爬一页数据,那么对于一些要进行翻页请求的数据我们应该怎么办呢?

  • 回顾requests模块是如何实现翻页请求的:

    1. 找到下一页的url地址

    2. 调用requests.get(url)

  • scrapy实现翻页的思路:

    1. 找到下一页的url地址

    2. 构造url地址的请求对象,传递给引擎

构造Request对象,并发送请求

实现方法

  1. 确定url地址

  2. 构造请求,scrapy.Request(url,callback)

    • callback:指定解析函数名称,表示该请求返回的响应使用哪一个函数进行解析

  3. 把请求交给引擎:yield scrapy.Request(url,callback)

scrapy.Request的更多参数

scrapy.Request(url[,callback,method="GET",headers,body,cookies,meta,dont_filter=False])
参数解释
  1. 中括号里面的参数为可选参数

  2. callback:表示当前的url的响应交给哪个函数去处理

  3. meta:实现数据在不同的解析函数中传递,meta默认带有部分数据,比如下载延迟,深度请求等

  4. dont_filter:默认为False,表示开启过滤,会过滤请求过的url,如果一个页面要重复请求,那么就要可以改为True

  5. method:指定POST或者GET请求

  6. headers:接收一个字典,其中不包含cookies

  7. cookies:接收一个字典,专门放置cookies

  8. body:接收json字符串,为POST的数据,发送payload_post请求时使用

meta参数的使用

meta的作用:meta可以实现数据在不同的解析函数中的传递

在爬虫文件的parse方法中,提取详情页增加之前callback指定的parse_detail函数:

def parse(self,response):……yield scrapye.Request(detail_url,callback=self.parse_detail,meta={"item":item})……
def parse_detail(self,response):# 获取之前传入的itemitem = response.meta["item]

特别注意

  1. meta参数是一个字典

  2. meta字典中有一个固定的键proxy,表示代理ip,后面在scrapy的中间件中进行介绍

scrapy模拟登录

学习目标:

  1. 应用 请求对象cookies参数的使用

  2. 了解 start_requests函数的作用

  3. 应用 构造并发送post请求

回顾之前的模拟登陆的方法

requests模块是如何实现模拟登陆的?

  1. 直接携带cookies请求页面

  2. 找url地址,发送post请求存储cookie

selenium是如何模拟登陆的?

  1. 找到对应的input标签,输入文本点击登陆

scrapy的模拟登陆

  1. 直接携带cookies

  2. 找url地址,发送post请求存储cookie

scrapy携带cookies直接获取需要登陆后的页面

应用场景

  1. cookie过期时间很长,常见于一些不规范的网站

  2. 能在cookie过期之前把所有的数据拿到

  3. 配合其他程序使用,比如其使用selenium把登陆之后的cookie获取到保存到本地,scrapy发送请求之前先读取本地cookie

实现:重构scrapy的starte_rquests方法

scrapy中start_url是通过start_requests来进行处理的,其实现代码如下

# 这是源代码def start_requests(self) -> Iterable[Any]:warnings.warn(("The Spider.start_requests() method is deprecated, use ""Spider.start() instead. If you are calling ""super().start_requests() from a Spider.start() override, ""iterate super().start() instead."),ScrapyDeprecationWarning,stacklevel=2,)if not self.start_urls and hasattr(self, "start_url"):raise AttributeError("Crawling could not start: 'start_urls' not found ""or empty (but found 'start_url' attribute instead, ""did you miss an 's'?)")for url in self.start_urls:yield Request(url, dont_filter=True)

所以对应的,如果start_url地址中的url是需要登录后才能访问的url地址,则需要重写start_request方法并在其中手动添加上cookie

携带cookies登陆豆瓣
import scrapy
​
class DouSpider(scrapy.Spider):name = "dou"allowed_domains = ["douban.com"]start_urls = ["https://www.douban.com/people/290131564/?_i=3446982r7DGOBi"]
​def start_requests(self):url = self.start_urls[0]
​temp = '...' # 抓取cookie值cookies = {data.split('=')[0]: data.split('=')[-1] for data in temp.split('; ')}
​yield scrapy.Request(url=url,callback=self.parse,cookies=cookies)
​def parse(self, response):print(response.xpath('/html/head/title/text()').extract_first())

注意:

  1. scrapy中cookie不能够放在headers中,在构造请求的时候有专门的cookies参数,能够接受字典形式的coookie

  2. 在setting中设置

    USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
    ROBOTSTXT_OBEY = False //协议
    DOWNLOAD_DELAY = 3  # 防止请求过快
    COOKIES_ENABLED = True # 允许cookies


文章转载自:

http://DcYnGNBt.wkmjg.cn
http://bqgbCM2P.wkmjg.cn
http://zsYweKEs.wkmjg.cn
http://4X2H5lp0.wkmjg.cn
http://Plvl5zYR.wkmjg.cn
http://CJeTlN6N.wkmjg.cn
http://3E9kB0cE.wkmjg.cn
http://GkjfJsVC.wkmjg.cn
http://uyOHocGM.wkmjg.cn
http://3QN03hVK.wkmjg.cn
http://uXXeThSo.wkmjg.cn
http://mDdWzAPM.wkmjg.cn
http://8ZQTbbMV.wkmjg.cn
http://lF2OmEFt.wkmjg.cn
http://cMv9DBYK.wkmjg.cn
http://SBFauq93.wkmjg.cn
http://adDh0wTk.wkmjg.cn
http://rK6HfrIv.wkmjg.cn
http://4BzLq5Af.wkmjg.cn
http://cyiPBF1t.wkmjg.cn
http://6eko93rv.wkmjg.cn
http://nLDBjf2y.wkmjg.cn
http://uLGx5jej.wkmjg.cn
http://xnU6ss9a.wkmjg.cn
http://CcQw8pwE.wkmjg.cn
http://Ujk7qcNC.wkmjg.cn
http://m6hOk9RI.wkmjg.cn
http://nLidrMck.wkmjg.cn
http://9GKcv3sV.wkmjg.cn
http://pzg3CBGZ.wkmjg.cn
http://www.dtcms.com/a/385466.html

相关文章:

  • LLaMA Factory微调记录(重修版)
  • JAVA开发面试题
  • 逆向国内外社媒电商爬虫算法思路
  • 中山AI搜索优化公司:AI时代GEO技术全解析
  • PostgreSQL GIN 索引揭秘
  • 老鸟对单片机全局变量常用用法(读写在2个独立函数中)
  • 大前端社交应用中 AI 驱动的内容审核与反垃圾信息机制
  • MP3的ID3信息简介及其如何解析
  • MyBatis-Plus 扩展全局方法
  • java中的泛型
  • 使用 AWS Comprehend 综合指南
  • 使用秩和比拟解决非独立同分布情况下的投毒攻击
  • 七、vue3后台项目系列——包装scss、全句变量scss与导入
  • 煤矿山井下绝绝缘监测故障定位
  • 海外分部人员OA请假申请时长为0
  • MySQL --JDBC
  • python使用pyodbc通过不同认证方式连接sqlserver数据源
  • java通过线程池加CompletableFuture实现批量异步处理
  • Coze源码分析-资源库-创建知识库-后端源码-详细流程梳理
  • 极简版 Nginx 反向代理实验步骤
  • python-86-基于Graphviz或Mermaid绘制流程图
  • 智能农机无人驾驶作业套圈路径规划
  • Rayon Rust中的数据并行库入门教程
  • NumPy数组与Python列表的赋值行为解析
  • 基于 AI 的大前端智能家居控制应用开发
  • RAGFlow集成SGLang部署的大模型:实现OpenAI API兼容的自定义LLM调用
  • sqlsever 内存配置错误无法连接,后面恢复连接
  • 51c大模型~合集182
  • 2025.9.15总结
  • 深入理解 Roo Code 的 Code Actions 功能