scrapy进阶(豆瓣新书速递)(比亚迪)

scrapy数据建模与请求

学习目标:

  1. 应用 在scrapy项目中进行建模
  2. 应用 构造Request对象,并发送请求
  3. 应用 利用meta参数在不同的解析函数中传递数据
  4. scrapy构造post请求

1. 数据建模

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

1.1 为什么建模

  1. 定义item即提前规划好哪些字段需要抓,防止手误,因为定义好之后,在运行过程中,系统会自动检查
  2. 配合注释一起可以清晰的知道要抓取哪些字段,没有定义的字段不能抓取,在目标字段少的时候可以使用字典代替

1.2 如何建模

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

# Define here the models for your scraped items
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy
class DoubanItem(scrapy.Item):
    # define the fields for your item here like:
    name = scrapy.Field()    # 名字
    content = scrapy.Field()  # 内容
    link = scrapy.Field()  # 链接
    txt = scrapy.Field()  #详情介绍

1.3 如何使用模板类

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

爬虫文件.py

# -*- coding:utf-8 -*-
import scrapy
from douban.items import DoubanItem
....

    def parse(self, response):
        name = response.xpath('//h2[@class="clearfix"]/a/text()').extract()
        content = response.xpath('//p[@class="subject-abstract color-gray"]/text()').extract()
        link = response.xpath('//h2[@class="clearfix"]/a/@href').extract()
        for names, contents, links in zip(name, content, link):
            item = DoubanItem()  # 实例化后拿到模板类就可直接使用 本质是一个字典
            item['name'] = names
            item['content'] = contents.strip()
            item['link'] = links

注意:
1. from douban.items import DoubanItem这一行代码中 注意item的正确导入路径,忽略pycharm标记的错误
2. python中的导入路径要诀:从哪里开始运行,就从哪里开始导入

1.4 开发流程总结

1. 创建项目
   scrapy startproject 项目名
2. 明确目标
   在items.py文件中进行建模  (一般来说在开发流程里建模是必须的,但如果字段特别少也可以选择忽略)
3. 创建爬虫
   3.1 创建爬虫
       scrapy genspider 爬虫名 允许的域
   3.2 完成爬虫
       修改start_urls
       检查修改allowed_domains
       在parse方法里编写解析方法
4. 保存数据
   在pipelines.py文件中定义对数据处理的管道
   在settings.py文件中注册启用管道

2. 翻页请求的思路

  1. 找到下一页的url地址
  2. 把url地址构造成请求对象,传递给引擎

3. 构造Request对象,并发送请求

3.1 实现方法

  1. 确定url地址
  2. 构造请求,scrapy.Request(url,callback)
    • callback:指定响应体解析的函数名称,表示该请求返回的响应使用哪一个函数进行解析(callback不赋值的话默认是给parse方法解析)
  3. 把请求交给引擎:yield scrapy.Request(url,callback)

3.2 豆瓣新书速递爬虫

通过爬取豆瓣新书速递的页面信息,学习如何实现翻页请求

地址:豆瓣新书速递

思路分析:
  1. 获取首页的响应数据(因为里面有我们想要的翻页链接)
  2. 寻找下一页的地址,进行翻页,获取数据
注意:
  1. 可以在settings中设置ROBOTS协议

    False表示忽略网站的robots.txt协议,默认为True

    ROBOTSTXT_OBEY = False

  2. 可以在settings中设置User-Agent:
    (scrapy发送的每一个请求的默认UA都是设置的这个User-Agent)

    USER_AGENT = ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36’

3.3 代码实现

在爬虫文件的parse方法中:

....
    # 1,构造翻页
    # 提取下一页url
    part_url = response.xpath('//span[@class="next"]//a/@href').extract_first()
    # 2,判断是否为下一页的条件
    if '?subcat=' in part_url:
        # 构造完整的url
        next_url = response.urljoin(part_url)
        print("下一页参数信息:", part_url)
        print("下一页链接:", next_url)
        # 构造scrapy.Request对象,并yield给引擎,利用callback参数指定该Request对象之后获取的响应用哪个函数进行解析 
        yield scrapy.Request(url=next_url, callback=self.parse)

3.4 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地址,即请求过的url地址不会继续被请求,对需要重复请求的url地址可以把它设置为Ture,比如贴吧的翻页请求,页面的数据总是在变化;start_urls中的地址会被反复请求,否则程序不会启动
  5. method:指定POST或GET请求
  6. headers:接收一个字典,其中不包括cookies
  7. cookies:接收一个字典,专门放置cookies
  8. body:接收json字符串,为POST的数据,发送payload_post请求时使用(在下面内容中会介绍post请求)

4. meta参数的使用

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

使用场景:常用在数据分散在不同结构页面中

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

# 爬虫默认自带的解析方法
def parse(self,response):
     yield scrapy.Request(url=item['link'],callback=self.parse_detail, meta={'item': item})

# 新建一个解析方法 用于解析详情页 里面一定要有resposne参数
def parse_detail(self,response):
    # 获取meta传递过来的参数给item字典接收
    item = resposne.meta["item"]
特别注意
  1. meta参数是一个字典
  2. meta字典中有一个固定的键proxy,表示代理ip,关于代理ip的使用我们将在scrapy的下载中间件进行介绍

scrapy中间件的使用

学习目标:

  1. 应用 scrapy中使用间件使用随机UA的方法
  2. 应用 scrapy中使用代理ip的的方法

1.1 scrapy中间件的分类

根据scrapy运行流程中所在位置不同分为:

  1. 下载中间件
  2. 爬虫中间件

scrapy默认情况下,两中中间件都是在middlewares.py一个文件中,爬虫中间件使用方法和下载中间件相同,且功能重复,通常使用下载中间件

1.2 scrapy中间件的作用:预处理request和response对象

  1. 对header以及cookie进行更换和处理
  2. 使用代理ip等
  3. 对请求进行定制化操作

2. 下载中间件的使用方法:

接下来我们对豆瓣爬虫进行修改完善,通过下载中间件来学习如何使用中间件
编写一个Downloader Middlewares和我们编写一个pipeline一样,定义一个类,然后在setting中开启

Downloader Middlewares默认的方法:

  • process_request(self, request, spider):

    1. 当每个request通过下载中间件时,该方法被调用。
      2. 返回None值:没有return也是返回None,该request对象传递给下载器,或通过引擎传递给其他权重低的process_request方法
      3. 返回Response对象:不再请求,把response返回给引擎
      4. 返回Request对象:把request对象通过引擎交给调度器,此时将不通过其他权重低的process_request方法
  • process_response(self, request, response, spider):

    1. 当下载器完成http请求,传递响应给引擎的时候调用
      2. 返回Resposne:通过引擎交给爬虫处理或交给权重更低的其他下载中间件的process_response方法
      3. 返回Request对象:通过引擎交给调取器继续请求,此时将不通过其他权重低的process_request方法
  • 在settings.py中配置开启中间件,权重值越小越优先执行

3. 定义实现随机User-Agent的下载中间件

3.1 在middlewares.py中完善代码 middlewares.py中自带的代码可以删除掉

import random
class UserAgentDownloadMiddleware(object):
    user_agent = [
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:77.0) Gecko/20190101 Firefox/77.0',
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36',
        'Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16.2'
    ]
    # 方法名是scrapy规定的方法 (协商机制)
    # 每个交给下载器的request对象都会经过该方法,并期望返回response
    def process_request(self, request, spider):
        # 获取随机请求头
        u_a = random.choice(self.user_agent)
        # 设置请求头
        request.headers['User-Agent'] = u_a

3.2 在settings中设置开启自定义的下载中间件,设置方法同管道

settings文件所写参数的详细说明可参考以下博客:

https://blog.csdn.net/Lan_cer/article/details/87554025

DOWNLOADER_MIDDLEWARES = {
    'douban.middlewares.UserAgentDownloadMiddleware': 200,
}

4. 代理ip的使用

4.1 思路分析

  1. 代理添加的位置:request.meta中增加proxy字段
  2. 获取一个代理ip,赋值给request.meta['proxy']
    • 代理池中随机选择代理ip
    • 像代理ip的api发送请求获取一个代理ip

4.2 具体实现

class RandomProxy(object):
    ip_list = [
        '116.26.39.23:4215',
        '42.56.239.136:4278',
        '115.234.192.226:4275',
    ]
    def process_request(self, request, spider):
        proxy = random.choice(self.ip_list)
        # 需要加上https://,否则报错
        # 修改请求的元数据字典  用于给框架中其他组件传递信息 比如给其添加一个代理
        request.meta['proxy'] = 'https://' + proxy
同理要在settings.py中开启该中间件
DOWNLOADER_MIDDLEWARES = {
    'douban.middlewares.RandomProxy': 100,
    'douban.middlewares.UserAgentDownloadMiddleware': 200,
}

scrapy管道的使用

学习目标:

1. 掌握 scrapy管道(pipelines.py)的使用

之前我们在scrapy入门使用一节中学习了管道的基本使用,接下来我们深入的学习scrapy管道的使用
process_item(self,item,spider):

  • 管道类中必须有的函数
  • item指引擎传过来的数据 实现对item数据的处理
  • 必须return item
  • spide指的是使用这个管道的爬虫

2. 管道文件的修改

继续完善豆瓣爬虫,在pipelines.py代码中完善

# -*- coding:utf-8 -*-
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
import json
import logging

from itemadapter import ItemAdapter
import pymysql


class DoubanPipeline:
    def __init__(self):
        self.file = open('douban.json', 'a', encoding='utf-8')

    def process_item(self, item, spider):
        data = dict(item)
        json_data = json.dumps(data, ensure_ascii=False) + ',\n'
        self.file.write(json_data)
        
         # 不return的情况下,另一个权重较低的pipeline将不会获得item
        return item

    # 整个程序生命周期结束 内存销毁 该方法才会执行结束
    def __del__(self):
        self.file.close()


class DoubansqlPipeline:
    def __init__(self):
        # 连接数据库                 用户名       密码             数据库名               编码
        self.db = pymysql.connect(user='root', password='admin', database='xiaoxiao', charset='utf8')
        self.cursor = self.db.cursor()  # 获取操作游标

    def process_item(self, item, spider):
         # 此时item对象必须是一个字典,再插入,如果此时item是BaseItem则需要先转换为字典:dict(BaseItem)
        item = dict(item)
        # print(item)
        try:
            sql = 'insert into db_data(name,content,link,txt) values(%s,%s,%s,%s)'  # SQL语句
            self.cursor.execute(sql, [item['name'], item['content'], item['link'], item['txt']])  # 执行sql语句
            self.db.commit()  # 提交
        except Exception as e:
            logging.error(f'数据存储异常,原因:{e}')
            
       # 不return的情况下,另一个权重较低的pipeline将不会获得item
        return item

    # 当所属类运行完成 这个方法就会关闭掉
    def close_spider(self, spider):
        self.db.close()

3. 开启管道

在settings.py设置开启pipeline:

ITEM_PIPELINES = {
    'douban.pipelines.DoubanPipeline': 300,   # 300表示权重
    'douban.pipelines.DoubansqlPipeline': 301,  # 权重值越小,越优先执行!
}

4. pipeline使用注意点

  1. 使用之前需要在settings中开启
  2. pipeline在setting中键表示位置(即pipeline在项目中的位置可以自定义),值表示距离引擎的远近,越近数据会越先经过:权重值小的优先执行
  3. 有多个pipeline的时候,process_item的方法必须return item,否则后一个pipeline取到的数据为None值
  4. pipeline中process_item的方法必须有,否则item没有办法接受和处理
  5. process_item方法接受item和spider,其中spider表示当前传递item过来的spider
  6. def init(self): (或者可以写def open_spider(spider) 😃 都表示能够在爬虫开启的时候执行一次
  7. def close_spider(self, spider): 能够在爬虫关闭的时候执行一次
  8. 上述俩个方法经常用于爬虫和数据库的交互,在爬虫开启的时候建立和数据库的连接,在爬虫关闭的时候断开和数据库的连接

小结

  • 管道能够实现数据的清洗和保存,能够定义多个管道实现不同的功能,其中有个三个方法
    • process_item(self,item,spider):实现对item数据的处理
    • open_spider(self, spider): 在爬虫开启的时候仅执行一次
    • close_spider(self, spider): 在爬虫关闭的时候仅执行一次

scrapy.Request发送post请求

我们可以通过scrapy.Request()指定method、body参数来发送post请求;也可以使用scrapy.FormRequest()来发送post请求

1 发送post请求

注意:scrapy.FormRequest()能够发送表单和ajax请求,参考阅读 https://www.jb51.net/article/146769.htm

2 思路分析

  1. 找到post的url地址:然后定位url地址为https://www.bydauto.com.cn/api/comom/search_join_shop

  2. 找到请求体的规律:分析post请求的请求体(参数)

  3. start_urls中的url地址是交给parse处理的,如有必要,我们需要重写start_request这个定制方法:
    爬虫文件

import scrapy
import json
from jsonpath import jsonpath

class BydSpiderSpider(scrapy.Spider):
    name = 'byd_spider'
    # 1.检查域名
    allowed_domains = ['bydauto.com']
    # 2.修改请求url
    # start_urls = ['https://www.bydauto.com.cn/api/comom/search_join_shop']
    # 注意post请求的起始url发请求的那一刻要求是str类型
    city_url = 'https://www.bydauto.com.cn/api/comom/search_join_shop'
    # post请求的参数
    payload = {"type": 2, "province": 430000, "city": 430100, "network": 'null'}

    # 3,构造起始方法:start_requests(self),此方法是spider模块中的定制方法,是一个重写方法,不能修改名字和参数
    # 作用:爬虫从该方法开始,此时start_urls 和 parse( ) 函数可删除,可在该start_requests函数中写入多种请求
    def start_requests(self):
        # 4.将请求信息打包成一个请求对象 并将返回的响应数据交给parse方法处理
        yield scrapy.Request(url=self.city_url,method='POST',body=json.dumps(self.payload),callback=self.parse)

    # 5.解析比亚迪地址和电话信息
    def parse(self, response):
        json_data = response.json()
        address = jsonpath(json_data,'$..address')
        print(address)
        tel = jsonpath(json_data,'$..tel')
        print(tel)

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

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

相关文章

Vision Mamba论文阅读(主干网络)

这几天被Mamba刷屏了,又由于本人是做视觉方面任务的,固来看看mamba在视觉上的应用。 今天分享的是Vision Mamba: Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Model 论文网址:https://arxiv.or…

【蓝桥杯】

题目列表 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<bits/stdc.h> using llunsigned long long; #define int ll const int N2e510; int k0; std::string s; int a,b,c,d; void solve() {char op;std::cin>>op;if(opA){std::string s;for(int i1;i&l…

vue3结合element-plus之如何优雅的使用表格

背景 表格组件的使用在后台管理系统中是非常常见的,但是如果每次使用表格我们都去一次一次地从 element-plus 官网去 复制、粘贴和修改成自己想要的表格。 这样一来也说得过去,但是如果我们静下来细想不难发现,表格的使用都是大同小异的,每次都去复制粘贴,对于有很多表格…

5月23日 网络编程day6

1.IO多路复用的原理&#xff1f; 答&#xff1a;将文件描述符放入一个集合中&#xff0c;当集合中有事件产生&#xff0c;移除其他文件描述符&#xff0c;执行剩下的文件描述符所对应的任务&#xff0c;往复循环。 2.实现IO多路复用可以使用哪些函数完成&#xff1f; 答&…

【设计模式】JAVA Design Patterns——Balking(止步模式)

&#x1f50d;目的 止步模式用于防止对象在不完整或不合适的状态下执行某些代码。 &#x1f50d;解释 真实世界例子 洗衣机中有一个开始按钮&#xff0c;用于启动衣物洗涤。当洗衣机处于非活动状态时&#xff0c;按钮将按预期工作&#xff0c;但是如果已经在洗涤&#xff0c;则…

嵌入式科普(18)Ubuntu在移动硬盘的安装和启动

目录 一、概述 二、应用场景 三、移动硬盘安装Ubuntu 3.1 移动硬盘格式化 3.2 VMware安装Ubuntu到移动硬盘 四、电脑BIOS启动移动硬盘Ubuntu 五、从VMware启动移动硬盘Ubuntu 六、问题解决(坑)和思考提问 嵌入式科普(18)Ubuntu在移动硬盘的安装和启动 一、概述 在移动硬…

Python实现天气数据采集

Python实现天气数据采集 一、需求介绍二、完整代码一、需求介绍 本次天气数据采集的需求是获取每日的最高温、最低温、风力、风向、天气状况、AQI指数,如图所示,完整代码附后: 本次采集的目标网址是2345天气网: 上图的URL中,beijing是城市名称的缩写,54511即为城市代码…

【机器学习】前沿探索,如何让前端开发更加搞笑

在当今数字化时代&#xff0c;机器学习的崛起为前端开发带来了巨大的机遇和挑战。随着人工智能和数据科学的不断进步&#xff0c;前端工程师不再局限于传统的界面设计和交互体验&#xff0c;而是开始探索如何将机器学习技术融入到他们的工作中&#xff0c;以创造更加智能、个性…

Video-FocalNets: Spatio-Temporal Focal Modulation for Video Action Recognition

标题&#xff1a;Video-FocalNets&#xff1a;用于视频动作识别的时空聚焦调制 源文链接&#xff1a;Wasim_Video-FocalNets_Spatio-Temporal_Focal_Modulation_for_Video_Action_Recognition_ICCV_2023_paper.pdf (thecvf.com)https://openaccess.thecvf.com/content/ICCV202…

vscode打造舒适的python开发环境

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 背景 突然想写一些python小脚本&#xff0c;提升我的mac使用体验和日常效率提升…

LayUI使用(一)点击树组件的右边空白区域也可响应事件

前提&#xff1a; 如下&#xff0c;希望能够点击右边的空白区域也能够响应&#xff0c;而不仅仅是点击文本才响应 分析流程 一开始问了chatgpt&#xff0c;但它给的方案太麻烦了&#xff0c;而且还有错误&#xff0c;因此自己上手F12进入调试模式&#xff0c;点击查看最终渲…

【MATLAB】基于EMD-PCA-LSTM的回归预测模型

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 1 基本定义 基于EMD-PCA-LSTM的回归预测模型是一种结合了经验模态分解&#xff08;Empirical Mode Decomposition, EMD&#xff09;、主成分分析&#xff08;Principal Component Analysis, PCA&#xff09;和长短期记忆…

Qt快速入门到熟练(电子相册项目(二))

上一节我们成功实现了创建项目的向导界面的开发&#xff0c;这节我们继续去实现电子相册的其他功能。 新建DirTreeWidget类 还记得在Qt快速入门到熟练(电子相册项目(一))-CSDN博客里面&#xff0c;我们是在QDockWidget中添加了一个treeWidget作为以后显示目录树的空间…

App Inventor 2 TaifunBattery 电池管理器拓展,获取电量、电池容量

TaifunBattery 电池管理器拓展 电池管理器扩展。所需权限&#xff1a;无 demo效果图&#xff1a; 属性 返回当前健康常量。 可能的值有&#xff1a;冷(cold)、死(dead)、好(good)、过热(overheat)、过压(over voltage)、未知(unknown)、未指定故障(unspecified failure)。 返…

海山数据库(He3DB)数据仓库发展历史与架构演进:(一)传统数仓

从1990年代Bill Inmon提出数据仓库概念后经过四十多的发展&#xff0c;经历了早期的PC时代、互联网时代、移动互联网时代再到当前的云计算时代&#xff0c;但是数据仓库的构建目标基本没有变化&#xff0c;都是为了支持企业或者用户的决策分析&#xff0c;包括运营报表、企业营…

最近真的忙炸了。。

大家好&#xff0c;我是鱼皮&#xff0c;每隔一段时间&#xff0c;我都会写一段自己的工作复盘。最近这个月的主题就是 “忙炸了”&#xff01;基本上只要睁眼的时间&#xff0c;基本都是在工作&#xff0c;以至于眼药水都怼上了。 简单分享一下我最近在做的一些事情吧。 1、…

docker 指定jdk11镜像执行jar

dockerfile :下载jdk11 并将上传的jar 放入jdk11容器/root&#xff0c;改名为app.jar vi dockerfile 。。。。内容见下图 # 构建jdk11镜像 docker build -t demo . # 也可以通过jdk11镜像&#xff08;前提有jdk11镜像&#xff09;外挂载目录方式运行jar docker run --name d…

简单介绍十款可以免费使用的API测试工具

API开发应该是后端开发最常见的工作&#xff0c;而调试和测试API是非常关键的&#xff0c;这篇文章简单介绍几款常用的工具以供大家参考。 SoapUI SoapUI是很老牌的工具的&#xff0c;在之前Webservice盛行的时候经常会用到。 现在官方推出了Pro版本的ReadyAPI&#xff0c;但要…

MacOS安装Docker-Compose

方法一 按照百度的方法进行安装&#xff0c;我大致复制一下百度的方法 1.确保您已经安装了Docker Desktop。 2.下载Docker Compose二进制文件。 3.将二进制文件移动到/usr/local/bin目录。 4.更改二进制文件的权限&#xff0c;使其可执行。 以下是具体的命令&#xff1a;…

使用TensorFlow Lite Micro流程记录(带源码)

文章目录 0 关于tflite micro1 克隆仓库2 编译静态库3 模型转换4 编写工程5 编写demo5.1 进行算子注册 5.2 推理过程6 debug记录6.1 缺少算子 6.2 注册表太小6.3 段错误6.4 进一步减小库体积 7 实际部署 0 关于tflite micro 关于tflite micro在这里接不做过多介绍了&#xff0c…