Scrapy的基础知识

一、Scrapy的作用

Scrapy应该算是Python宇宙中最常用的爬虫框架了,他是一个较完善的爬虫框架,同时也是一个比较难学的框架。Scrapy多应用于中型网站内容爬取。
Scrapy的优点:

  • 提供内置的HTTP缓存,加速本地开发
  • 自动节流调整机制,遵守 robots.txt 的设置
  • 自定义爬取深度
  • 执行HTTP基本认证,不需要明确保存状态
  • 自动填写表单
  • 自动设置请求中的引用头
  • 支持通过3xx响应重定向,也可以通过HTML元刷新
  • 避免被网站使用的 < noscript > meta 重新向困住,以检查没有JS支持的页面
  • 默认使用CSS选择器或XPath编写解析器
  • 可以用过splash或任何其他技术呈现JavaScript页面
  • 有强大的社区支持
  • 提供通用spider抓取常见格式

二、Scrapy框架认识

在这里插入图片描述
框架认识就不重复介绍,大致是这样,点这里。

  • Scrapy Engine(引擎):负责控制数据流。
  • Scheduler(调度器):接收爬取请求(Request)。
  • Downloader(下载器):获取页面数据,返回response。
  • Spider(蜘蛛):分析response,提取信息,返回Item类。
  • Item Pipeline(数据管道):处理Item类,数据信息清洗。
  • Downloader middlewares(下载器中间件):下载器和引擎中间的特定钩子,处理下载器传送给引擎的response,拓展scrapy功能。
  • Spider middlewares(Spider中间件):spider和引擎中间特定的钩子,处理输入spider的response和spider输出的item。使得scrapy的功能得到拓展。

三、Scrapy基本认识

1.文件目录结构
|——(工程名文件)
|   |———   _init_.py		'''包定义 '''
|   |———   	items.py		'''模型定义 '''
|   |———   pipelines.py		'''管道定义 '''
|   |———   settings.py		'''配置文件 '''
|   |———   spiders			'''蜘蛛(spider)文件夹 '''
|			|———	_init_.py	'''控制文件'''
|——scrapy.cfg				'''运行配置文件 '''
1.1、创建项目
scrapy startproject + ProjectName

运行该命令后即在当前目录下创建一个Scarpy工程,同时建立工程文件,文件结构如上所诉。这也是官方所推荐的scrapy最小运行框架。

1.2、创建spider
scrapy genspider + SpiderName + Start_Url

Spider 是 Scrapy 中很是重要也很是常见的一个功能,当我们创建一个scrapy项目是,一般都会先编写spider的逻辑。spider的作用是分析有scrapy引擎返回的爬网内容(即:Response),并决定是否继续生成新的请求(即:Request),最终返回Item。

1.3、启动爬网
scrapy crawl + SpiderName
2.数据模型Item

Item可以理解为一种数据容器,作为spider和pipeline的数据载体。spider对Response进行分析,提取具体的数据结构,并生成对应的item,然后有scrapy引擎传递给对应的pipeline进行处理。spider只有产生Item,才能进入下一环节,所以使用scrapy必须要先定义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 ChinanewsSrawlerItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    ''''我们尝试定义一个简单的item'''
    title = scrapy.Field()
    price = scrapy.Field()
    stock = scrapy.Field()
    date = scrapy.Field()
    data = scrapy.Field()
    #Field对象指明了每个字段的元数据(metadata),Field对象接受的值没有任何限制
3.蜘蛛——spider

spider类定义了如何爬取某些网站,包括爬取的动作以及如何从网页的内容中提取结构化数据(Item)

# -*- coding: utf-8 -*-
import scrapy
from bs4 import BeautifulSoup
from ..items import ChinanewsSrawlerItem

class ChinanewsSpider(scrapy.Spider):
    name = 'chinanews'
    allowed_domains = ['https://?????.com/']
    start_urls = ['https://www.?????.com/']

    def parse(self, response):
        rss = BeautifulSoup(response.body,'html.parser')
        for item in rss.findAll('item'):
            fee_item = ChinanewsSrawlerItem()
            fee_item['title'] = item.title
            fee_item['price'] = item.price
            fee_item['stock'] = item.stock
            fee_item['date'] = item.date
            fee_item['data'] = item.data
            yield fee_item
 ''' 
 yield关键字的作用,有点类似return,都是用于结果的返回。
 与return不同的是,yield返回的是一个迭代器。
 yield不会像return直接将当前执行的代码中断并返回,而是将当前可被返回的对象生成一个迭代器,\
 然后继续执行下一行代码
 '''

蜘蛛要从spider 基类中继承,当然也可以从其他 spider 的其他类继承。scrapy工具所创建的蜘蛛类有三个属性。

  • name : 蜘蛛的名称,用于识别。当一个项目中存在多个蜘蛛(spider)时,这个名称标识就尤为重要。
  • allowed_domains :只爬取该域内的内容,自动过滤链接到其他域的内容。
  • start_urls : 当蜘蛛被启动时,第一批请求的url。也就是从这个网址开始爬取。
'''
以下用两个parse函数实现“间接”爬取,用于对比上面的“直接”爬取
'''
# -*- coding: utf-8 -*-
import scrapy
from bs4 import BeautifulSoup
from ..items import ChinanewsSrawlerItem

class ChinanewsSpider(scrapy.Spider):
    name = 'chinanews'
    allowed_domains = ['https://?????.com/']
    start_urls = ['https://www.?????.com/']

    def parse(self, response):
     rss = BeautifulSoup(response.body,'html.parser')
     rss_links = set([item['data'] for i in rss.findAll('a')])
     for link in rss_links:
     	yield scrapy.Request(url = link , callback = self.parse_feed)

	def parse_feed(self,response):
        rss = BeautifulSoup(response.body,'html.parser')
        for item in rss.findAll('item'):
            fee_item = ChinanewsSrawlerItem()
            fee_item['title'] = item.title
            fee_item['price'] = item.price
            fee_item['stock'] = item.stock
            fee_item['date'] = item.date
            fee_item['data'] = item.data
            yield fee_item

parse是由spider基类中定义的一个空函数,函数体内只有一个pass关键字。我们可以将spider理解为一个抽象类,而parse则是所有子类中必须实现的“抽象方法”,因而每个spider中必须有一个能返回item的parse函数,scrapy的调度器会找到parse函数并调用它。
上诉parse函数是并没有返回fee_item的迭代器,而是返回一个request的迭代器,在request的构造函数中将parse_feed函数引用作为参数输入。当request对象被下载器发送到目标url并返回之后,就会自动调用parse_feed函数,并将返回的response作为参数传入,这样就形成了二次循环。
最后,当parse函数返回的是一个Item的枚举时,就标志着这个蜘蛛已经完成他需要处理的事情,scrapy引擎将引导工作流进行下一环节,即 “管道” 处理。

4.管道——Pipeline

“管道,”只接收Item并拖过Item执行一些行为,并决定此Item是否继续通过管道,他只负责输入和输出,并且输入输出的对象都是Item

# -*- 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

class ChinanewsSrawlerPipeline(object):
    def process_item(self, item, spider):
        return item

每个管道都需要调用 process_item 方法,而且这个方法必须返回一个Item对象或者是抛出一个 DropItem 异常。每个管道每次只能通过一个Item,意味着每次只能处理一个Item对象。
参数:
item :当前处理的Item对象
spider: 产生当前Item对象的spider

4.1、过滤性管道

面对那些没用的、重复的数据,我们可以通过建立一个过滤性管道来判断数据的有效性。在 process_item 处理函数中发起 scarapy.exceptions.DropItem 的异常就能完成丢弃动作,从而过滤掉垃圾数据。在此过程中并不用担心 process_item中发起的异常会使得工程中止。因为管道的每次处理是针对单个Item对象进行的。

'''
建立过滤管道,过滤'tital'中包含'游戏'信息的数据
'''
import scrapy
class BlockPipeline:
    def process_item(self, item, spider):
    	key = '游戏'
    	if key in item['tital']:
    		raise scrapy.exceptions.DropItem
        return item

'''
建立过滤管道,去重
'''
class DoplicatesPipeline:
	def _int_(self):
		self.du = set()
		
    def process_item(self, item, spider):
    	if self.du in item['tital']:
    		self.du.add(item['tital'])
    		raise scrapy.exceptions.DropItem
        return item
4.2、加工性管道

建立管道,对数据进行加工。
有如,运算求和,加权,格式化等。

4.3、储存性管道
import json

class jsonfeedPipeline(object):
	def _int_(self):
		self.json_file = open('feed.json','wt')
		self.json_file.write('[\n')
		
    def process_item(self, item, spider):
    	line = json.dumps(dict(item))+',\n'
    	self.json_file.write(line)
        return item

	def close_spider(self,spider):
		self.json_file.write('\n]')
		self.json_file.close()

如果要将所有的Item保存到一个json文件中,无需手工实现json的储存。

  • 全局性指定:在配置过程中,配置FEED_URI 和FEED_FORMAT 两个配置项,输出文件会保存到指定的位置(即:FFED_URI指定的位置)
  • 动态指定:在scrapy 命令中加入 -o +文件名称 ,即可在“根目录”下生成输出文件。
4.4、管道引用

管道的引用需要在settings.py文件中进行指定。即指定spider之后使用哪个管道,和使用顺序。
如果有两个不同的item,需要在管道中进行识别,防止出错。
在setings.py中找到下面的配置内容,该部分内容即指定管道的使用。
ITEM_PIPELINES 内要以全路径引用,可同时引用多个管道。
管道 “:”后面的数字表示优先级(即:执行顺序),数字越小优先级越高,数字的取值范围0 ~ 1000

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
#ITEM_PIPELINES = {
#    'chinanews_srawler.pipelines.ChinanewsSrawlerPipeline': 300,
#}

'''
配置
'''
ITEM_PIPELINES = {
    'chinanews_srawler.pipelines.BlockPipeline': 300,
    'chinanews_srawler.pipelines.jsonfeedPipeline': 301,
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值