文章目录
最近在研究scrapy框架,在这里简单整理下scrapy使用步骤进行记录,也方便大家阅读。
1. 安装scrapy
pip install scrapy
2. 创建scrapy项目
# projectname为项目名称,可自定义
scrapy startproject projectname
创建项目后会看到以项目名称为名的目录,目录下面的结构如下所示
projectname/
scrapy.cfg # 配置文件
projectname/ # 爬虫模块文件夹
__init__.py
items.py # items定义文件
middlewares.py # 中间件middlewares文件
pipelines.py # 项目管道pipelines文件
settings.py # 设置settings文件
spiders/ # 爬虫文件夹
__init__.py
3. scrapy框架工作原理
在编写前首先要了解scrapy的工作原理
3.1 scrapy框架工作流程图
3.2 Scrapy数据流讲解
- 爬虫引擎Engine从爬虫Spiders中获得初始请求开始抓取。
- 爬虫引擎EngineE开始请求调度程序Scheduler,并准备对下一一次的请求Request进行抓取。
- 爬虫调度器Scheduler返回下一个请求Request给爬虫引擎Engine。
- 引擎Engine请求发送到下载器Downloader,通过下载中间件Middleware下载网络数据。
- 一旦下载器Downloader完成页面下载,将下载结果Response返回给爬虫引擎Engine。
- 引擎Engine将下载器Downloader的响应通过中间件Middleware返回给爬虫Spiders进行处理。
- 爬虫Spiders处理响应Response,并通过中间件Middleware返回处理后的Items,以及新的请求Request给引擎Engine。
- 引擎Engine发送处理后的Items给到项目管道Pipelines进行存储或其他处理,把处理后的Requests给调度器Scheduler,调度器Scheduler计划处理下一个请求抓取。
3.3 各个组件的讲解
- 爬虫引擎(ENGINE)
爬虫引擎负责控制各个组件之间的数据流,当某些操作触发事件后都是通过engine来处理。 - 调度器(SCHEDULER)
调度器接收来子engine的请求并将请求放入队列中,并通过事件返回给engine。 - 下载器(DOWNLOADER)
通过engine请求下载网络数据并将结果响应给engine。 - Spider
Spider发出请求,并处理engine返回给它下载器响应数据,以items和规则内的数据请求(urds)返回给engine。 - 管道项目(item pipeline)
负责处理engine返回spider解析后的数据,并且将数据持久化,例如将数据存入数据库或者文件。 - 下载中间件(MIDDLEWARE)
下载中间件是engine和下载器交互组件,以钩子(插件)的形式存在,可以代替接收请求处理数据的下载以及将结果响应给engine. - spider中间件(MIDDLEWARE)
spider中间件是engine和spider之间的交互组件,以钩子(插件)的形式存在,可以代替处理responsel以及返回给engineitems及新的请求集。
4. 提取数据
提取数据前要先定位元素,scrapy中可以使用xpath进行定位,也可以使用CSS进行定位,实例如下
response.xpath('//span/text()').get()
response.css('span::text').get()
详细的这里不做记录了,请百度。
5. 爬虫编写步骤
- 找到要爬取的网站
- 找到要获取的数据,定义items,在items.py中定义要获取的内容,item内容在spiders的parse函数中赋值
- 在spiders目录下创建一个Python文件,该文件用来处理爬虫。文件中需要创建一个继承scrapy.Spider的类,类中定义一个爬虫名,并定义需要爬取的网址;在parse函数中解析爬到的数据,并对应到items
- 在pipeline中编写数据持久化的方法,如存入数据库或存入文件
- 如若需要,可在中间件Middleware.py中编写需要的处理过程
6. 执行爬虫
爬虫写好后当然就是要迫不及待的执行试试了
# projectname为项目名称
scrapy crawl projectname
# 在shell中执行scrapy,URL为要爬取的网址
scrapy shell URL
7. 测试项目案例(附源码)
为了学习这里就使用豆瓣进行测试,实现将图书详细信息页面的信息进行存储,我是用《百年孤独》页面来做测试的,其网址为https://book.douban.com/subject/6082808
我创建的项目名称为booksearch,使用的爬虫名为book,爬取后,会解析出书名、作者、出版社、原作名、译者、出版年、页数、定价、装帧、丛书、ISBN码、评分,并以json的形式存到book.json文件中,读取json文件如下图所示
下面上代码
项目文件结构
booksearch/
scrapy.cfg # 配置文件
booksearch/ # 爬虫模块文件夹
__init__.py
items.py # items定义文件
middlewares.py # 中间件文件
pipelines.py # 项目管道文件
settings.py # 设置文件,设置headers、执行优先级、robots开关等设置
spiders/ # 爬虫文件夹
__init__.py
book_spider.py # 爬虫文件,负责爬取图书页面
爬虫文件
# -*- coding: utf-8 -*-
import scrapy
from booksearch.items import BooksearchItem
class BookSpider(scrapy.Spider):
name = 'book'
allowed_domains = ['book.douban.com']
def __init__(self,url=None, *args, **kwargs):
super(BookSpider, self).__init__(*args, **kwargs)
self.start_urls = [r'https://book.douban.com/subject/6082808/',]
def parse(self, response):
print('开始处理')
item = BooksearchItem()
# 书名
item['title'] = response.xpath("//span[@property='v:itemreviewed']/text()").extract()[0]
# 获取图书信息后解析
temp_dict = {}
temp_list = []
tmp = response.xpath('//div[@id="info"]')
for i in tmp.xpath('.//text()').extract():
i=i.replace(' ', '').strip('\n').strip()
if len(i)>0:
if '作者' in i:
i = '作者:'
if '译者' in i:
i = '译者:'
if ':' not in i:
i = i + ';'
if i == ':':
continue
temp_list.append(i.replace(' ', '').strip('\n').strip())
temp_str = ''.join(temp_list)
temp_list2 = temp_str.split(';')
for i in temp_list2:
if len(i)>0:
temp_dict.update({i.split(':')[0]:i.split(':')[1]})
if '作者' in temp_dict.keys():
item['author'] = temp_dict['作者'] # 作者
if '出版社' in temp_dict.keys():
item['publisher'] = temp_dict['出版社'] # 出版社
if '原作名' in temp_dict.keys():
item['original_title'] = temp_dict['原作名'] # 原作名
if '译者' in temp_dict.keys():
item['translator'] = temp_dict['译者'] # 译者
if '出版年' in temp_dict.keys():
item['pub_date'] = temp_dict['出版年'] # 出版年
if '页数' in temp_dict.keys():
item['pages'] = temp_dict['页数'] # 页数
if '定价' in temp_dict.keys():
item['price'] = temp_dict['定价'] # 定价
if '装帧' in temp_dict.keys():
item['bingding'] = temp_dict['装帧'] # 装帧
if '丛书' in temp_dict.keys():
item['series'] = temp_dict['丛书'] # 丛书
if 'ISBN' in temp_dict.keys():
item['isbn'] = temp_dict['ISBN'] # ISBN码
# 获取评分
item['star'] = response.xpath("//strong/text()").get()
yield item
itmes文件
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class BooksearchItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field() # 书名
author = scrapy.Field() # 作者
publisher = scrapy.Field() # 出版社
original_title = scrapy.Field() # 原作名
translator = scrapy.Field() # 译者
pub_date = scrapy.Field() # 出版年
pages = scrapy.Field() # 页数
price = scrapy.Field() # 定价
bingding = scrapy.Field() # 装帧
series = scrapy.Field() # 丛书
isbn = scrapy.Field() # ISBN码
star = scrapy.Field() # 评分
项目管道文件
# -*- coding: utf-8 -*-
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
import json
class BooksearchPipeline(object):
def process_item(self, item, spider):
print('开始存储爬取内容')
line = json.dumps(dict(item)) + "\n"
print(line)
with open('book.json', 'w') as f:
f.write(line)
return item