前言
从这篇开始,带大家通过 Scrapy 框架来写爬虫,相比之前写的爬虫脚本,用上 Scrapy 才更像一个爬虫项目
Scrapy 是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中
其最初是为了 页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以应用在获取 API 所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫
Scrapy 使用了 Twisted'twɪstɪd异步网络框架来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求
简单来说,Scrapy 就是一个方便爬虫搭建的框架,那么下面来看看我们的第一个 Scrapy 项目(其实之前就有一篇爬取堆糖的文章已经用过了,这里完整的来一遍)
今天主要讲解如何建一个 Scrapy 项目,以及** Scrapy 的基本结构和配置**
正文
首先,安装 Scrapy 可以在 Pycharm 中安装,也可以手动下载或通过命令行安装,这里就举个直接在 Pycharm 中是如何安装的
首先在 settings 中点击 Project interpreter ,右侧就是你当前使用的 Python 解释器已经安装的包,这里我已经装过了,还提示可以升级到 Scrapy 1.6.0
然后我们点击最右侧的绿色加号,在上方搜索 Scrapy 可以看到下方就出现了 scrapy ,右侧是其最新的版本,点击底部 Install Package 就可以安装,稍等几分钟就能装好了
接着来看看如何创建一个 Scrapy 项目,如下图所示,打开 cmd 命令行,什么?不会打开...
按 “Win + r” 键运行,输入 cmd 回车即可
接着进入自己经常放代码的文件夹下,在这里输入
scrapy startproject myscrapy
然后回车,myscrapy 是你自己定的项目名,之所以我这里是
python3 -m scrapy startproject myscrapy
是因为一开始我同时装了 Python2 和 Python3,所以执行命令时要区别,所以没有同时装两个版本的各位,可以不用跟我一样加上 python3 -m
到这里 Scrapy 项目就创建好了,但是我们还需要一个主要放爬虫代码的.py文件,而在我们创建完一个 Scrapy 之后也提示我们,可以进入这个项目,创建一个爬虫文件
cd myscrapy
scrapy genspider first "bilibili.com"
first 是爬虫名,“bilibili.com” 是为了方便自定义的爬取网站的域名
这样一来完整的 Scrapy 项目就创建完了,下面是完整的项目结构
这里
- scrapy.cfg: 项目的配置文件
- myscrapy/: 该项目的python模块。之后您将在此加入代码
- myscrapy/spiders/: 放置spider代码的目录
- myscrapy/items.py: 项目中的item文件
- myscrapy/pipelines.py: 项目中的pipelines管道文件
- myscrapy/middlewares.py: 项目中的middlewares中间件文件
- myscrapy/settings.py: 项目的设置文件
还有一点是,Scrapy 的命令可不止 startproject
和 genspider
,更多的可以直接在命令行中输入
scrapy
回车后就可以看见,而需要注意的是,没有进入项目文件下,与进入项目文件下可执行的 Scrapy 命令有点不同
没有进入项目文件夹 进入项目文件夹下具体作用大家可以问问度娘~我就不再多说了(谁说我不知道了,这些小知识得自己搜过印象才深嘛)
项目结构以及如何创建 Scrapy 项目就先到这儿,下面我们来看看 Scrapy 到底有哪些五脏六腑
first.py
首先,我们的 first.py 文件,之后我们要写的爬虫主体代码就在此编写,可以看到生成的文件中,有一个 FirstSpider 类,继承着 scrapy.Spider
name
是爬虫名,之后运行爬虫的时候,就要用到这个 name
allowed_domains
包含了spider允许爬取的域名(domain)的列表
start_urls
初始URL元祖/列表
parse
方法,当请求url返回网页没有指定回调函数时,默认的Request对象回调函数。用来处理网页返回的response,以及生成Item或者Request对象
# -*- coding: utf-8 -*-
import scrapy
class FirstSpider(scrapy.Spider):
name = 'first'
allowed_domains = ['bilibili.com']
start_urls = ['http://bilibili.com/']
def parse(self, response):
pass
items.py
Item 中定义结构化数据字段,用来保存爬取到的数据
可以通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field的类属性来定义一个Item
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class MyscrapyItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field()
middlewares.py
中间件文件中定义了两个中间件类 MyscrapySpiderMiddleware
和 MyscrapyDownloaderMiddleware
下载器中间件是介于 Scrapy 的request/response处理的钩子框架。 是用于全局修改Scrapy request和response的一个轻量、底层的系统
要使用下载器中间件,就需要激活,要激活下载器中间件组件,将其加入到 DOWNLOADER_MIDDLEWARES
设置中。 该设置是一个字典(dict),键为中间件类的路径,值为其中间件的顺序(order),需在 settings,py 中配置
当然也可以自己编写中间件
将其注释解掉即可
#SPIDER_MIDDLEWARES = {
# 'myscrapy.middlewares.MyscrapySpiderMiddleware': 543,
#}
#DOWNLOADER_MIDDLEWARES = {
# 'myscrapy.middlewares.MyscrapyDownloaderMiddleware': 543,
#}
# -*- coding: utf-8 -*-
# Define here the models for your spider middleware
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/spider-middleware.html
from scrapy import signals
class MyscrapySpiderMiddleware(object):
# Not all methods need to be defined. If a method is not defined,
# scrapy acts as if the spider middleware does not modify the
# passed objects.
@classmethod
def from_crawler(cls, crawler):
# This method is used by Scrapy to create your spiders.
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
return s
def process_spider_input(self, response, spider):
# Called for each response that goes through the spider
# middleware and into the spider.
# Should return None or raise an exception.
return None
def process_spider_output(self, response, result, spider):
# Called with the results returned from the Spider, after
# it has processed the response.
# Must return an iterable of Request, dict or Item objects.
for i in result:
yield i
def process_spider_exception(self, response, exception, spider):
# Called when a spider or process_spider_input() method
# (from other spider middleware) raises an exception.
# Should return either None or an iterable of Response, dict
# or Item objects.
pass
def process_start_requests(self, start_requests, spider):
# Called with the start requests of the spider, and works
# similarly to the process_spider_output() method, except
# that it doesn’t have a response associated.
# Must return only requests (not items).
for r in start_requests:
yield r
def spider_opened(self, spider):
spider.logger.info('Spider opened: %s' % spider.name)
class MyscrapyDownloaderMiddleware(object):
# Not all methods need to be defined. If a method is not defined,
# scrapy acts as if the downloader middleware does not modify the
# passed objects.
@classmethod
def from_crawler(cls, crawler):
# This method is used by Scrapy to create your spiders.
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
return s
def process_request(self, request, spider):
# Called for each request that goes through the downloader
# middleware.
# Must either:
# - return None: continue processing this request
# - or return a Response object
# - or return a Request object
# - or raise IgnoreRequest: process_exception() methods of
# installed downloader middleware will be called
return None
def process_response(self, request, response, spider):
# Called with the response returned from the downloader.
# Must either;
# - return a Response object
# - return a Request object
# - or raise IgnoreRequest
return response
def process_exception(self, request, exception, spider):
# Called when a download handler or a process_request()
# (from other downloader middleware) raises an exception.
# Must either:
# - return None: continue processing this exception
# - return a Response object: stops process_exception() chain
# - return a Request object: stops process_exception() chain
pass
def spider_opened(self, spider):
spider.logger.info('Spider opened: %s' % spider.name)
pipelines.py
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。
每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
以下是item pipeline的一些典型应用:
- 清理HTML数据
- 验证爬取的数据(检查item包含某些字段)
- 查重(并丢弃)
- 将爬取结果保存到数据库中
同样要使用 pipeline ,也需要在 settings.py 中启用
#ITEM_PIPELINES = {
# 'myscrapy.pipelines.MyscrapyPipeline': 300,
#}
# -*- coding: utf-8 -*-
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
class MyscrapyPipeline(object):
def process_item(self, item, spider):
return item
settings.py
Scrapy设置(settings)提供了定制Scrapy组件的方法。可以控制包括核心(core),插件(extension),pipeline及spider组件。比如 设置Json Pipeliine、LOG_LEVEL等
结尾
关于 Scrapy 项目的基本点就讲到这里,另外公众号后台回复【scrapy课件】,有一个关于 Scrapy 的课件等着你哦,对于新手来说基本知识点都涵盖在内了,且易于理解
print('微信公众号搜索 "猿狮的单身日常" ,Java技术升级、虫师修炼,我们 不见不散!')
print('也可以扫下方二维码哦~')
猿狮的单身日常
网友评论