4.5. scrapy两大爬虫类_Spider
一: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
二:案例:腾讯招聘网自动翻页采集
- 创建一个新的爬虫:
 
scrapy genspider tencent "tencent.com"
- 编写items.py:获取职位名称、详细信息
 
class TencentItem(scrapy.Item):
name = scrapy.Field()
detailLink = scrapy.Field()
positionInfo = scrapy.Field()
peopleNumber = scrapy.Field()
workLocation = scrapy.Field()
publishTime = scrapy.Field()
- 编写tencent.py
 
# -*- coding: utf-8 -*-
import scrapy
import re
from mySpider.items import TencentItem class TencentSpider(scrapy.Spider):
name = 'tencent'
allowed_domains = ['hr.tencent.com']
base_urls = 'http://hr.tencent.com/position.php?&start='
#根据url规律,定义偏移量offset
offset = 0
#组装发送请求的URL地址
start_urls = [base_urls + str(offset)] #处理响应信息默认的调用方法
def parse(self, response):
for each in response.xpath("//tr[@class='even']|//tr[@class='odd']"):
#引入定义好的字段Item类
item = TencentItem()
#获取信息
#xpath使用规则则:因为xpath返回一个列表,所以必须取索引;xpath.extract()将xpath对象转换为Unicode字符串
#将unic编码格式转换成utf-8
item['name'] = each.xpath("./td[1]/a/text()").extract()[0].encode('utf-8')
item['detailLink'] = each.xpath('./td[1]/a/@href').extract()[0].encode('utf-8')
if len(each.xpath('./td[2]/text()')):
item['positionInfo'] = each.xpath('./td[2]/text()').extract()[0].encode('utf-8')
else:
item['positionInfo'] = ""
item['peopleNumber'] = each.xpath('./td[3]/text()').extract()[0].encode('utf-8')
item['workLocation'] = each.xpath('./td[4]/text()').extract()[0].encode('utf-8')
item['publishTime'] = each.xpath('./td[5]/text()').extract()[0].encode('utf-8') #将数据返回给管道文件
yield item #实现腾讯招聘网自动翻页采集方式1:上一页和下一页变成灰色
#print response.xpath("//a[@class='noactive' and @id='next']")
#if len(response.xpath("//a[@class='noactive' and @id='next']")) == 0:
#url = response.xpath("//a[@id='next']/@href")[0].extract()
#print "-------------------"+url
#yield scrapy.Request("http://hr.tencent.com/"+url,callback = self.parse) # 实现腾讯招聘网自动翻页采集方式2:
curpage = re.search('(\d+)', response.url).group(1)
page = int(curpage) + 10
url = re.sub('\d+', str(page), response.url)
# 发送新的url请求加入待爬队列,并调用回调函数 self.parse
yield scrapy.Request(url, callback=self.parse)
- 编写pipeline.py文件
 
import json #class ItcastJsonPipeline(object):
class TencentJsonPipeline(object): def __init__(self):
#self.file = open('teacher.json', 'wb')
self.file = open('tencent.json', 'wb') def process_item(self, item, spider):
content = json.dumps(dict(item), ensure_ascii=False) + "\n"
self.file.write(content)
return item def close_spider(self, spider):
self.file.close()
- 在 setting.py 里设置ITEM_PIPELINES
 
ITEM_PIPELINES = {
    #'mySpider.pipelines.SomePipeline': 300,
    #"mySpider.pipelines.ItcastJsonPipeline":300
    "mySpider.pipelines.TencentJsonPipeline":300
}
执行爬虫:
scrapy crawl tencent
思考
请思考 parse()方法的工作机制: 
1. 因为使用的yield,而不是return。parse函数将会被当做一个生成器使用。scrapy会逐一获取parse方法中生成的结果,并判断该结果是一个什么样的类型;
2. 如果是request则加入爬取队列,如果是item类型则使用pipeline处理,其他类型则返回错误信息。
3. scrapy取到第一部分的request不会立马就去发送这个request,只是把这个request放到队列里,然后接着从生成器里获取;
4. 取尽第一部分的request,然后再获取第二部分的item,取到item了,就会放到对应的pipeline里处理;
5. parse()方法作为回调函数(callback)赋值给了Request,指定parse()方法来处理这些请求 scrapy.Request(url, callback=self.parse)
6. Request对象经过调度,执行生成 scrapy.http.response()的响应对象,并送回给parse()方法,直到调度器中没有Request(递归的思路)
7. 取尽之后,parse()工作结束,引擎再根据队列和pipelines中的内容去执行相应的操作;
8. 程序在取得各个页面的items前,会先处理完之前所有的request队列里的请求,然后再提取items。
7. 这一切的一切,Scrapy引擎和调度器将负责到底。
 1. 因为使用的yield,而不是return。parse函数将会被当做一个生成器使用。scrapy会逐一获取parse方法中生成的结果,并判断该结果是一个什么样的类型; 2. 如果是request则加入爬取队列,如果是item类型则使用pipeline处理,其他类型则返回错误信息。 3. scrapy取到第一部分的request不会立马就去发送这个request,只是把这个request放到队列里,然后接着从生成器里获取; 4. 取尽第一部分的request,然后再获取第二部分的item,取到item了,就会放到对应的pipeline里处理; 5. parse()方法作为回调函数(callback)赋值给了Request,指定parse()方法来处理这些请求 scrapy.Request(url, callback=self.parse) 6. Request对象经过调度,执行生成 scrapy.http.response()的响应对象,并送回给parse()方法,直到调度器中没有Request(递归的思路) 7. 取尽之后,parse()工作结束,引擎再根据队列和pipelines中的内容去执行相应的操作; 8. 程序在取得各个页面的items前,会先处理完之前所有的request队列里的请求,然后再提取items。 7. 这一切的一切,Scrapy引擎和调度器将负责到底。 
4.5. scrapy两大爬虫类_Spider的更多相关文章
- Java入门到精通——框架篇之Spring源码分析Spring两大核心类
		
一.Spring核心类概述. Spring里面有两个最核心的类这是Spring实现最重要的部分. 1.DefaultListableBeanFactory 这个类位于Beans项目下的org.spri ...
 - cocos2d-x 的两大基类
		
cocos2d-x 有两个重要的基类,一个管理引用计数的 Ref,别一个则定义许多基本属性的 Node. 在 cocos2d-x 中的基本概念 说到 create 函数的时候提到 cocos2d-x ...
 - Scrapy:创建爬虫程序的方式
		
Windows 10家庭中文版,Python 3.6.4,Scrapy 1.5.0, 在Scrapy中,建立爬虫程序或项目的方式有两种(在孤读过Scrapy的大部分文档后): 1.继承官方Spider ...
 - scrapy的大文件下载(基于一种形式的管道类实现)
		
scrapy的大文件下载(基于一种形式的管道类实现) 爬虫类中将解析到的图片地址存储到item,将item提交给指定的管道 在管道文件中导包:from scrapy.pipelines.images ...
 - dll的加载方式主要分为两大类,显式和隐式链接
		
之前简单写过如何创建lib和dll文件及简单的使用(http://blog.csdn.net/betabin/article/details/7239200).现在先再深入点写写dll的加载方式. d ...
 - 【Java知识点专项练习】之 数据类型两大类
		
Java的数据类型分为两大类:基本类型和引用类型: 基本类型只能保存一些常量数据,引用类型除了可以保存数据,还能提供操作这些数据的功能: 为了操作基本类型的数据,java也对它们进行了封装, 得到八个 ...
 - 关于fmri数据分析的两大类,四种方法
		
关于fmri数据分析的两大类,四种方法: 数据驱动: tca:其实这种方法,主要是提取时间维的特征.如果用它来进行数据的分析,则必须要利用其他的数据方法,比如结合ICA. ica:作为pca的一般化实 ...
 - Python的两个爬虫框架PySpider与Scrapy安装
		
Python的两个爬虫框架PySpider与Scrapy安装 win10安装pyspider: 最好以管理员身份运行CMD,不然可能会出现拒绝访问文件夹的情况! pyspider:pip instal ...
 - Access Violation分成两大类:运行期和设计期(很全的解释)
		
用Delphi开发程序时,我们可以把遇到的Access Violation分成两大类:运行期和设计期. 一.设计期的Access Violation 1.硬件原因 在启动或关闭Delphi IDE以 ...
 
随机推荐
- XmlEncrypt
			
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
 - 一、Node.js安装及环境配置之Windows篇
			
一.安装环境 1.本机系统:Windows 10 Pro(64位)2.Node.js:v6.9.2LTS(64位) 二.安装Node.js步骤 1.下载对应你系统的Node.js版本:https:// ...
 - 【JulyEdu-Python基础】第 8 课:Python第三方库
			
outline 数值计算 numpy 数据处理分析 pandas 可视化 matplotlib/seaborn 机器学习 Sklearn / keras 交互 pygame 网络 Selen ...
 - 【机器学习】QQ-plot深入理解与实现
			
QQ-plot深入理解与实现 26JUN June 26, 2013 最近在看关于CSI(Channel State Information)相关的论文,发现论文中用到了QQ-plot.Sigh!我承 ...
 - VMware中centos虚拟机的安装
			
几个月前,就下载了VMware,centOS 6 操作系统镜像.苦于对linux的不理解和安装教程的不熟悉,一直未安装成功. 几天前,终于独自安装好了,特此记录一下. 安装其实很简单,之前失败是在于安 ...
 - NPM安装过程中的一些问题与解决
			
1. 安装 vue-cli3后提示 : Package require os(darwin) not compatible with your platform(win32). 上面是因为安装 npm ...
 - octave
			
1. octave, 如何求一元二次方程的解: 例如:· -3x-9y=18 · 4x+3y=12 命令: >>> A=[-3 -9; 4 3]; B=[18;12]; &g ...
 - Go基础:函数多返回值特性
			
之前在写Python程序的时候,惊叹于它支持多返回值的特性带来的便利性.在学习Go的时候,发现Go也拥有多返回值的特性. 1.基本用法 创建一个多返回值的方法: func getACar() (bra ...
 - 阿里云服务器 lnmp安装流程
			
nginx安装:wget http://nginx.org/download/nginx-1.12.2.tar.gztar zxvf nginx-1.12.2.tar.gzcd nginx-1.12. ...
 - 【转帖】.NET的一点历史故事:Novell的崩溃和Xamarin的重生
			
.NET的一点历史故事:Novell的崩溃和Xamarin的重生 https://blog.csdn.net/sD7O95O/article/details/78096502 学习安装 mono 时了 ...