python爬虫之九_scrapy框架入门

根据b站爬虫教程整理

一 架构与流程

1.1 架构

在这里插入图片描述
模块:

  1. Engine:Scrapy框架的核心;负责在各部件之间通信、传递数据;
  2. Spider:由用户自定义,发送目标URL、解析目标网页;请求的增强由Middleware实现;
  3. Scheduler:由用户自定义,接收引擎传递的请求后决定请求顺序、处理重复URL;
  4. Download:下载网页、数据;Download功能增强在Middleware中实现;
  5. Pipeline:用户自定义,保存目标数据到数据库或文件;

1.2 流程

在这里插入图片描述

  1. Spider创建Request对象,发送给引擎;
  2. 引擎将Request对象转发到调度器,调度器保存Request对象到队列中;
  3. 引擎从调度器队列中获取Request对象;
  4. 引擎将Request对象发送给下载器;
  5. 下载器发送请求、接收响应、创建Reponse对象,发送给引擎;
  6. 引擎将Reponse对象转发给Spider;
  7. Spider解析Response对象,获取数据,发送给引擎;
  8. 引擎将数据转发给Pipelines;Pipeline将数据保存到数据库或文件;

各模块之间的中间件Middleware可以对传输的对象或数据进行加工处理。

引擎的作用在于:各模块不用考虑相互的功能,直接用return返回结果、直接把其他模块结果作为参数使用,由引擎实现接收和转发。

二 安装与创建scrapy项目

2.1 安装scrapy框架

安装scrapy库:

pip install scrapy

安装pypiwin32库:

scrapy异步操作依赖于twisted库;twisted库在win平台上运行时需要win32支持
pip install pypiwin32

注意:
python第三方库默认安装目录为:\python\Scripts路径,需加入环境变量Path。

2.2 创建、启动scrapy项目

  1. pycharm创建一个纯python项目;
  2. 命令行中创建sracpy项目:
scrapy startproject [项目名]
  1. 命令行创建spider文件:
scrapy genspider [文件名] [爬虫目标域名]

需要先cd到 项目/spiders 目录
  1. 命令行/pycharm 启动scrapy项目:
法一:命令行启动
scrapy crawl [爬虫名字]

需要先cd到spider目录

法二:通过py文件调用命令行,直接在pycharm中启动
1)创建start.py
from scrapy import cmdline
cmdline.execute(["scrapy","crawl","[爬虫名]"])
2)运行start.py

注意:
1.scrapy项目、scrapy目录,必须通过命令行创建
2.scrapy项目,必须通过命令行启动

2.3 项目结构

  1. scrapy.cfg:项目配置文件;
  2. spider:爬虫代码目录;
  3. iterm.py:存储爬取数据的模型;
  4. middlewares.py:用于定义下载器中间件、爬虫中间件;
  5. pipelines:存储爬取的数据;
  6. settings:爬虫下载设置,请求头、cookie…

2.4 配置爬虫

settings配置爬虫

ROBOTSTXT_OBEY = False 								# 将值设置为False
DEFAULT_REQUEST_HEADERS={'User-Agent':'...',...}	# 默认请求头

DOWNLOAD_DELAY										# 爬虫延迟

三 模块实现

以爬取糗事百科为例:

3.1 spider 数据解析

3.1.1 创建

自定义爬虫类,继承scrapy.Spider类,必须实现以下方法和属性:

属性:

  1. name:爬虫的名字;
  2. allowed_domains:待爬取目标的域名;
  3. start_urls:初始URL;

方法:

  1. parse:以爬虫返回的Response为参数,进行解析;
3.1.2 调用

parse方法是spider类的核心,负责发送请求、解析数据、传输数据。parse方法由scrapy框架自动调用。

  1. 发送请求:创建Request对象,通过yield将Request对象发送给引擎;
  2. 解析数据:接收Response对象,使用HtmlReposne对象的xpath、css方法进行解析;
  3. 传输数据:返回解析的数据,由scrapy框架自动接收并传输到pipelines;

parse返回请求、数据的操作有两种:

  1. return语句:直接返回数据;
  2. yield语句:返回迭代器;【推荐】

另外,parse可以以dict方式返回数据,也可以封装为item对象返回。推荐的是后一种。

3.1.3 解析数据

Response为HtmlResponse对象,可执行xpath、css方法提取数据,提取结果为Selector、SelectorList类型,进一步通过get、getall提取处字符串

属性:

  1. body
  2. text(解码后的)

方法:

  1. xpath:使用xpath规则解析;
  2. css:使用css选择器解析,
  3. 不支持直接使用bs4进行解析,只能先获取返回数据再bs4解析

xpath方法:
返回值为selector或selectorList;当只存在一个符合xpath规则的结果时返回selector,有多个时返回selectorList;

selector对象:

  1. 继承自List类,可遍历;
  2. 有xpath、css、re、extract方法,可继续解析;
  3. 有get、getall方法,可获取HTML标签中的文本信息;get方法获取第一个标签下的文本返回为string,getall方法获取所有标签下的文本返回为list;

scrapy包的xpath方法和lxml包的xpath方法语法一致吗?API有差异

  1. lxml中解析后用text属性可得标签元素内的文本,response对象通过get获取;而且lxml中获取的不包含标签本身,而get获取的包含。

3.2 item 数据封装

spider将解析后的数据封装为item后传给引擎,引擎进一步传给pipelines,然后进行存储;

item为自定义类,继承自scrapy.Item,用于封装数据。

#定义Item类
class MyItem(scrapy.Item):
	author=scrapy.Field()
	content=scrapy.Field()

#Item类属性赋值
item=MyItem(author='abc')
item['content']='123'

注意:

  1. Item对象属性赋值时可以像字典一样使用;
  2. Item类比字典的好处在于结构更固定;
  3. Item类不能出现复杂嵌套,也就是说item相当于一个字典,而且每个字段值都只能是简单类型,不能是对象;

3.3 pipelines 数据存储

3.3.1 创建、调用
  1. 自定义pipelines类,直接继承自object对象;
  2. setting中通过ITEM_PIPELINES指定pipelines类,scrapy框架自动创建pipelines对象并调用方法。【类似与spring中IOC】
3.3.2 方法

pipelines中可定义以下三种方法,条件触发时,scrapy框架自动调用:

  1. open_spider:爬虫启动时调用;可用于打开文件(也可以在pipelines的构造函数中打开);
  2. process_item(self,item,spider):spider将item传给pipelines时调用;用于接收和写入数据;【json.dumps用于将dict转为json】
  3. close_spider:爬虫结束时调用;可用于关闭文件。
class MyPipeline(object):
	def __init__(self):
		self.fp=open("abc.txt",'w',encoding='utf-8')
	def open_spider(self,spider):
		print('爬虫开始了...')
	def process_item(self,item,spider):
		item_json=json.dumps(dict(item),ensure_ascii=False)
		self.fp.write(item_json+'\n')
		return item
	def close_spider(self,spider):
		self.fp.close()
		print('爬虫结束了...')

注意:
从下载image、file来看,pipelines是先对item处理,然后才存储数据。普通的item直接通过pipeline中的方法即可写入文件,而ImagesPipeline、FilesPipeline会先根据item中的image_urls、file_urls字段下载文件。

3.3.3 存储为json文件

游戏脚本中的python_序列化、反序列化、json配置文件

Scrapy包提供JsonItemExporter、JsonLinesItemExporter方法用于将item对象序列化为json文件。不需要先转为dict,再用json.dump()。

注意:
只有存为item才能使用这两个API,而存为item就要求结构中不存在嵌套的,所以其实和json差不多

打算把数据存入mongodb,数据有一层嵌套,目前用自定义对象+json.dump实现;
报错:ERROR: Spider must return Request, BaseItem, dict or None,

JsonItemExporter、JsonLinesItemExporter:

  1. JsonItemExporter、JsonLinesItemExporter均以二进制方式写入数据,因此文件要以二进制方式(‘wb’)打开;
  2. JsonItemExporter:每次将item数据添加到内存中,最后同一写入磁盘;整个文件为一整个Json格式的List,每个item作为List中一项;
  3. JsonLinesItemExporter:每次将item数据作为一行写入磁盘;整个文件像多个Json文件合并,整体不符合Json格式,每个item符合Json格式
from scrapy.exporters import JsonItemExporter

fout=open('test.json','wb')
exporter=JsonItemExporter(fout,ensure_ascii=False,encoding='utf-8')
exporter.start_exporting()
exporter.export_item(item)
exporter.finish_exporting()
fout.close()
from scrapy.exporters import JsonLinesItemExporter

fout=open('test.json','wb')
exporter=JsonLinesItemExporter(fout,ensure_ascii=False,encoding='utf-8')
exporter.export_item(item)
fout.close()

补充:
yield:[原理见python 生成器]
https://www.liaoxuefeng.com/wiki/897692888725344/923029685138624
yeild功能上就是向引擎发送数据(对象)
引擎根据收到的数据的类型执行对应的操作
如果是scrapy.Item对象,则将对象传递给pipelines.py进行处理
如果是scrapy.Request对象,则会获取该对象指向的链接,并在请求完成后调用该对象的回调函数
https://www.jianshu.com/p/7c1a084853d8

P108Request和Response对象
Request对象:
属性
url:request对象发送请求的URL
callback:下载器下载完成后执行的回调函数,即解析函数
method:默认get,若要用post改用formrequest对象
headers:请求头,字典类型
meta:在不同请求或响应间传递数据,字典类型
encoding:默认utf-8
dont_filter:表示不由调度器过滤,默认调度器不会向相同的URL发送请求,若要重复请求则设置为false(如下载错误,需重新下载时)
errback:发送错误时执行的函数

from  scrapy import  Request
yeild Request(url,meta,callback='parse')

https://www.cnblogs.com/themost/p/7044673.html?utm_source=itdadao&utm_medium=referral

Response对象
1.meta:从其他请求传过滤的meta属性,可用于保持多个请求之间的数据连接
2.encoding:将返回当前字符串编码和解码的格式
3.text:网页返回的数据,scarpy已解码为unicode字符串
4.body:网页返回的数据,未经过解码,未bytes字符串,【有时scrapy解码可能不对需要自己对bytes解码】
【网络和硬盘之间通信的数据是bytes类型,即编码后的数据】
5.xpath:xpath选择器
6.css:css选择器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值