Scrapy框架
***Scrapy***是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架。Scrapy 使用了Twisted['twɪstɪd]异步网络框架来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求,加快开发速度。
原理图
- 爬虫文件将第一个需要处理的网址交给引擎。
- 引擎将该网址交给调度器去处理(调度器主要控制爬取网址的顺序)。
- 调度器将处理好的网址返回给引擎。
- 引擎将从调度器得到的请求通过下载器中间件处理以后交给给下载器。
- 下载器从互联网上下载网页源码,将下载得到的响应通过下载器中间件交给引擎。
- 引擎将得到的响应,通过爬虫中间件的处理以后交给爬虫文件。
- 爬虫文件得到响应(源码)以后进行相关处理(提取数据,提取新链接)。将数据和链接通过爬虫中间件再交给引擎。
- 引擎现在有两个数据,引擎会将数据交给管道文件处理,管道文件进行响应的保存等的处理,引擎将请求(新链接)交给调度器处理。调度器会把新的链接加入下载队列。
scrapy全局命令
# 创建一个项目
scrapy startproject 项目名
# 测试电脑性能
scrapy bench
scrapy项目命令
# 创建一个爬虫文件
scrapy genspider 爬虫文件名 域名
# 运行爬虫文件
scrapy crawl 爬虫文件名
# 列出爬虫的名字
scrapy list
# 在浏览器打开url
scrapy view
# 查看scrapy的版本
scrapy version
scrapy爬虫实例
# -*- coding: utf-8 -*-
import scrapy
class QuotesSpider(scrapy.Spider):
# 爬虫的名字
name = 'quotes'
# 允许爬取的域名
allowed_domains = ['quotes.toscrape.com']
# 初始url,默认发出请求,将response返回到回调函数parse
start_urls = [f'http://quotes.toscrape.com/page/{v}/' for v in range(1, 2)]
# 回调函数
def parse(self, response):
# 根据xpath获取数据
quotes = response.xpath('//div[@class="row"]/div[@class="col-md-8"]/div')
for quote in quotes:
text = quote.xpath('.//span[@class="text"]/text()').extract_first()
author = quote.xpath('.//span/small[@class="author"]/text()').extract_first()
yield {author: text}
start_urls为一个可迭代对象,可以为列表和元组
extract()提取xpath对象中的数据,结果为一个列表
extract_first()提取出列表中的第一个数据
如果不写extract()和extract_first() ,结果为一个对象
保存文件结果
scrapy crawl 爬虫名 -o 保存路径/文件.json
start_request方法
start_urls内部默认会调用start_request方法,如果不使用start_urls,可以重写该方法自行定义发送请求
为什么要重写start_request方法
- start_urls默认为GET请求
- 重写start_request方法可以设置headers,meta,callback等,callback为回调函数
Request方法
-
url 本次请求的网址
-
callback 回调函数
-
headers 请求头 ,字典格式
-
cookies Cookie ,字典格式
-
meta 以浅复制的方式在两个方法之间传递数据-[字典格式]
-
method 请求方式,默认不写为GET方式
meta的使用案例
- 爬取豆瓣top250中的电影名称以及电影详情中的简介
# -*- coding: utf-8 -*-
import scrapy
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['movie.douban.com/top250']
start_urls = [f'https://movie.douban.com/top250/?start={v}&filter=' for v in range(0, 100, 25)]
def parse(self, response):
li = response.xpath('//ol/li')
for v in li:
title = v.xpath('.//a/img/@alt').extract_first()
detail = v.xpath('.//div[@class="pic"]//a/@href').extract_first()
# 通过meta保存的数据,在回调函数中可以直接拿到
yield scrapy.Request(detail, callback=self.parsedetail, meta={"title": title})
def parsedetail(self, response):
summary = response.xpath('//span[@property="v:summary"]/text()').extract()
allsum = ''
for sum in summary:
allsum += sum.strip()
# 获取meta中的值
yield {response.meta['title']: allsum}