scrapy框架基于管道的持久化存储
scrapy框架的使用
基于管道的持久化存储的编码流程
在爬虫文件中数据解析
将解析到的数据封装到一个叫做
Item类型的对象将
item类型的对象提交给管道管道负责调用process_item的方法接收item,然后进行某种形式的持久化存储在配置文件中开启管道
ITEM_PIPELINES = {
'frist_scrapy.pipelines.FristScrapyPipeline': 300,
} # 将这段代码的注释去掉
注意事项:
1.什么情况下需要用到多个管道类
- 一个管道类对应一种形式的持久化存储 2.process_item中的return item:
- 可以将item提交给下一个即将被执行的管道类 3.如果直接将一个字典写入到redis报错的话:
- pip install redis==2.10.6
全栈数据的爬取
手动请求的发送
yield scrapy.Request(url=new_url,callback=self.parse) # 可以传入参数 meta
yield scrapy.Request(url=new_url,callback=self.parse,meta={'item':item})
总结:什么时候用yield
1.向管道提交item的时候
2.手动请求发送的时候
如何发送post请求:
yield scrapy.FromRequest(url=new_url,callback=self.parse,formdata={})为什么start_urls列表可以进行get请求的发送:
父类对start_requests的原始实现:
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url,callback=self.parse)
五大核心组件(对象)

对scrapy的异步实现有一定的理解
相关方法和对象实例化的调用流程
组件的作用:
引擎(Scrapy)
用来处理整个系统的数据流处理, 触发事务(框架核心) 调度器(Scheduler)
用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址 下载器(Downloader)
用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的) 爬虫(Spiders)
爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面 项目管道(Pipeline)
负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
如何适当提升scrapy爬取数据的效率
增加并发:
默认scrapy开启的并发线程为16个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置成了为100。 降低日志级别:
在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL = ‘ERROR’ 禁止cookie:
如果不是真的需要cookie,则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:COOKIES_ENABLED = False 禁止重试:
对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:RETRY_ENABLED = False 减少下载超时:
如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:DOWNLOAD_TIMEOUT = 10 超时时间为10s
请求传参
作用:帮助scrapy实现深度爬取
- 深度爬取:
- 爬取的数据没有在同一张页面中
- 深度爬取:
需求:爬取名称和简介,https://www.4567tv.tv/frim/index1.html
实现流程
传参:
yield scrapy.Request(url,callback,meta),将meta这个字典传递给callback
接收参数
response.meta
代码实现:
# -*- coding: utf-8 -*-
import scrapy class MvspidersSpider(scrapy.Spider):
name = 'mvspiders'
# allowed_domains = ['https://www.4567tv.tv/frim/index1.html']
start_urls = ['https://www.4567tv.tv/frim/index1.html'] url = "https://www.4567tv.tv/index.php/vod/show/id/5/page/%s.html"
pageNum = 1 def parse(self, response): li_list = response.xpath('/html/body/div[1]/div/div/div/div[2]/ul/li') for li in li_list:
a_href = li.xpath('./div/a/@href').extract_first()
url = 'https://www.4567tv.tv/' + a_href # 对详情页的url进行手动请求发送
# 请求传参:
# 参数meta是一个字典,字典会传递给callback
yield scrapy.Request(url,callback=self.infoparse) # 用于全栈的爬取
if self.pageNum < 5:
self.pageNum += 1
new_url = self.url%self.pageNum
# 递归调用自己
yield scrapy.Request(new_url,callback=self.parse) def infoparse(self,response): title = response.xpath("/html/body/div[1]/div/div/div/div[2]/h1/text()").extract_first() content = response.xpath('/html/body/div[1]/div/div/div/div[2]/p[5]/span[2]/text()').extract_first()items.py文件中的,它的作用就是为了定义你需要给上边文件中的item封装数据就必须要在这个类中添加对应的数据名,后边的scrapy.Field()就是内置字典类(dict)的一个别名,并没有提供额外的方法和属性,被用来基于类属性的方法来支持item生命语法。# -*- coding: utf-8 -*- # Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html import scrapy
class MvItem(scrapy.Item):
# define the fields for your item here like:
title = scrapy.Field()
content = scrapy.Field()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 #写入到文本文件中
import pymysql
from redis import Redis
class DuanziproPipeline(object):
fp = None
def open_spider(self,spider):
print('开始爬虫......')
self.fp = open('./duanzi.txt','w',encoding='utf-8')
#方法每被调用一次,参数item就是其接收到的一个item类型的对象
def process_item(self, item, spider):
# print(item)#item就是一个字典
self.fp.write(item['title']+':'+item['content']+'\n')
return item#可以将item提交给下一个即将被执行的管道类
def close_spider(self,spider):
self.fp.close()
print('爬虫结束!!!')
#将数据写入到mysql
class MysqlPipeLine(object):
conn = None
cursor = None
def open_spider(self,spider):
self.conn = pymysql.Connect(host='127.0.0.1',port=3306,user='root',password='222',db='spider',charset='utf8')
print(self.conn)
def process_item(self,item,spider):
sql = 'insert into duanzi values ("%s","%s")'%(item['title'],item['content'])
self.cursor = self.conn.cursor()
try:
self.cursor.execute(sql)
self.conn.commit()
except Exception as e:
print(e)
self.conn.rollback()
return item
def close_spider(self,spider):
self.cursor.close()
self.conn.close() #将数据写入到redis
class RedisPileLine(object):
conn = None
def open_spider(self,spider):
self.conn = Redis(host='127.0.0.1',port=6379)
print(self.conn)
def process_item(self,item,spider):
self.conn.lpush('duanziData',item)
return item
scrapy框架基于管道的持久化存储的更多相关文章
- scrapy框架基于CrawlSpider的全站数据爬取
引入 提问:如果想要通过爬虫程序去爬取”糗百“全站数据新闻数据的话,有几种实现方法? 方法一:基于Scrapy框架中的Spider的递归爬取进行实现(Request模块递归回调parse方法). 方法 ...
- 11.scrapy框架持久化存储
今日概要 基于终端指令的持久化存储 基于管道的持久化存储 今日详情 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的 ...
- scrapy框架持久化存储
基于终端指令的持久化存储 基于管道的持久化存储 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文 ...
- scrapy框架的持久化存储
一 . 基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作. 执行输出指定格式进行存 ...
- 11,scrapy框架持久化存储
今日总结 基于终端指令的持久化存储 基于管道的持久化存储 今日详情 1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的 ...
- scrapy 框架持久化存储
1.基于终端的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表或字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作. # 执行输出指定格式进行存储:将 ...
- 10 Scrapy框架持久化存储
一.基于终端指令的持久化存储 保证parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作. 执行输出指定格式进行存储:将爬取到的 ...
- scrapy框架之持久化操作
1.基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作. 执行输出指定格式进行存储: ...
- Scrapy持久化存储
基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作; 执行输出指定格式进行存储:将爬 ...
随机推荐
- Python 设计模式——单例模式
单例模式即确保类有且只有一个特定类型的对象,并提供全局访问点.因此通常用于日志记录.数据库操作.打印机后台处理程序等.这些程序在运行过程中只生成一个实例,避免对同一资源产生相互冲突的请求. 特点: 确 ...
- C# Wpf Shape类继承关系
Path派生于Shape namespace System.Windows.Shapes { public sealed class Path : Shape { // Path 派生于Shape } ...
- 制作3D小汽车游戏(上)
之前一段时间家里和公司的事太多,一直没有时间写博客,最近腾出一段时间,看了一遍官方的examples,收货颇多,想整理一点东西出来,又苦于没有好的东西,three写点东西真是太难了.好吧,今天郭先生就 ...
- C语言全排列
#include <stdio.h> int m=5; char s[]="12345"; void Swap(char *a, char *b)//元素交换 { ch ...
- Reset 对象属性
Input Reset 对象 在 HTML 表单中 标签每出现一次,一个 Reset 对象就会被创建. 当重置按钮被点击,包含它的表单中所有输入元素的值都重置为它们的默认值.默认值由 HTML val ...
- JS中var与let的区别
区别: var声明的变量,其作用域在该语句所在的函数之内,存在着变量提升的现象. let声明的变量,其作用域为该句所在的代码块内,不存在变量提升的问题. let相比于var,其不允许在相同作用域内,重 ...
- jdbc事务、连接池概念、c3p0、Driud、JDBC Template、DBUtils
JDBC 事务控制 什么是事务:一个包含多个步骤或者业务操作.如果这个业务或者多个步骤被事务管理,则这多个步骤要么同时成功,要么回滚(多个步骤同时执行失败),这多个步骤是一个整体,不可分割的. 操作: ...
- 数据库的查询(结合YGGL.sql)
(如有错误,欢迎指正!) 1.select 语句查询 (1)查询employees表员工部门号和性别,要求消除重复行. mysql> select distinct 员工部门号,性别 from ...
- Dockerfile文件说明
文件说明 此文件用于docker镜像文件的制作 基本结构 Dockerfile文件由行命令组成,以#开头注释行 一般分为四部分,基础镜像信息.维护者信息.镜像操作指令和容器启动执行指令. 例如 #De ...
- 【JavaWeb】Tomcat 使用
Tomcat 使用 基础概念 JavaWeb: JavaWeb:所有通过 Java 语言编写可以通过浏览器访问的程序的总称,它是是基于请求和响应来开发的: 请求:客户端给服务器发送数据,即 Reque ...