python爬虫——scrapy框架
1、介绍
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,爬虫中封装好的一个明星框架。功能呢:高性能的持久化存储,异步的数据下载,高性能的数据解析,分布式。对于框架的学习,重点是要学习其框架的特性、各个功能的用法即可。
由五大核心组件组成:python爬虫——scrapy框架五大核心组件
2、scrapy框架的环境安装
-
(1)mac or linux:
pip install scrapy -
(2)windows:
- pip install wheel
- 下载twisted(根据对应的python版本选择),下载地址为:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
- 安装twised: pip install Twisted‑20.3.0‑cp36‑cp36m‑win_amd64.whl
- pip install pywin32
- pip install scrapy
3、scrapy框架的基本使用
(1)创建一个工程
确定好目录文件夹后,在终端命令行界面上输入:
scrapy startproject xxxxx
例如:scrapy startproject firstBlood
创建工程
(2)在spiders子目录中创建一个爬虫文件
进入到工程文件的目录下,输入命令:
scrapy genspider spiderName www.xxxx.com
可自动创建到spiders目录下
在spiders/pyache/spiderName.py中更改为
import scrapy
class SpidernameSpider(scrapy.Spider):
#爬虫文件的名称,就是爬虫源文件的一个唯一标识
name = 'spiderName'
#允许的域名:用来限定start_urls列表中哪些url可以进行请求发送
# allowed_domains = ['www.baidu.com']
#起始的url列表:该列表中存放的url会被scrapy自动的请求发送
start_urls = ['http://www.baidu.com/','https://www.sogou.com']
#用作于数据解析:response参数表示的是请求成功后对应的响应对象,解析start_urls中的内容
def parse(self, response):
print(response)
注:一般情况下注释掉allowed_domains
(3)执行工程
在__spiders__文件下的__init__.py中将ROBOTSTXT_OBEY
改为ROBOTSTXT_OBEY=False
,可关闭robots协议。
之后在命令行窗口输入
scrapy crawl spiderName
可显示执行情况。
输入scrapy crawl spiderName --nolog
可只显示结果,不显示其余日志
若有报错时,想输出报错信息,可在__init__.py中添加LOG_LEVEL = 'ERROR'
之后输入scrapy crawl spiderName --nolog
时若有错,便可以出现错误信息。
注:LOG_LEVEL为生成日志的等级,有DEBUG、INFO、WARNING、ERROR
Log 日志级别
4、scrapy数据解析
应用案例
python爬虫——基于scrapy框架爬取糗事百科上的段子内容
5、scrapy持久化存储
(1)基于终端指令
- 要求:只可以将parse方法的返回值存储到本地的文本文件中
- 注意:持久化存储对应的文本文件类型只可以存储:
'json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle'
类型 - 指令:scrapy crawl xxx -0 filePath
- 优点:简洁、高效、便捷
- 缺点:局限性比较强(数据只可以存储到指定后缀的文本文件中)
应用案例
将qiubai.py
中的内容改为:
import scrapy
class QiubaiSpider(scrapy.Spider):
name = 'qiubai'
# allowed_domains = ['www.xxx.com']
start_urls = ['https://www.qiushibaike.com/text/']
def parse(self, response):
#解析:作者的名称+段子的内容
div_list = response.xpath('//*[@id="content"]/div/div[2]/div')
print(div_list)
for div in div_list:
#xpath返回的是列表,但是列表元素一定是Selector类型的对象
#extract可以将Selector对象中data参数存储的字符串提取出来
author = div.xpath('./div/a[2]/h2/text()').extract_first()
#列表调用了extract之后,则表示将列表中每一个Selector对象中data对应的字符串提取了出来
content = div.xpath('./a[1]/div//text()').extract()
content = ''.join(content)
dic = {
'author':author,
'content':content
}
all_data.append(dic)
return all_data
输入命令,存储至.csv文件中:scrapy crawl qiubai -o ./qiubai.csv
注:
extract():返回一个包含有字符串数据的列表
extract_first():返回列表中的第一个字符串
使用response.xpath():返回的是一个含有selector对象的列表
(2)基于管道
编码流程:
- 数据解析
- 在item类中定义相关的属性
- 将解析的数据封装存储到item类型的对象
- 将item类型的对象提交给管道进行持久化存储的操作
- 在管道类的process_item中要将其接收到的item对象中存储的数据进行持久化存储操作
- 在配置文件中开启管道
好处:
通用性强
应用案例
(1)在item中定义相关属性
items.py
文件
import scrapy
class QiubaiproItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
author = scrapy.Field()
content = scrapy.Field()
(2)解析数据,将解析到的数据存储到item类型的对象中,然后将其提交给管道
qiubai.py
文件
import scrapy
from qiubaiPro.items import QiubaiproItem
class QiubaiSpider(scrapy.Spider):
name = 'qiubai'
# allowed_domains = ['www.xxx.com']
start_urls = ['https://www.qiushibaike.com/text/']
def parse(self, response):
#解析:作者的名称+段子的内容
div_list = response.xpath('//*[@id="content"]/div/div[2]/div')
#存储所有解析到的数据
all_data = []
for div in div_list:
#xpath返回的是列表,但是列表元素一定是Selector类型的对象
#extract可以将Selector对象中data参数存储的字符串提取出来
author = div.xpath('./div/a[2]/h2/text()').extract_first()
#列表调用了extract之后,则表示将列表中每一个Selector对象中data对应的字符串提取了出来
content = div.xpath('./a[1]/div//text()').extract()
content = ''.join(content)
item = QiubaiproItem()
item['author'] = author
item['content'] = content
#将item提交给管道
yield item
(3)在配置文件中开启管道,将接收到的item对象进行持久化存储
settings.py
文件
ITEM_PIPELINES = {
'qiubaiPro.pipelines.QiubaiproPipeline': 300,
#300表示的是优先级,数值越小优先级越高
}
pipelines.py
文件
from itemadapter import ItemAdapter
class QiubaiproPipeline:
fp = None
#重写父类的一个方法:该方法只在开始爬虫的时候被调用一次
def open_spider(self,spider):
print('开始爬虫......')
self.fp = open('./qiubai.txt','w',encoding='utf-8')
#专门用来处理item类型的对象
#该方法可以接收爬虫文件提交过来的item对象
#该方法每接收到一个item就会被调用一次
def process_item(self, item, spider):
author = item['author']
content = item['content']
self.fp.write(author+':'+content+'\n')
return item
def close_spider(self,spider):
print('结束爬虫!')
self.fp.close()
命令行上执行scrapy crawl qiubai
即可完成爬取即持久化存储工作
知识点:
python中的yield关键字是个什么鬼?它有什么用处?
6、实现翻页效果
- 需求:动态爬取http://pic.netbian.com/4kfengjing中各页面
- 实现方式:
- 将所有页面的url添加到start_urls列表中
- 自行手动进行请求发送(推荐)
- 手动请求发送:
- yield scrapy.Request(url,callback)
注:callback是专门做于数解析
- yield scrapy.Request(url,callback)
- 手动请求发送:
新建一个工程文件DynamicChangePro
,
在其下输入命令行,再创建一个spiders
的文件
scrapy genspider DynamicChange www.xxx.com
更改完setting.py
配置文件的内容后,编写DynamicChange.py
内的代码
import scrapy
class DynamicchangeSpider(scrapy.Spider):
name = 'DynamicChange'
# allowed_domains = ['www.xxx.com']
start_urls = ['http://pic.netbian.com/4kfengjing']
#生成一个通用的url模板(不可变)
url = 'http://pic.netbian.com/4kfengjing/index_%d.html'
page_num = 1
def parse(self, response):
#获取前十页内容
if self.page_num <= 10:
new_url = format(self.url%self.page_num)
self.page_num += 1
#手动请求发送:callback回调函数是专门用作于数据解析
print(new_url)
#以递归的形式编写,可实现动态的获取下一章页面
yield scrapy.Request(url=new_url,callback=self.parse)
执行scrap crawl DynamicChange --nolog
显示效果