Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 能够应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。css
引擎负责控制数据流。html
调度器从引擎接受request并将他们入队,以便以后引擎请求他们时提供给引擎。python
下载器负责获取页面数据并提供给引擎,然后提供给spider。正则表达式
Spider是Scrapy用户编写用于分析response并提取item(即获取到的item)或额外跟进的URL的类。 每一个spider负责处理一个特定(或一些)网站。数据库
Item Pipeline负责处理被spider提取出来的item。典型的处理有清理、 验证及持久化(例如存取到数据库中)。api
下载器中间件是在引擎及下载器之间的特定钩子(specific hook),处理Downloader传递给引擎的response。 其提供了一个简便的机制,经过插入自定义代码来扩展Scrapy功能。网络
Spider中间件是在引擎及Spider之间的特定钩子(specific hook),处理spider的输入(response)和输出(items及requests)。 其提供了一个简便的机制,经过插入自定义代码来扩展Scrapy功能。并发
安装如下程序框架
pip install pyopenssl
建立工程模板dom
命令行执行:scrapy startproject 工程名
建立好的工程结构以下图:
Idea中配置scrapy启动
开发中主要涉及spider,item,Pipeline,settings模块的开发。须要扩展插件则开发extions模块。
继承scrapy.Spider类
属性
name : 爬虫名字,用于区别spider,惟一。
start_urls : Spider在启动时进行爬取的url列表。后续的URL则从初始的URL获取到的数据中提取。
方法
parse(self, response) :每一个初始url爬取到的数据将经过response参数传递过来。此方法负责解析数据(response), 提取数据(生成Item),生成须要进一步处理的URL请求(request)。
scrapy.Request(url=link, errback=self.errback_http, callback=self.parse_article)
框架会对url=link的地址发起请求,若是请求出现错误执行用户自定义的errback_http方法,若是请求成功则执行用户自定义的parse_article方法。
须要继承scrapy.Item。Item是一个dict(),用于存储spider中parse()中解析到的数据,在pipeline中调用。
import scrapy class DmozItem(scrapy.Item): title = scrapy.Field() link = scrapy.Field() desc = scrapy.Field()
Scrapy Selector基于xpath和css提取元素。
xpath()
: 传入xpath表达式,返回该表达式所对应的全部节点的selector list列表 。css()
: 传入CSS表达式,返回该表达式所对应的全部节点的selector list列表.extract()
: 序列化该节点为unicode字符串并返回list。re()
: 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表。运行爬虫
在项目目录下运行如下命令,便可执行爬虫:
scrapy crawl NAME(爬虫名字)
Settings文件能够能够控制包括核心(core),插件(extension),pipeline及spider组件。这里只说3.settings模块。
若是须要使用该配置文件中定义的属性,类(爬虫,管道,插件)须要增长额外的类方法: from_crawler(cls, crawler)。
设定能够经过Crawler的 scrapy.crawler.Crawler.settings
属性进行访问。其由插件及中间件的from_crawler
方法所传入:
class MyExtension(object): @classmethod def from_crawler(cls, crawler): settings = crawler.settings if settings['LOG_ENABLED']: print "log is enabled!"
也能够经过字典访问,避免错误,建议使用setting API中的规范key值。
管道相似过滤处理链,根据自定义业务依次处理Spider解析后的数据,例如数据验证(去重、转换),计算存储(DB,NOSQL),发送消息(Kafka,MQ),报表生成。
开发自定义管道类须要两步骤:
说明
自定义管道根据序列号从小到大依次执行请求,若是抛出DropItem异常,后续管道将不会执行,例如数据出现重复主键,能够抛出DropItem异常。
使用如下代码在管道中定义日志名称
logger = logging.getLogger('pipelogger')
日志启用也能够在settings中设置以下属性
LOG_ENABLED = True #启用日志
LOG_ENCODING = 'utf-8' #设置日志字符集
LOG_FILE = 'e://workspace/log/csdncrawl.log' #指定日志文件及路径
LOG_LEVEL = 'INFO' #定义日志级别
LOG_STDOUT = True #是否将print语句打印内容输出到日志
开发者可自定义运行在不一样阶段的插件,例如打开爬虫、关闭爬虫、数据抓取等。
插件只须要关注:在何时作什么事情,即 状态-方法。
开发插件只须要2步:
crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)
import scrapy class DmozSpider(scrapy.Spider): name = "dmoz" allowed_domains = ["dmoz.org"] start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] def parse(self, response): for sel in response.xpath('//ul/li'): title = sel.xpath('a/text()').extract() link = sel.xpath('a/@href').extract() desc = sel.xpath('text()').extract() print title, link, desc
日志Logging
import logginglogger = logging.getLogger('mycustomlogger')
logger.warning("This is a warning") import logging import scrapy logger = logging.getLogger('mycustomlogger') class MySpider(scrapy.Spider): name = 'myspider' start_urls = ['http://scrapinghub.com'] def parse(self, response): logger.info('Parse function called on %s', response.url)
参考资料:
中文版scrapy资料地址:https://scrapy-chs.readthedocs.io/zh_CN/1.0/intro/tutorial.html