Scrapy框架01【入门操作,Scrapy Shell操作,Spider类】
常用命令集锦
scrapy startproject mySpider # 新建项目
scrapy genspider xxx "xxx.cn" # 创建爬虫的文件 不能与项目同名
scrapy crawl xxx # 爬虫文件当中的name 对应的变量 运行爬虫
response.body # 将输出response的包体
response.headers # 可以看到response的包头。
response.url # 请求的url
url response.status # 状态码
scrapy crawl xxx --nolog # 爬虫文件当中的name 对应的变量 运行爬虫 不打印Log信息
# 三种导入setting文件的方法
from scrapy.utils.project import get_project_settings
# IMAGES_STORE = get_project_settings().get('IMAGES_STORE')
from Itcast.settings import IMAGES_STORE
from scrapy.conf import settings
配置
ROBOTSTXT_OBEY = True # 开启robots协议
ROBOTSTXT_OBEY = False # 关闭robots协议
ITEM_PIPELINES = {
'mySpider.pipelines.MyspiderPipeline': 300, # 管道设置 键为:管道类 值为:权重 从小到大保存(值小的先保存 )
}
setting.py 设置抓取间隔
BOT_NAME = 'zhihu'
SPIDER_MODULES = ['zhihu.spiders']
NEWSPIDER_MODULE = 'zhihu.spiders'
DOWNLOAD_DELAY = 0.25 #设置下载间隔为250ms
方法
item['info'] = li.xpath("./p/text()").extract()[0] # python3中获取内容 在python2中也有将unicode转为utf-8的作用
python2转码问题解决方案
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
Scrapy 框架
-
Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛。
-
框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便。
-
Scrapy 使用了 Twisted
['twɪstɪd](其主要对手是Tornado)异步网络框架来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求。
Scrapy架构图(绿线是数据流向):

-
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,并进行进行后期处理(详细分析、过滤、存储等)的地方.- process_item() PS:该函数必须返回item实例,供后续管道使用
-
Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。 -
Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)
Scrapy的运作流程
代码写好,程序开始运行...
-
引擎:Hi!Spider, 你要处理哪一个网站? -
Spider:老大要我处理xxxx.com。 -
引擎:你把第一个需要处理的URL给我吧。 -
Spider:给你,第一个URL是xxxxxxx.com。 -
引擎:Hi!调度器,我这有request请求你帮我排序入队一下。 -
调度器:好的,正在处理你等一下。 -
引擎:Hi!调度器,把你处理好的request请求给我。 -
调度器:给你,这是我处理好的request -
引擎:Hi!下载器,你按照老大的下载中间件的设置帮我下载一下这个request请求 -
下载器:好的!给你,这是下载好的东西。(如果失败:sorry,这个request下载失败了。然后引擎告诉调度器,这个request下载失败了,你记录一下,我们待会儿再下载) -
引擎:Hi!Spider,这是下载好的东西,并且已经按照老大的下载中间件处理过了,你自己处理一下(注意!这儿responses默认是交给def parse()这个函数处理的) -
Spider:(处理完毕数据之后对于需要跟进的URL),Hi!引擎,我这里有两个结果,这个是我需要跟进的URL,还有这个是我获取到的Item数据。 -
引擎:Hi !管道我这儿有个item你帮我处理一下!调度器!这是需要跟进URL你帮我处理下。然后从第四步开始循环,直到获取完老大需要全部信息。 -
管道``调度器:好的,现在就做!
注意!只有当调度器中不存在任何request了,整个程序才会停止,(也就是说,对于下载失败的URL,Scrapy也会重新下载。)
制作 Scrapy 爬虫 一共需要4步:
- 新建项目 (scrapy startproject xxx):新建一个新的爬虫项目
- 明确目标 (编写items.py):明确你想要抓取的目标
- 制作爬虫 (spiders/xxspider.py):制作爬虫开始爬取网页
- 存储内容 (pipelines.py):设计管道存储爬取内容
Scrapy的安装介绍
Scrapy框架官方网址:http://doc.scrapy.org/en/latest
Scrapy中文维护站点:http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html
Windows 安装方式
- Python 2 / 3
- 升级pip版本:
-
pip install --upgrade pip
- 通过pip 安装 Scrapy 框架
-
pip install Scrapy
Ubuntu 需要9.10或以上版本安装方式
- Python 2 / 3
- 安装非Python的依赖
sudo apt-get install python-dev python-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev - 通过pip 安装 Scrapy 框架
sudo pip install scrapy
具体Scrapy安装流程参考:http://doc.scrapy.org/en/latest/intro/install.html#intro-install-platform-notes 里面有各个平台的安装方法
爬虫的开发流程

一. 新建项目(scrapy startproject)
- 在开始爬取之前,必须创建一个新的Scrapy项目。进入自定义的项目目录中,运行下列命令:
scrapy startproject mySpider
- 其中, mySpider 为项目名称,可以看到将会创建一个 mySpider 文件夹,目录结构大致如下:
下面来简单介绍一下各个主要文件的作用:
scrapy.cfg :项目的配置文件 mySpider/ :项目的Python模块,将会从这里引用代码 mySpider/items.py :项目的目标文件 mySpider/pipelines.py :项目的管道文件 mySpider/settings.py :项目的设置文件 mySpider/spiders/ :存储爬虫代码目录
二、明确目标(mySpider/items.py)
我们打算抓取:http://www.XXXX.cn/channel/网站里的所有xxx.xxx.xxx信息
-
打开mySpider目录下的items.py
-
Item 定义结构化数据字段,用来保存爬取到的数据,有点像Python中的dict,但是提供了一些额外的保护减少错误。
-
可以通过创建一个 scrapy.Item 类, 并且定义类型为 scrapy.Field的类属性来定义一个Item。
-
接下来,创建一个ItcastItem 类,和构建item模型(model)。
- 模板实例存储数据比字典更安全
三、制作爬虫 (spiders/xxxSpider.py)
爬虫功能要分两步:
1. 爬数据
- 在当前目录下输入命令,将在
mySpider/spider目录下创建一个名为xxx的爬虫,并指定爬取域的范围:
scrapy genspider xxx "xxx.cn"
其实也可以由我们自行创建xxx.py并编写上面的代码,只不过使用命令可以免去编写固定代码的麻烦
要建立一个Spider, 你必须用scrapy.Spider类创建一个子类,并确定了三个强制的属性 和 一个方法。
-
name = "":这个爬虫的识别名称,必须是唯一的,在不同的爬虫必须定义不同的名字。 -
allow_domains = []是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页,不存在的URL会被忽略。 -
start_urls = ():爬取的URL元祖/列表。爬虫从这里开始抓取数据,所以,第一次下载的数据将会从这些urls开始。其他子URL将会从这些起始URL中继承性生成。 -
parse(self, response):解析的方法,每个初始URL完成下载后将被调用,调用的时候传入从每一个URL传回的Response对象来作为唯一参数,主要作用如下:- 负责解析返回的网页数据(response.body),提取结构化数据(生成item)
- 生成需要下一页的URL请求。
将start_urls的值修改为需要爬取的第一个url
start_urls = ("http://www.baidu.com",)
修改parse()方法
然后运行一下看看,在mySpider目录下执行:
scrapy crawl xxx
2. 取数据
利用scrapy封装好的response.xpath() 用法和xpath的方法一样
3.保存数据
scrapy保存信息的最简单的方法主要有四种,-o 输出指定格式的文件,,命令如下:
# json格式,默认为Unicode编码 scrapy crawl xxx -o teachers.json # json lines格式,默认为Unicode编码 scrapy crawl xxx -o teachers.jsonl # csv 逗号表达式,可用Excel打开 scrapy crawl xxx -o teachers.csv # xml格式 scrapy crawl xxx -o teachers.xml
案例
# -*- coding: utf-8 -*- import scrapy import time from Tencent.items import TencentItem class TencentSpider(scrapy.Spider): name = 'tencent' allowed_domains = ['tencent.com'] start_urls = ['http://hr.tencent.com/position.php'] def parse(self, response): host = "http://hr.tencent.com/" # 提取数据 有效数据及下一页的url tr_list = response.xpath("//tr[contains(@class, 'odd')]|//tr[contains(@class, 'even')]") for tr in tr_list: # 创建实例模型 item = TencentItem() # 遍历每个信息获取相关数据 item['href'] = host+tr.xpath('./td[1]/a/@href').extract_first() item['name'] = tr.xpath('./td[1]/a/text()').extract_first() item['genre'] = tr.xpath('./td[2]/text()').extract_first() item['number'] = tr.xpath('./td[3]/text()').extract_first() item['address'] = tr.xpath('./td[4]/text()').extract_first() item['pub_date'] = tr.xpath('./td[5]/text()').extract_first() # 将数据返回给引擎 yield item # 获取发送下一页 next_page = host + response.xpath("//a[@id='next']/@href").extract()[0] # 发送下一页请求,并指定运行的函数 yield scrapy.Request(next_page, callback=self.parse)
import scrapy class TencentItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() href = scrapy.Field() name = scrapy.Field() genre = scrapy.Field() # 类型 number = scrapy.Field() address = scrapy.Field() pub_date = scrapy.Field()
import json class TencentPipeline(object): def open_spider(self, spider): # 打开文件 self.file = open('centent.json', 'w') # 先 self.file.write('[') def process_item(self, item, spider): # 将item模型对象转为dict item_dict = dict(item) # 将dict转为json item_json = json.dumps(item_dict, ensure_ascii=False, indent=2) # 写入 self.file.write(item_json+',\n') return item def close_spider(self, spider): # 后 self.file.write(']') # 关 self.file.close()
Scrapy Shell
Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试XPath或CSS表达式,查看他们的工作方式,方便我们爬取的网页中提取的数据。
Selectors选择器
Scrapy Selectors 内置 XPath 和 CSS Selector 表达式机制
Selector有四个基本的方法,最常用的还是xpath:
- xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表
- extract(): 序列化该节点为字符串并返回list
- css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表,语法同 BeautifulSoup4
- re(): 根据传入的正则表达式对数据进行提取,返回字符串list列表
官方文档:http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/shell.html
进入shell默认会返回response对象和resquest对象 用dir(response)查看所有的操作属性及方法
scrapy shell -s USER_AGENT=‘Mozilla/5.0’ "http://hr.tencent.com/position.php?&start=0#a" # 启动shell并添加 用户头--伪装
Spider
Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。
class scrapy.Spider是最基本的类,所有编写的爬虫必须继承这个类。
主要用到的函数及调用顺序为:
__init__() : 初始化爬虫名字和start_urls列表
start_requests() 调用make_requests_from url():生成Requests对象交给Scrapy下载并返回response
parse() : 解析response,并返回Item或Requests(需指定回调函数)。Item传给Item pipline持久化 , 而Requests交由Scrapy下载,并由指定的回调函数处理(默认parse()),一直进行循环,直到处理完所有的数据为止。
#所有爬虫的基类,用户定义的爬虫必须从这个类继承 class Spider(object_ref): #定义spider名字的字符串(string)。spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。 #name是spider最重要的属性,而且是必须的。 #一般做法是以该网站(domain)(加或不加 后缀 )来命名spider。 例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite name = None #初始化,提取爬虫名字,start_ruls def __init__(self, name=None, **kwargs): if name is not None: self.name = name # 如果爬虫没有名字,中断后续操作则报错 elif not getattr(self, 'name', None): raise ValueError("%s must have a name" % type(self).__name__) # python 对象或类型通过内置成员__dict__来存储成员信息 self.__dict__.update(kwargs) #URL列表。当没有指定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。 if not hasattr(self, 'start_urls'): self.start_urls = [] # 打印Scrapy执行后的log信息 def log(self, message, level=log.DEBUG, **kw): log.msg(message, spider=self, level=level, **kw) # 判断对象object的属性是否存在,不存在做断言处理 def set_crawler(self, crawler): assert not hasattr(self, '_crawler'), "Spider already bounded to %s" % crawler self._crawler = crawler @property def crawler(self): assert hasattr(self, '_crawler'), "Spider not bounded to any crawler" return self._crawler @property def settings(self): return self.crawler.settings #该方法将读取start_urls内的地址,并为每一个地址生成一个Request对象,交给Scrapy下载并返回Response #该方法仅调用一次 def start_requests(self): for url in self.start_urls: yield self.make_requests_from_url(url) #start_requests()中调用,实际生成Request的函数。 #Request对象默认的回调函数为parse(),提交的方式为get def make_requests_from_url(self, url): return Request(url, dont_filter=True) #默认的Request对象回调函数,处理返回的response。 #生成Item或者Request对象。用户必须实现这个类 def parse(self, response): raise NotImplementedError @classmethod def handles_request(cls, request): return url_is_from_spider(request.url, cls) def __str__(self): return "<%s %r at 0x%0x>" % (type(self).__name__, self.name, id(self)) __repr__ = __str__
主要属性和方法
-
name
定义spider名字的字符串。
例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite
-
allowed_domains
包含了spider允许爬取的域名(domain)的列表,可选。
-
start_urls
初始URL元祖/列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。
-
start_requests(self)
该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取(默认实现是使用 start_urls 的url)的第一个Request。
当spider启动爬取并且未指定start_urls时,该方法被调用。
-
parse(self, response)
当请求url返回网页没有指定回调函数时,默认的Request对象回调函数。用来处理网页返回的response,以及生成Item或者Request对象。
-
log(self, message[, level, component])
使用 scrapy.log.msg() 方法记录(log)message。 更多数据请参见 logging

浙公网安备 33010602011771号