学习自:

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. Python3.7.3 + pycharm安装

    Python3.7.3下载地址: https://www.python.org/ https://www.python.org/getit/ Pycharm: http://www.jetbrains ...

  2. JavaScript之Promise实现原理(手写简易版本 MPromise)

    手写 Promise 实现 Promise的基本使用 Promise定义及用法详情文档:Promise MAD文档 function testPromise(param) { return new P ...

  3. Arduino+ESP32 之 驱动GC9A01圆形LCD(一),基于Arduino_GFX库

    最近买了一块圆形屏幕,驱动IC是GC9A01,自己参考淘宝给的stm32的驱动例程, 在ubuntu下使用IDF开发ESP32,也在windows的vscode内安装IDF开发ESP32,虽然都做到了 ...

  4. 布客·ApacheCN 翻译校对活动进度公告 2020.5

    注意 请贡献者查看参与方式,然后直接在 ISSUE 中认领. 翻译/校对三个文档就可以申请当负责人,我们会把你拉进合伙人群.翻译/校对五个文档的贡献者,可以申请实习证明. 请私聊片刻(52981514 ...

  5. JavaScript的内存管理

    JavaScript的内存管理 1.什么是内存管理? 在了解JavaScript的内存管理之前,可以先大致熟悉一下什么是内存管理,不管什么样的编程语言,在其代码执行的过程中都是需要为其分配内存的. 不 ...

  6. Thread的打断

    常用方法 public void interrupt() t.interrupt() 打断t线程(设置t线程某给标志位f=true,并不是打断线程的运行),不能打断正在竞争锁的线程. public b ...

  7. HttpClient 的Timeout waiting for connection from pool

    Timeout waiting for connection from pool 异常 httpClient大家用到地方会很多,先简单描述一下几个关键配置的意义 httpClient版本为4.5.1 ...

  8. Docker容器启动失败 Failed to start Docker Application Container Engine

    1.在k8s mster节点执行 1.kubectl get nodes 发现node节点没起来 [root@guanbin-k8s-master ~]# kubectl get nodes NAME ...

  9. Centos下安装配置WordPress与nginx教程

    感谢大佬:https://www.howtoing.com/how-to-install-wordpress-with-nginx-on-centos-6-2 WordPress是一个免费和开源网站和 ...

  10. Spring与Struts2整合时action自动注入的问题

    当Struts和Spring框架进行整合时,原本由action实例化对象的过程移交给spring来做(这个过程依赖一个叫struts2-spring-plugin的jar包,这个包主要的功能就是实现刚 ...