scrapy

scrapy 简介

scrapy 是一款 python 开发的 web 抓取框架,用于抓取 web 站点并从页面中提取结构化数据。scrapy 还可以用于数据挖掘、检测和自动化测试等。

scrapy 构成

scrapy 主要由以下组件组成,它们分别是调度器(Scheduler)、调度中间件(Scheduler Middewares)、下载器(Downloader)、下载器中间件(Downloader Middlewares)、爬虫(Spider)、爬虫中间件(Spider Middlewares)、管道(Item Pipeline) 和 Scrapy引擎(Scrapy Engine)。

Scrapy引擎(Scrapy Engine)

框架的核心部分,它控制着调度器、下载器、爬虫和管道,相当于计算机的 CPU,控制整个流程。

管道(Item Pipeline)

用于处理爬虫提取的实体,主要功能是验证和清除不需要的信息,并持久化信息。

爬虫(Spider)

用户自己定制的部分,用于从特定的网站中提取自己需要的信息。

爬虫中间件(Spider Middlewares)

介于scrapy引擎和爬虫之间的中间件,主要处理爬虫响应输入和请求输出。包含url重定向、url长度、请求深度、请求错误等处理。

下载器(Downloader)

用于高速的从网络上获取资源,是建立在 twisted 这个高效的异步模型上。

下载器中间件(Downloader Middlewares)

介于引擎和下载器之间的框架,主要是处理引擎和下载器之间的请求和响应,可以在此处配置ip代理迟、user_agent,cookie 等反爬策略。

调度器(Scheduler)

用于接收请求并压入队列中,在引擎再次请求时返回,由它决定下一个要抓取的网址是什么,同时负责去重网址。

scrapy 执行流程

scrapy发出请求后的整个流程如下:

1.首先发送出的 request 经Scrapy引擎交给调度器(Scheduler)
2.调度器排序处理后,由Scrapy引擎经下载器中间件到下载器(Downloader)
3.下载器向互联网发送请求,并接收响应,再由Scrapy引擎经过爬虫中间件交给 Spiders
4.spiers处理response,提取数据后,再由Scrapy引擎交给管道(Item Pipeline)
5.提取新的request 经Scrapy引擎交给调度器(Scheduler)并重复上述流程

向scrapy中的spider传参

有时候需要根据项目的实际需求向spider传递参数来控制spider的运行方式。

ep:

1
2
1. 根据用户提交的url来控制spider爬取的网站。
2. 根据需求增量爬取数据。

Spider参数通过 crawl 命令的 -a 选项来传递,比如:

1
2
scrapy crawl xxx -a parameter=xxxxxx
注:augmenter=不为空

在spider中添加如下配置

1
2
3
4
5
6
7
8
import scrapy

class MySpider(scrapy.Spider):
name = 'myspider'

def __init__(self, parameter=None, *args, **kwargs):
super(MySpider, self).__init__(*args, **kwargs)
self.start_urls = ['http://www.example.com/categories/%s' % category]

注:在网上也看了不少的博客,最后发现*args, **kwargs这两个必须加上,要不然会出现bug。

上面的

1
super(MySpider, self).__init__(*args, **kwargs)

可用下面的方式代替,这里的eval()获取的是类名,这样写必须是最后一个是你要的类名,中间如果有继承就会出错!

1
super(eval(self.__class__.__name__), self).__init__(*args, **kwargs)

callback 传递参数

方法一: 直接传递参数(不推荐使用)

1
2
3
4
5
def start_requests(self):
yield Request(url=self.url, callback=lambda response, urls=self.list_urls, count=1: self.parse(response, urls, count))

def parse(self, response, urls, count):
pass

方法二: 使用meta传递参数

1
2
3
4
5
6
7
def start_requests(self):
yield Request(self.user_url.format(uid=uid), callback=self.parse_user, meta={'page': 1, 'uid': uid})

def parse_user(self, response):
page = response.meta.get('page')
uid = response.meta.get('uid')
pass

log 配置方式

在setting.py添加以下参数配置log的路径和等级

1
2
LOG_FILE = 'xxxlog.txt'
LOG_LEVEL = 'INFO'

在项目中使用如下方式记录日志:

1
2
3
4
5
6
7
8
9
10
11
import logging

class TTspiderPipeline(object):

logger = logging.getLogger(__name__)

def process_item(self, item, spider):
print('process_item', item)

def close_spider(self, spider):
self.logger.info('TTspiderPipeline close_spider')