Scrapy框架的基本组成及功能使用
1.什么是scrapy?
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。框架的本质就是集成各种功能、具有很强通用性的项目模板。
2.安装
Linux:
pip3 install scrapy
Windows:===》见Twisted安装
a. pip3 install wheel
b. 下载twisted http:
/
/
www.lfd.uci.edu
/
~gohlke
/
pythonlibs
/
#twisted
c. 进入下载目录,执行 pip3 install Twisted‑
17.1
.
0
‑cp35‑cp35m‑win_amd64.whl
d. pip3 install pywin32
e.
pip3 install scrapy
- scrapy crawl qiubai -o qiubai.json
- scrapy crawl qiubai -o qiubai.xml
- scrapy crawl qiubai -o qiubai.csv
- project_name/
- scrapy.cfg:
- project_name/
- __init__.py
- items.py
- pipelines.py
- settings.py
- spiders/
- __init__.py
应用名称.py- scrapy.cfg 项目的主配置信息。(真正爬虫相关的配置信息在settings.py文件中)
- items.py 设置数据存储模板,用于结构化数据,如:Django的Model
- pipelines 数据持久化处理
- settings.py 配置文件,如:递归的层数、并发数,延迟下载等
- spiders 爬虫目录,如:创建文件,编写爬虫解析规则
执行完创建应用命令后,打开文件会显示出如下页面
- # -*- coding: utf-8 -*-
- import scrapy
- class QiubaiSpider(scrapy.Spider):
- name = 'qiubai' #应用名称
- #允许爬取的域名(如果遇到非该域名的url则爬取不到数据)
- allowed_domains = ['https://www.qiushibaike.com/']
- #起始爬取的url
- start_urls = ['https://www.qiushibaike.com/']
- #访问起始URL并获取结果后的回调函数,该函数的response参数就是向起始的url发送请求后,获取的响应对象.该函数返回值必须为可迭代对象或者NUll
- def parse(self, response):
- print(response.text) #获取字符串类型的响应内容
- print(response.content)#获取字节类型的相应内容
修改settings相关配置
- 修改内容及其结果如下:
- 19行:USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' #伪装请求载体身份
- 22行:ROBOTSTXT_OBEY = False #可以忽略或者不遵守robots协议 ==》防君子不防小人协议 需要改为False,不需要遵守协议
scrapy对糗事百科进行爬取
- # -*- coding: utf-8 -*-
- import scrapy
- class QiubaiSpider(scrapy.Spider):
- name = 'qiubai'
- allowed_domains = ['https://www.qiushibaike.com/']
- start_urls = ['https://www.qiushibaike.com/']
- def parse(self, response):
- #xpath为response中的方法,可以将xpath表达式直接作用于该函数中
- odiv = response.xpath('//div[@id="content-left"]/div')
- content_list = [] #用于存储解析到的数据
- for div in odiv:
- #xpath函数返回的为列表,列表中存放的数据为Selector类型的数据。我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。
- author = div.xpath('.//div[@class="author clearfix"]/a/h2/text()')[0].extract()
- content=div.xpath('.//div[@class="content"]/span/text()')[0].extract()
- #将解析到的内容封装到字典中
- dic={
- '作者':author,
- '内容':content
- }
- #将数据存储到content_list这个列表中
- content_list.append(dic)
- return content_list
执行爬虫程序并保存文件
- 执行输出指定格式进行存储:将爬取到的数据写入不同格式的文件中进行存储
- scrapy crawl qiubai -o qiubai.json
- scrapy crawl qiubai -o qiubai.xml
- scrapy crawl qiubai -o qiubai.csv
- 二.scrapy持久化操作:将爬取到糗百数据存储写入到文本文件中进行存储
- # -*- coding: utf-8 -*-
- import scrapy
- class QiubaiSpider(scrapy.Spider):
- name = 'qiubai'
- allowed_domains = ['https://www.qiushibaike.com/']
- start_urls = ['https://www.qiushibaike.com/']
- def parse(self, response):
- #xpath为response中的方法,可以将xpath表达式直接作用于该函数中
- odiv = response.xpath('//div[@id="content-left"]/div')
- with open('./data.txt', 'w') as fp:
- for div in odiv:
- #xpath函数返回的为列表,列表中存放的数据为Selector类型的数据。我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。
- author = div.xpath('.//div[@class="author clearfix"]/a/h2/text()')[0].extract()
- content=div.xpath('.//div[@class="content"]/span/text()')[0].extract()
- #持久化存储爬取到的内容
- fp.write(author + ':' + content + '\n')
注意:上述代码表示的持久化操作是我们自己通过IO操作将数据进行的文件存储。在scrapy框架中已经为我们专门集成好了高效、便捷的持久化操作功能,我们直接使用即可。要想使用scrapy的持久化操作功能,我们首先来认识如下两个文件:
items.py:数据结构模板文件。定义数据属性。
pipelines.py:管道文件。接收数据(items),进行持久化操作。
持久化流程:
1.爬虫文件爬取到数据后,需要将数据封装到items对象中。
2.使用yield关键字将items对象提交给pipelines管道进行持久化操作。
3.settings.py配置文件中开启管道
三.小试牛刀:将糗事百科首页中的段子和作者数据爬取下来,然后进行持久化存储
- # -*- coding: utf-8 -*-
- import scrapy
- from secondblood.items import SecondbloodItem
- class QiubaidemoSpider(scrapy.Spider):
- name = 'qiubaiDemo'
- allowed_domains = ['www.qiushibaike.com']
- start_urls = ['http://www.qiushibaike.com/']
- def parse(self, response):
- odiv = response.xpath('//div[@id="content-left"]/div')
- for div in odiv:
- # xpath函数返回的为列表,列表中存放的数据为Selector类型的数据。我们解析到的内容被封装在了Selector对象中,需要调用extract()函数将解析的内容从Selecor中取出。
- author = div.xpath('.//div[@class="author clearfix"]//h2/text()').extract_first()
- author = author.strip('\n')#过滤空行
- content = div.xpath('.//div[@class="content"]/span/text()').extract_first()
- content = content.strip('\n')#过滤空行
- #将解析到的数据封装至items对象中
- item = SecondbloodItem()
- item['author'] = author
- item['content'] = content
- yield item#提交item到管道文件(pipelines.py)
items.py
- import scrapy
- class SecondbloodItem(scrapy.Item):
- # define the fields for your item here like:
- # name = scrapy.Field()
- author = scrapy.Field() #存储作者
- content = scrapy.Field() #存储段子内容
管道文件:pipelines.py
- # -*- coding: utf-8 -*-
- # Define your item pipelines here
- #
- # Don't forget to add your pipeline to the ITEM_PIPELINES setting
- # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
- class SecondbloodPipeline(object):
- #构造方法
- def __init__(self):
- self.fp = None #定义一个文件描述符属性
- #下列都是在重写父类的方法:
- #开始爬虫时,执行一次
- def open_spider(self,spider):
- print('爬虫开始')
- self.fp = open('./data.txt', 'w')
- #因为该方法会被执行调用多次,所以文件的开启和关闭操作写在了另外两个只会各自执行一次的方法中。
- def process_item(self, item, spider):
- #将爬虫程序提交的item进行持久化存储
- self.fp.write(item['author'] + ':' + item['content'] + '\n')
- return item
- #结束爬虫时,执行一次
- def close_spider(self,spider):
- self.fp.close()
- print('爬虫结束')
配置文件:settings.py
- #开启管道
- ITEM_PIPELINES = {
- 'secondblood.pipelines.SecondbloodPipeline': 300, #300表示为优先级,值越小优先级越高
- }
Scrapy递归爬取多页数据:
需求:将糗事百科所有页码的作者和段子内容数据进行爬取切持久化存储
- # -*- coding: utf-8 -*-
- import scrapy
- from qiushibaike.items import QiushibaikeItem
- # scrapy.http import Request
- class QiushiSpider(scrapy.Spider):
- name = 'qiushi'
- allowed_domains = ['www.qiushibaike.com']
- start_urls = ['https://www.qiushibaike.com/text/']
- #爬取多页
- pageNum = 1 #起始页码
- url = 'https://www.qiushibaike.com/text/page/%s/' #每页的url
- def parse(self, response):
- div_list=response.xpath('//*[@id="content-left"]/div')
- for div in div_list:
- #//*[@id="qiushi_tag_120996995"]/div[1]/a[2]/h2
- author=div.xpath('.//div[@class="author clearfix"]//h2/text()').extract_first()
- author=author.strip('\n')
- content=div.xpath('.//div[@class="content"]/span/text()').extract_first()
- content=content.strip('\n')
- item=QiushibaikeItem()
- item['author']=author
- item['content']=content
- yield item #提交item到管道进行持久化
- #爬取所有页码数据
- if self.pageNum <= 13: #一共爬取13页(共13页)
- self.pageNum += 1
- url = format(self.url % self.pageNum)
- #递归爬取数据:callback参数的值为回调函数(将url请求后,得到的相应数据继续进行parse解析),递归调用parse函数
- yield scrapy.Request(url=url,callback=self.parse)
scrapy组件
- 引擎(Scrapy)
用来处理整个系统的数据流处理, 触发事务(框架核心) - 调度器(Scheduler)
用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址 - 下载器(Downloader)
用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的) - 爬虫(Spiders)
爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面 - 项目管道(Pipeline)
负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
* 解释:引擎首先会将爬虫文件中的起始url获取,并且提交到调度器中。如果需要从url中下载数据,则调度器会将url通过引擎提交给下载器,下载器根据url去下载指定内容(响应体)。下载好的数据会通过引擎移交给爬虫文件,爬虫文件可以将下载的数据进行指定格式的解析。如果解析出的数据需要进行持久化存储,则爬虫文件会将解析好的数据通过引擎移交给管道进行持久化存储。
面试题:如果最终需要将爬取到的数据值一份存储到磁盘文件,一份存储到数据库中,则应该如何操作scrapy?
答:管道文件中的代码为:
- #该类为管道类,该类中的process_item方法是用来实现持久化存储操作的。
- class DoublekillPipeline(object):
- def process_item(self, item, spider):
- #持久化操作代码 (方式1:写入磁盘文件)
- return item
- #如果想实现另一种形式的持久化操作,则可以再定制一个管道类:
- class DoublekillPipeline_db(object):
- def process_item(self, item, spider):
- #持久化操作代码 (方式1:写入数据库)
- return item
在settings.py开启管道操作代码为:
- #下列结构为字典,字典中的键值表示的是即将被启用执行的管道文件和其执行的优先级。
- ITEM_PIPELINES = {
- 'doublekill.pipelines.DoublekillPipeline': 300,
- 'doublekill.pipelines.DoublekillPipeline_db': 200,
- }
- #上述代码中,字典中的两组键值分别表示会执行管道文件中对应的两个管道类中的process_item方法,实现两种不同形式的持久化操作。
五.Scrapy发起post请求:
- 问题:在之前代码中,我们从来没有手动的对start_urls列表中存储的起始url进行过请求的发送,但是起始url的确是进行了请求的发送,那这是如何实现的呢?
- 解答:其实是因为爬虫文件中的爬虫类继承到了Spider父类中的start_requests(self)这个方法,该方法就可以对start_urls列表中的url发起请求:
- def start_requests(self):
- for u in self.start_urls:
- yield scrapy.Request(url=u,callback=self.parse)
【注意】该方法默认的实现,是对起始的url发起get请求,如果想发起post请求,则需要子类重写该方法。
- 重写start_requests方法,让其发起post请求:
- def start_requests(self):
- #请求的url
- post_url = 'http://fanyi.baidu.com/sug'
- # 表单数据
- formdata = {
- 'kw': 'wolf',
- }
- # 发送post请求
- yield scrapy.FormRequest(url=post_url, formdata=formdata, callback=self.parse)
Scrapy框架的基本组成及功能使用的更多相关文章
- 爬虫入门之Scrapy 框架基础功能(九)
Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非 ...
- Python爬虫从入门到放弃(十一)之 Scrapy框架整体的一个了解
这里是通过爬取伯乐在线的全部文章为例子,让自己先对scrapy进行一个整理的理解 该例子中的详细代码会放到我的github地址:https://github.com/pythonsite/spider ...
- Python爬虫从入门到放弃(十二)之 Scrapy框架的架构和原理
这一篇文章主要是为了对scrapy框架的工作流程以及各个组件功能的介绍 Scrapy目前已经可以很好的在python3上运行Scrapy使用了Twisted作为框架,Twisted有些特殊的地方是它是 ...
- 安装scrapy框架的常见问题及其解决方法
下面小编讲一下自己在windows10安装及配置Scrapy中遇到的一些坑及其解决的方法,现在总结如下,希望对大家有所帮助. 常见问题一:pip版本需要升级 如果你的pip版本比较老,可能在安装的过程 ...
- 关于使用scrapy框架编写爬虫以及Ajax动态加载问题、反爬问题解决方案
Python爬虫总结 总的来说,Python爬虫所做的事情分为两个部分,1:将网页的内容全部抓取下来,2:对抓取到的内容和进行解析,得到我们需要的信息. 目前公认比较好用的爬虫框架为Scrapy,而且 ...
- Python使用Scrapy框架爬取数据存入CSV文件(Python爬虫实战4)
1. Scrapy框架 Scrapy是python下实现爬虫功能的框架,能够将数据解析.数据处理.数据存储合为一体功能的爬虫框架. 2. Scrapy安装 1. 安装依赖包 yum install g ...
- python scrapy框架爬虫遇到301
1.什么是状态码301 301 Moved Permanently(永久重定向) 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一.如果可能,拥有链接编 ...
- Scrapy框架
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的, 也可以 ...
- python爬虫入门(六) Scrapy框架之原理介绍
Scrapy框架 Scrapy简介 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬 ...
随机推荐
- <十四>UML核心视图静态视图之类图和包图
一:类图(行为类和实体类) --->类图用于展示系统中的类及其相互之间的关系 --->概念层类图 --->说明层类图 二:概念层类图 --->概念层的观点认为:在这个层次的 ...
- 错误 128 无法将类型“string”隐式转换为“System.Windows.Forms.DataGridViewTextBoxColumn”
原因是DataGridView中列的Name属性值和DataPropertyName属性值一样,比如Name="CardID",DataPropertyName="Car ...
- nagios对windows流量的检测
windows下用于和 nagios 整合监控的方式主要有三种:nsclient++ .nrpe_nt.SNMP.三者各自的特点主要如下: 1.nsclient++比较成熟稳定,文档也丰富,内置很多了 ...
- javascript runat server
<script runat="server"> protected void SubmitBtn_Click(object sender, EventArgs e) { ...
- JQuery学习笔记(三)遍历 DOM
遍历 DOM jQuery 提供了多种遍历 DOM 的方法.遍历方法中最大的种类是树遍历(tree-traversal). 向上父节点parent,向下子节点child,同胞next和pre 缩写搜索 ...
- 利用jstack定位典型性能问题实例
此文已由作者朱笑天授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 问题的起因是笔者在一轮性能测试的中,发现某协议的响应时间很长,去观察哨兵监控里的javamethod监控可以 ...
- 51nod 1278【贪心】
主要这道题没有包含的情况,所以直接搞个左端,然后对于每个二分求一下>right的最近的位置j,那么ans就会增加 j 以后的: #include <cstdio> #include ...
- Untiy一些方法前特殊标签记录
[ExecuteInEditMode] // Make code live-update even when not in play mode [ContextMenu("Execute&q ...
- 从图(Graph)到图卷积(Graph Convolution):漫谈图神经网络模型 (一)
本文属于图神经网络的系列文章,文章目录如下: 从图(Graph)到图卷积(Graph Convolution):漫谈图神经网络模型 (一) 从图(Graph)到图卷积(Graph Convolutio ...
- 类的property特性
目录 什么是 property特性 简单示例 property属性的两种方式 装饰器 类属性方式 property+类的封装 应用 私有属性添加getter和setter方法 使用property升级 ...