Scrapy实训小项目(详细讲解)

前言:

我们大多数基于requests或aiohttp来实现爬虫的整个逻辑的。可以发现,在这个过程中,我们需要实现爬虫相关的所有操作,例如爬取逻辑、异常处理、数据解析、数据存储等,但其实这些步骤很多是通用或者重复的。既然如此,我们完全可用把这些步骤的逻辑抽离出来,把其中通用的功能做成一个个基础的组件

架构设计(理解)

架构

在这里插入图片描述

Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。

Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。

Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,

Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器).

Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。

Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。

Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)

数据流动
  1. 引擎打开一个网站(open a domain),找到处理该网站的Spider并向该spider请求第一个要爬取的URL(s)。
  2. 引擎从Spider中获取到第一个要爬取的URL并在调度器(Scheduler )以Request调度。
  3. 引擎向调度器请求下一个要爬取的URL。
  4. 调度器返回下一个要爬取的URL给引擎,引擎将URL通过下载中间件(请求( request)方向)转发给下载器(Downloader )。
  5. 一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件(返回( response)方向)发送给引擎。
  6. 引擎从下载器中接收到Response并通过Spider中间件(输入方向)发送给Spider处理。
  7. Spider处理Response并返回爬取到的Item及(跟进的)新的Request给引擎。
  8. 引擎将(Spider返回的)爬取到的Item给Item Pipeline,将(Spider返回的)Request给调度器。
  9. (从第二步)重复直到调度器中没有更多地request,引擎关闭该网站。

从整体上来看,各个组件都只专注于一个功能,组件和组件之间的耦合度非常低,也非常容易扩展。再由引擎将各个组件组合起来,使得各个组件各司其职,互相配合,共同完成爬取工作。另外加上Scrapy对异步处理的支持,Scrapy还可以最大限度地利用网络带宽,提高数据爬取和处理的效率

Scrapy框架的使用(重点)

安装Scrapy

pip install Scrapy

安装好Scrapy框架之后,我们首先来了解一下Scrapy爬虫的制作过程:
制作 Scrapy 爬虫 一共需要4步:

  1. 新建项目 (scrapy star tproject xxx):新建一个新的爬虫项目
  2. 明确目标 (编写items.py):明确你想要抓取的目标
  3. 制作爬虫 (spiders/xxspider .py):制作爬虫开始爬取网页
  4. 存储内容 (pipelines.py):设计管道存储爬取内容


实训一:(百度爬虫)

升级 pip 版本
pip install --upgrade pip
安装Scrapy
pip install Scrapy
1、创建一个工程
scrapy star tproject f r istProject

在这里插入图片描述

这些文件分别是:

spiders ----------------------------------------------------# 放置Spiders的文件夹
item.py -------------------------------------# Items的定义,定义爬取的数据结构
middleware.py ------------------# Middlewares的定义,定义爬取时的中间件
pipelines.py -----------------------------------# Pipelines的定义,定义数据管道
settings.py -------------------------------------------------------------------# 配置文件

2、创建Spider
cd fristProject
scrapy genspider baidu baidu.com

(先进入对应的目录,再创建Spider)

  • 执行完毕后,spiders文件夹中多了一个baidu.py,它就是刚刚创建的Spider
  • 这个BaiduSpider就是刚才命令行自动创建的Spider,它继承了scrapy的Spider类
  • BaiduSpider有3个属性:
    1、name:每个项目唯一的名字,用来区分不同的Spider
    2、allowd_domains:允许爬取的域名,如果初始或后续的请求链接不是这个域名下的,则请求链接会被过滤掉
    3、star t_ur l:包含了Spider在启动时爬取的URL列表,初始请求是由它来定义的
  • BaiduSpuder有1个方法:
    1、parse():在默认情况下,star t_ur ls里面的链接构成的请求完成下载后,parse()方法就会被调用,返回的响应就会作为唯一的参数传递给parse()方法。该方法负责解析返回的响应、提取数据或者进一步生成要处理的请求,相当于回调函数

我们可以通过修改baidu.py来定义爬虫逻辑

baidu.py

import scrapy
class BaiduSpider(scrapy.Spider ):
# 爬虫名的唯一标识
name = 'baidu'
# 允许的域名
# ps:但是有一个问题:对于star t_ur ls里的起始爬取页面,它是不会过滤的,它的作用是过滤首页之后的页面-----待验证
allowed_domains = ['baidu.com']
# 起始的ur l列表:只可以存储ur l
# 作用:列表中存储的ur l都会被进行get请求的发送
star t_ur ls = ['https://baidu.com/']
# 数据解析
# parse方法调用的次数完全取决于请求的次数
# 参数response:表示的就是服务器返回的响应对象
def parse(self, response):
# 输出响应
print(response)

在这里插入图片描述

4、修改set t ings.py
  • settings.py是整个项目的设置文件
  • Scrapy项目允许问我们自定义所有Scrapy组件的行为,其中就是通过修改settings.py来完成
  • 我们将会在接下来的学习中一步一步的了解Scrapy组件的设置
    在这里插入图片描述
  • Scrapy框架可以客制化的设置有很多,我们从中选3个用得比较多的基本设置开始:

1、 禁止robots:

ROBOTSTXT_OBEY = False

2、指定日志类型:

LOG_LEVEL = 'ERROR'

3、UA伪装

UA伪装: USER_AGENT = ' '

在这里插入图片描述

  • 执行工程后,默认会输出工程所有的日志信息(默认 LOG_LEVEL=‘INFO’ )。为了避免输出过多的日志信息,我们将日志等级提升到ERROR
4、执行爬虫
scrapy crawl baidu

在这里插入图片描述

实训二(段子网爬虫)

链接:https://duanzixing.com/


【知识点一】:

  • 在scrapy框架中,GET请求发送的方式是:
# callback指定解析函数,用于解析数据
# GET请求
yield scrapy.Request(url, callback)
# # 完整版
# yield scrapy.Request(url, headers.cookies, meta, callback=self.parse_response)
  • POST请求的方式是:
# POST请求
yield scrapy.FormRequest(ur l,callback,formdata)
# # 完整版
# yield scrapy.FormRequest(ur l, headers. cookies, formdata, meta,callback=self.parse_response)

在 scrapy.Request(url, callback) 还有一个必须用到的参数callback,它默认是 self.parse() ,代表回调函数,代表将Request执行请求后得到的Response对象调用到该回调函数中,这也是为什么我们能在 self.parse() 进行数据解析的原因;


【知识点二】:

在Scrapy框架中,已经默认为我们实现一个 star t_requests() 方法:

def star t_requests(self):
	for u in self.start_urls:
		yield Request(u,callback=self.parse)
  • 我们还发现这是一个生成器,返回的所有Request都会作为初始Request加入调度队列
    因此,如果我们想要自定义初始请求,只需要重新 star t_requests() 方法就可以。比如说我们改成POST请求:
def star t_requests(self):
	for u in self.star t_ur ls:
		yield scrapy.FormRequest(ur l=u,callback=self.parse)

我们开始正式的段子网爬虫实训:
1、创建一个工程
scrapy startproject duanziProject
2、定义item(items.py)
import scrapy

class DuanziprojectItem(scrapy.Item):
	# define the fields for your item here like:
	# 标题
	title = scrapy.Field()
	# 作者
	author = scrapy.Field()
	# 时间
	re_time = scrapy.Field()
	# 正文
	content = scrapy.Field()

3、创建爬虫
cd duanziProject
scrapy genspider duanzi duanzixing.com

duanzi.py


import scrapy
from duanziProject.items import DuanziprojectItem
class DuanziSpider(scrapy.Spider ):

	name = 'duanzi'
	# allowed_domains = ['https://duanzixing.com/']
	star t_ur ls = ['https://duanzixing.com//']
	
	# 通用的url模板
	base_url = 'https://duanzixing.com/page/{}/'
	# 页码(从第二页开始)
	page = 2
	# 重写父类方法:这个是该方法的原始实现
	# 这里其实和原本一样
	def start_requests(self):
		for u in self.star t_urls:
			yield scrapy.Request(url=u, callback=self.parse)
			
	# 将段子网中所有页码对应的数据进行爬取
	def parse(self, response):
		# 找到所有的ar ticle
		article_ls = response.xpath('/html/body/section/div/div/ar ticle')
		# 遍历
		for article in article_ls:
			# 实例化item
			item = DuanziprojectItem()
			# 标题
			item['title'] = ar ticle.xpath('./header /h2/a/text()').ext ract_first()
			# 作者
			item['author '] = ar ticle.xpath('./p[1]/span[1]/text()').ext ract_first()
			# 时间
			item[' re_time'] = ar ticle.xpath('./p[1]/time/text()').ext ract_first()
			# 正文
			item['content'] = ar ticle.xpath('./p[2]/text()').ext ract_first()
			# 传递给管道
		yield item
		
	# 对新的页面发起请求
	# 直到递归条件结束
	if self.page < 11: # 结束递归的条件
		print(self.page)
		new_url = self.base_url.format(self.page) # 其他页码对应的完整url
		self.page += 1
		# 对新的页码对应的ur l进行请求发送(手动请求GET发送)
		yield scrapy.Request(ur l=new_url, callback=self.parse)

我们在 self.parse() 后面手动设置了一个对新的ur l发起的请求,由于回调函数还是 self.parse() ,当递归条件未结束时,Scrapy爬虫会一直重复调用 self.parse() ,此时 self.parse() 兼顾了数据解析和发送请求的功能


4、定义Piplines

from itemadapter import ItemAdapter
import json

class DuanziprojectPipeline:
	# 初始化
	def __init__(self):
		# 文件
		self.fp = None
	
	def process_item(self, item, spider ):
		# 提示
		print(f'JSON正在写入{item["title"]}')
		# 写入文件
		json.dump(str(item), self.fp, ensure_ascii=False, indent=4)
		# 伪装json格式
		self.fp.wr ite( " ,\n" )
		# 将item存储到本文文件
		return item

	# open_spider
	def open_spider (self, spider ):
		print('使用json方式的open_spider ()!')
		self.fp = open('./duanzi.json', 'wt', encoding='utf-8')
		# 伪装json格式
		self.fp.wr ite('[\n')

	# close_spider
	def close_spider (self, spider ):
		print('结束使用json方式的close_spider ()')
		self.fp.wr ite(']')
		self.fp.close()
		

5、修改settings.py
  1. 禁止robots:
ROBOTSTXT_OBEY = False
  1. 指定日志类型:
 LOG_LEVEL = 'ERROR'
  1. UA伪装:
USER_AGENT = ' '
  1. 开启管道:
ITEM_PIPELINES = {}

6、执行爬虫
scrapy crawl duanzi

实训三(远鉴字幕组电影详情页爬虫)

链接:https://ifenpaidy.com/blog

待完成

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值