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
# tencent.pyfrom mySpider.items import TencentItem
import scrapy
import re class TencentSpider(scrapy.Spider): name = "tencent" allowed_domains = ["hr.tencent.com"] start_urls = [ "http://hr.tencent.com/position.php?&start=0#a" ] def parse(self, response): for each in response.xpath('//*[@class="even"]'): item = TencentItem() name = each.xpath('./td[1]/a/text()').extract()[0] detailLink = each.xpath('./td[1]/a/@href').extract()[0] positionInfo = each.xpath('./td[2]/text()').extract()[0] peopleNumber = each.xpath('./td[3]/text()').extract()[0] workLocation = each.xpath('./td[4]/text()').extract()[0] publishTime = each.xpath('./td[5]/text()').extract()[0] #print name, detailLink, catalog, peopleNumber, workLocation,publishTime item['name'] = name.encode('utf-8') item['detailLink'] = detailLink.encode('utf-8') item['positionInfo'] = positionInfo.encode('utf-8') item['peopleNumber'] = peopleNumber.encode('utf-8') item['workLocation'] = workLocation.encode('utf-8') item['publishTime'] = publishTime.encode('utf-8') 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 yield item 
  • 编写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引擎和调度器将负责到底。

转载于:https://www.cnblogs.com/joshuazc/p/9791200.html

Scrapy框架----- Spiders相关推荐

  1. scrapy 框架抓取艺龙酒店(热门城市酒店信息)

    一.scrapy框架 Spiders文件- Yi_long.py import requests import re import time import jsonclass Yi_long():de ...

  2. python爬虫之Scrapy框架的post请求和核心组件的工作 流程

    python爬虫之Scrapy框架的post请求和核心组件的工作 流程 一 Scrapy的post请求的实现 在爬虫文件中的爬虫类继承了Spider父类中的start_urls,该方法就可以对star ...

  3. Scrapy框架中的crawlspider爬虫

    1 crawlspider是什么 在spider中要寻找下一页的url地址或者内容的url地址,想想是否有简单的方法省略寻找url的过程? 思路: 从response中提取所有的满足规则的url地址 ...

  4. 爬虫基础分享Scrapy框架流程图与安装

    从头开发一个爬虫程序是一项烦琐的工作,为了避免因制造轮子而消耗大量时间,在实际应用中我们可以选择使用一些优秀的爬虫框架,使用框架可以降低开发成本,提高程序质量,让我们能够专注于业务逻辑.所以,我们一起 ...

  5. python 爬虫 学习笔记(一)Scrapy框架入门

    沉迷于通过高效算法及经典数据结构来优化程序的时候并不理解,为什么多线程可以优化爬虫运行速度?原来是程序特性所决定的:传统算法的程序复杂度主要来源于计算,但网络程序的计算时间可以忽略不计,网络程序所面临 ...

  6. python scrapy框架基如何实现多线程_【转】爬虫的一般方法、异步、并发与框架scrapy的效率比较...

    问题的由来 我们的需求为爬取红色框框内的名人(有500条记录,图片只展示了一部分)的 名字以及其介绍,关于其介绍,点击该名人的名字即可,如下图: 这就意味着我们需要爬取500个这样的页面,即500个H ...

  7. Scrapy框架基础使用

    1.流程框架 2.在命令行中输入scrapy,会有scrapy常见命令参数 在命令中输入scrapy startproject quote创建一个叫quote的项目 cd到创建好的项目目录中,然后执行 ...

  8. scrapy框架_Scrapy框架学习---Scrapy介绍(一)

    Scrapy 框架 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页 ...

  9. Python爬虫从入门到放弃(十二)之 Scrapy框架的架构和原理

    原文地址https://www.cnblogs.com/zhaof/p/7173397.html 这一篇文章主要是为了对scrapy框架的工作流程以及各个组件功能的介绍 Scrapy目前已经可以很好的 ...

最新文章

  1. Tensorflow安装与测试
  2. 统计学习方法笔记 -- Boosting方法
  3. Sublime Text3软件安装教程
  4. 数据库抽象层 PDO
  5. Nginx学习笔记(七) 创建子进程
  6. php熊掌号怎么设置json-ld,dedecms织梦系统怎么对接百度熊掌号并添加JSON_LD数据
  7. 392. 判断子序列 golang 关于布尔类型返回值判断的思考
  8. 日均5亿查询量的京东订单中心,为什么舍MySQL用ElasticSearch?
  9. 网页连接的服务器失败是怎么回事啊,网页怎么连接服务器失败
  10. UVA10341 Solve It【二分】
  11. centos5.5和6.5中vncservervncviewer最基本配置
  12. MFC框架学习:《深入浅出MFC》阅读笔记
  13. LibVLC —— Qt下OpenGL播放rtsp/rtmp流,每帧图像基于OpenCv处理
  14. 7-12 输出大写英文字母 (15 分)
  15. 2021.12.10 vue vue-cil (12)
  16. linux卸载软件wine,Ubuntu 卸载wine
  17. 绝对最大额定值(ABSOLUTE MAXIMUM RATINGS: ABS)是否可以超过
  18. python微信定时发送消息
  19. 专业商标设计、logo免费在线设计
  20. css3和html5网站模板

热门文章

  1. Linux - How to use LVM in Linux
  2. android 监听时钟变化,Android4.4 SystemUI分析之Clock时钟显示
  3. python地理数据处理 下载_python-doc/将Python用于地理空间数据处理.md at master · zhuxinyizhizun/python-doc · GitHub...
  4. OpenCV中图像的BGR格式 Img对象的属性说明
  5. c语言数码管编写程序,跪求单片机0~99数码管显示用C语言编写的程序
  6. 17原理图查找连接的管脚接口_第三节 主板原理图之标识的作用
  7. SpringBoot 自动配置
  8. 【c++】13.必须用指针取值的情况.md
  9. 《JAVA与模式》之状态模式
  10. 深入了解 Java 之虚拟机内存