学习自:

Scrapy爬虫框架教程(一)-- Scrapy入门 - 知乎

Scrapy爬虫框架,入门案例(非常详细)_ck784101777的博客-CSDN博客_scrapy爬虫案例

爬虫框架Scrapy个人总结(详细)熟悉 - 简书

本章介绍Scrapy使用时的基本要素构成。

1、简介

Scrapy最初是为了页面抓取/网络抓取设计的。Scrapy用途广泛,可以应用数据挖掘、监控、自动化测试等领域。

Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便地进行修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持。

2、各组件作用

Scrapy框架主要由五大组件组成,分别是Scrapy引擎(Scrapy Engine)、下载器(Downloader)、Spider、Item Pipeline、调度器(Scheduler)。

①Scrapy Engine

引擎是整个框架的核心,它用来控制、调度Scheduler、Downloader、Spider。

②调度器(Scheduler)

调度器可以视为一个想要进行抓取的URL队列,由它来决定下一个要抓取的网址是什么,同时可以去除重复的网址。用户可以根据自己的需求定制调度器。

③下载器(Downloader)

下载器负责下载页面数据并提供给引擎,而后提供给Spider。Scrapy的下载器代码并不复杂,但是效率很高,这是因为Scrapy下载器是建立在twisted这个高效的异步模型上的。

④Item Pipeline

Item Pipeline负责处理被Spider提取出来的Item。典型的处理有清理多余信息、验证Item有效性及持久化Item(例如存取到数据库中)。

当页面被爬虫解析所需的数据存入Item之后,将会被发送到Pipeline,并经过几个特定的次序处理数据,最后存入本地文件或者存入数据库。

⑤Spider

用户定制自己的爬虫(通过正则表达式等语法),用于从特定的网页中提取自己需要的信息,即Item。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面。

除了以上五种组件,还有另外三个概念(它们与前边五种组件是相互关联的)也需要了解:

①下载器中间件(Downloader middlewares)

下载器中间件是在引擎及下载器之间的特定钩子(Specific hook),处理Downloader传递给引擎的response。它提供了一个简便机制,通过插入自定义代码来扩展Scrapy功能

通过设置下载器中间件可以事先爬虫自动更换User-Agent、IP等功能。

②Spider中间件(Spider middlewares)

Spider中间件是在引擎及Spider之间的特定钩子(Specific hook),处理Spider的输入(Response)和输出(Item及Requests)。

③数据流(Data Flow)

1).Engine打开一个网站,找到处理该网站的Spider并向该Spider请求第一个要爬取的URL(s);

2).Engine从Spider中获取到第一个要爬取的URL,将其放入Scheduler的URL队列中;

3).Engine向Scheduler请求下一个要爬取的URL;

4).Scheduler返回下一个要爬取的URL给Engine,Engine将URL发送给Downloader;

5)、6).Downloader访问Internet,下载页面;

7).Downloader生成一个该页面的Response,并将其发送给Engine;

8).Engine将Response发送给Spider处理;

9).Spider处理Response并返回爬取到的Item及新URL给Engine,重复上述流程直到URL队列中没有多余URL;

10).Engine将爬取到的Item发送到Item Pipeline。

将整个流程可视化,可以得到如下流程图,该图是按照上文数据流中的顺序进行的。

官方架构图:图中的绿线是数据流向。

3、一些类、文件的作用

①类

1)Spider

class scrapy.spider.Spider

Spider是最简单的spider。每个其他的spider都必须继承自该类(包括Scrapy自带的其他spider以及我们自己编写的spider)。Spider没有提供其他特殊的功能,其作用为1)区分请求给定的start_urls/start_requests;2)根据response调用parse方法。

属性:

name:spider名字的字符串。spider的名字定义了Scrapy如何开始定位(并初始化)spider,所以其必须是唯一的。如果该spider爬取单个网站,一个常见的做法是以该网站名来命名spider。例如spider要爬取mywebsite.com,该spider通常会被命名为mywebsite。

allowed_domains:可选。包含了spider允许爬取的URL List。当OffsiteMiddleware启用时,不在List中指定URL及其子URL中的URL将不会被跟进(即爬取的URL必须与该List中的URL有相同的前缀)。

start_urls:URL List。当没有特定的URL时,spider将从该List中开始进行爬取。因此,第一个被获取到的页面的URL必将是该List其中之一,后续URL将会从获取到的数据中提取。

方法:

start_requests():该方法必须返回一个Iterable。该Iterable包含了spider用于爬取的第一个Request。当spider启动爬取且并未制定URL时,该方法将会被调用。该方法的默认实现是使用start_urls的URL来生成Request。如果我们想要修改最初爬取某个网站的Request对象,那么可以重写该方法。例如,如果我们需要在启动时以POST的方式登录某个网站,可以这么写

    def start_requests(self):
return [scrapy.FormRequest('http://www.example.com/login',
formdata={'user': 'john', 'pass': 'secret'},
callback=self.logged_in)]
def logged_in(self,response):
pass

默认未被重写的情况下,该方法返回的Request对象中,parse()作为回调函数,dont_filter参数也被设置为开启。(详情见Reueqst)

make_requests_from_url(url):当spider启动且指定了URL时,该方法将会被调用,且仅仅会被调用一次,因此我们可以将之实现为Generator。该方法接受一个URL并返回用于爬取的Request对象。该方法在初始化Requests时被start_requests调用,也被用于转化URL为Request。

parse(response):当Response没有指定回调函数时,该方法是Scrapy处理下载的Response的默认方法。该方法负责处理Response并返回处理的数据以及跟进的URL。spider对其他的Request的回调函数也有相同的要求。关于返回值,该方法及其他Request回调函数必须返回一个包含Request或Item的Iterable。

参数:response:用于分析的Response

log(message [ ,level , commponent ] ):使用scrapy.log.msg()方法记录(log)message。log中自动带上该spider的name属性。更多数据可以参见Logging。

closed(reason):当spider关闭时,该方法被调用。该方法用于替代signals.connect()来监听spider_closed信号的快捷方式。

以上是最简单的Spider,此外还有其他Spider:Spiders — Scrapy 2.5.0 documentation

2)CrawlSpider

用于爬取URL具有一定规律的网页

3)Response

Scrapy中的response对象的属性、方法

属性 说明 类型
url HTTP响应的URL str
status 响应状态码 int
headers 响应头部,可以用get或getlist方法访问 类Dict
body 响应正文 bytes
text

文本形式的响应正文

response.text = response.body.decode(response.encoding)
str
encoding   响应正文的编码  
request  产生该响应的Request对象   
meta 即response.request.meta,在构造Request对象时,可以将传递给响应处理函函数的信息通过meta参数传入;响应处理函数处理相应时,通过response.meta将信息提取出来  
selector Selector对象用于在Response中提取数据   
方法 说明
xpath(query) 根据XPath路径表达式提取要素
css(query) 根据CSS语法提取要素
urljoin(url) 用于构造绝对url,当传入的url是一个相对地址时,根据response.url计算出相应的绝对url

②文件

通过指令scrapy startproject S创建项目后,会生成以下的文件结构:

S--->scrapy.cfg             #项目的配置文件
S-------->             #该项目的Python模块。之后你将在此加入代码
__init__.py     
items.py        #项目中的Item文件
pipelines.py      #Pipelines文件
settings.py      #设置文件
spiders--->      #放置Spider代码的目录
__init__.py
                   xxx.py #Spider代码

除了目录名S和Spider文件名是我们自定义的外,其他文件都是自动生成的,其中最关键的是pipelines.py和settings.py

1)items.py

存放需要提取元素名。

2)settings.py

BOT_NAME:项目名。

USER_AGENT:该项默认是注释掉的,但是由于现在的网站访问时都需要User-Agent,所以需要我们手动填充该项。

ROBOTSTXT_OBEY:是否遵循机器人协议,默认True,需要修改为False,否则很多东西爬不了(该项待验证)。

CONCURRENT_REQUESTS:最大并发数;同时允许开启多少个爬虫线程。

DOWNLOAD_DELAY:下载延迟时间;单位s,默认3s,即爬一个停3s。有的网站可能会对下载过快的情况进行侦测,从而判断出是爬虫并加以拒绝。

COOKIES_ENABLED:是否保存COOKIES;默认关,开启后可以记录爬取过程中的COOKIE。

DEFAULT_REQUEST_HEADERS:默认请求头;之前我们写了一个USER_AGENT,其实该项就是放在请求头中的。

ITEM_PIPELINES:项目管道;300为优先级,越低爬取的优先级越高。比如我的pipelines.py中写了两个pipeline,一个爬取网页的管道,另一个存数据库的管道,我调整了它们的优先级,如果有爬虫数据,则优先执行库存操作(如果items.py中有需要运行的代码,则该项必须声明)

ITEM_PIPELINES = {
'S.pipelines.BaiduPipeline' : 300,
'S.pipelines.BaiduMysqlPipeline':200
}

该Dict中的两个Key需要均是在要在pipelines.py事先定义好的两个类:

class BaiduPipeline(object):
#爬取网页
def process_item(self,item,spider):
return item class BaiduMysqlPipeline(object):
#将爬取内容存入数据库
def process_item(self,item,spider):
return item

LOG_LEVEL:日志等级;日志登记分级见下表

DEBUG 调试信息
INFO 一般信息
WARNING 警告
ERROR 普通错误
CRITICAL 严重错误

默认为'DEBUG',即所有信息都会被记录进日志中,如果设置为WARNING,则只会记录WARNING、ERROR和CRITICAL

LOG_FILE:日志文件名;格式为 '日志名.log'

3.5、建立Scrapy爬虫项目的流程

创建爬虫和运行爬虫时,要在cmd中用到三段指令:

scrapy startproject 项目名
scrapy genspider 爬虫名 域名
scrapy crawl 爬虫名

其中前两句分别是创建项目和创建爬虫,而创建爬虫也可以通过第②部分中的中的name和start_urls进行创建。

第三句话是爬虫构建好之后,运行爬虫的命令。

①创建项目

在开始爬取之前,需要建立一个新的Scrapy项目。

进入你打算存储代码的目录中,运行以下命令

scrapy startproject 项目名
cd 项目名
scrapy genspider 爬虫名 URL

②编写爬虫代码

Spider是用户编写的用于从网站爬取数据的类。

其包含了一个用于下载初始URL,如何跟进网页中的链接及如何分析页面中的内容,提取生成Item的方法。

为了创建一个Spider,你必须继承scrapy.Spider类,且定义以下三个属性及方法

name:用于区别不同的Spider。

start_urls:包含了Spider在启动时进行爬取的URL列表。因此,第一个被获取到的页面将是其中之一。后续的URL则从初始URL获取到的数据中心提取。

parse():Spider的一个方法。被调用时,每个初始URL完成下载后生成的Response对象将作为唯一的参数传递给该函数。该方法负责解析返回的数据(response data),提取数据(生成Item)以及生成需要进一步处理的URL的Request对象。

③启动爬虫

打开终端进入项目所在文件夹中,运行命令:

scrapy crawl woodenrobo

启动爬虫后就可以看到打印出来当前页所有的文章标题了。

可以把爬取到的内容导出为JSON或者CSV格式,方法是在执行爬虫指令时加入参数-o:

scrapy crawl 爬虫名 -o 文件名.csv
scrapy crawl 爬虫名 -o 文件名.json

对于JSON文件,需要在setting.py文件中设置编码格式,否则会乱码:

FEED_EXPORT_ENCODING = 'UTF-8'

启动爬虫时的程序运行流程:

Scrapy为Spider的start_urls属性中的每个URL创建了Request对象,并将parse方法作为回调函数赋值给requests,而requests对象经过Scheduler的调度,执行生成response对象并送回给parse()方法进行解析,所以url的改变是靠回调函数实现的。

yield scrapy.Request(self.url,callback=self.parse)

4、实例

①提取百度首页的标题title

现在看第一个Spider代码,保存位置为S2\Spiders目录下,名字取为baidu.py,目的是使用XPath提取百度首页的标题title

import scrapy

class BaiduSpider(scrapy.Spider):
name = 'baidu'
allowed_domains = ['www.baidu.com']
start_urls = ['http://www.baidu.com/'] def parse(self, response):
tile=response.xpath('//html/head/title/text()')
print(tile)

打开cmd终端,输入

scrapy crawl baidu

就可以看到一大堆输出信息,其中就包含了我们需要的内容。

然而,使用终端运行太麻烦了,而且不能提取数据,我们写一个运行文件作为程序的入口:

from scrapy import cmdline

cmdline.execute('scrapy crawl baidu'.split())

这段话可以写在另一个py文件或者spider.py文件中,直接运行这句话所在的py文件就可以了。

②爬取腾讯视频中的电影信息

1)

创建项目,将爬虫项目命名为TX;

创建爬虫,爬虫命名为txms,爬虫的start_url设置为v.qq.com

scrapy startproject TX
cd TX
scrapy genspider txs v.qq.com

2)修改setting

修改三项:

ROBOTSTXT_OBEY:机器人项

DOWNLOAD_DELAY:下载间隙

DEFAULT_REQUEST_HEADERS:请求头,需要添加一个User-Agent

ROBOTSTXT_OBEY = False
DOWNLOAD_DELAY = 1
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36'
}

3)确认要提取的数据,Item项

Item定义你要提取的内容(定义数据结构),比如我提取的内容为电影名和电影描述,我就创建两个变量(每有一个需要提取的内容,就要在items.py中新建一个变量)。Field方法实际上是创建一个Dict,给Dict添加一个Key,暂时不赋值,等待提取数据后再赋值。

下面的Item结构可以表示为:{ 'name':'' ; 'description':'' }

#items.py

import scrapy

class TXItem(scrapy.Item):
name=scrapy.Field()
description=scrapy.Field()

4)写爬虫程序

我们要写的部分是parse方法中的内容,重点在于如何写XPath。

我们要爬取的网页的URL为https://v.qq.com/channel/movie,页面如下:

from scrapy import Request
from scrapy import Spider
from TX.items import TXItem class TxsSpider(Spider):
name = 'txs'
allowed_domains = ['v.qq.com']
start_urls = ['https://v.qq.com/channel/movie'] def parse(self, response):
item=TXItem()
movies=response.xpath('//div[@id="movie_v3_new"]//div[@class="list_item "]')
for movie in movies:
item['name']=movie.xpath('.//div/a/text()').extract()[0]
item['description']=movie.xpath('.//div/div/text()').extract()[0]
yield item

5)、运行爬虫,保存爬取到的数据

scrapy crawl tms -o TX.csv

这一部分代码的解释,请看Scrapy(二)最后一部分

Python:Scrapy(一) 基础知识与实例的更多相关文章

  1. Python进阶----计算机基础知识(操作系统多道技术),进程概念, 并发概念,并行概念,多进程实现

    Python进阶----计算机基础知识(操作系统多道技术),进程概念, 并发概念,并行概念,多进程实现 一丶进程基础知识 什么是程序: ​   程序就是一堆文件 什么是进程: ​   进程就是一个正在 ...

  2. Python开发(一):Python介绍与基础知识

    Python开发(一):Python介绍与基础知识 本次内容 一:Python介绍: 二:Python是一门什么语言 三:Python:安装 四:第一个程序 “Hello world” 五:Pytho ...

  3. 基于Python的Flask基础知识

    Flask简介 Flask 是一个使用 Python 编写的轻量级 Web 应用程序框架.Armin Ronacher带领一个名为Pocco的国际Python爱好者团队开发了Flask. 下面我们简单 ...

  4. Python第一章-基础知识

    第一章:基础知识 1.1 安装python.     直接官网下载最新的python然后默认安装就可以了,然后开始菜单里找到pyhton *.*.* Shell.exe运行python的交互shell ...

  5. Python音频处理基础知识,这不是轻轻松松~~~

    大家好鸭,我是小熊猫 咱今天来讲一讲音频处理的基础知识上才艺~~~ 1.声音的基础 2.python读取.wav音频 欢迎加入白嫖Q群:660193417### import wave import ...

  6. python这不是有手就行?——python音频处理基础知识

    大家应该都知道声音的基础吧? 啊不知道当我没说吧~~~ 1.声音的基础 2.python读取.wav音频 Python学习交流Q群:660193417#### import wave import s ...

  7. Python之进程 基础知识 上

    阅读目录 理论知识 操作系统背景知识 什么是进程 进程调度 进程的并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 在python程序中的进程操作 multiprocess模块 进程的创建和mu ...

  8. Python程序设计1——基础知识

    1 Python脚本设计简介 1.1 输出"Hello World" 和一般的语言一样,运行python程序有两种方式,一种是GUI交互式命令,一种是通过脚本文件,前者适合小型简单 ...

  9. Python开发——1.基础知识

    一.开发 开发语言分为高级语言和低级语言 高级语言:Python.Java.PHP.C++.C#.GO.Ruby等:低级语言:C.汇编语言. 高级语言对应的是字节码,是将代码编译成字节码,然后交给机器 ...

随机推荐

  1. Kubernetes 微服务最佳实践

    本文由个人笔记 ryan4yin/knowledge 整理而来 本文主要介绍我个人在使用 Kubernetes 的过程中,总结出的一套「Kubernetes 配置」,是我个人的「最佳实践」. 其中大部 ...

  2. Kubernetes常见的部署方案(十四)

    一.常见的部署方案 滚动更新 服务不会停止,但是整个pod会有新旧并存的情况. 重新创建 先停止旧的pod,然后再创建新的pod,这个过程服务是会间断的. 蓝绿 (无需停机,风险较小) 部署v1的应用 ...

  3. Elasticsearch (1) 文档操作

    本文介绍如何在Elasticsearch中对文档进行操作. 1.检查Elasticsearch及Kibana运行是否正常 在浏览器输入192.168.6.16:9200,有如下输出则说明Elastic ...

  4. 「YNOI2016」自己的发明

    「YNOI2016」自己的发明 不换根 基本的莫队吧... 子树直接转到dfs序上. 其余部分可以见 「SNOI2017」一个简单的询问. 换根 根root,查询x,分3种: root不在x子树内,按 ...

  5. 关于CALayer的疑惑

  6. 有了Autolayout的UILabel

    在没有Autolayout之前,UILabel的文字内容总是居中显示,导致顶部和底部会有一大片空缺区域 有Autolayout之后,UILabel的bounds默认会自动包住所有的文字内容,顶部和底部 ...

  7. js 数组map用法 Array.prototype.map()

    map 这里的map不是"地图"的意思,而是指"映射".[].map(); 基本用法跟forEach方法类似: array.map(callback,[ thi ...

  8. js实现网页中英文翻译

    1,html 2,metrics.js 3,需要 http://www.microsoftTranslator.com/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKk ...

  9. JMeter使用流程

    JMeter使用流程 首先我们要新建一个线程组,线程组的作用模拟多个访问对象,对系统可以进行压力测试 添加"HTTP Cookie管理器": 添加"Http请求默认值&q ...

  10. HTTP缓存小结

    介绍 提到页面优化,浏览器缓存必定是一个绕不过的话题,判断一个网站的性能最直观的就是看网页打开的速度,而提高网页反应速度的一个方式就是使用缓存.一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟, ...