目录结构
一、Scrapy框架简介
1. Scrapy引入
2. Scrapy工作流程
二、搭建Scrapy框架
1. 安装Scrapy
2. 创建一个Scrapy项目
三、案例:利用Scrapy框架爬取某音乐排行榜信息
1. 创建项目:musicSpide
2. 在items.py中定义目标字段:title、artist
3. 利用scrapy命令生成编写爬虫的主体脚本:muSpider.py
4. 编写muSpider.py文件,运行爬虫框架获取响应数据
5. 数据清洗,提取目标数据
四、 利用yield关键字优化数据返回机制(效率)
1. yield关键字
2. yield优化返回数据效率
五、piplines管道实现:对item后期处理&数据保存
1. 编写piplines.py脚本
2. 对管道进行ITEM_PIPELINES设置执行优先级
3. 执行爬虫主体脚本,获取目标数据
六、自动翻页
一、Scrapy框架简介
1. Scrapy引入
Scrapy:是用Python实现爬取网站数据、提取结构性数据而编写的应用框架,用户通过定制开发几个模块就可实现爬虫功能,极大提高工作效率
2. Scrapy工作流程
- Scrapy Engine(引擎):负责Spider、Item Pipeline、Downloader、Scheduler中间的通讯,信号和数据传递
- Scheduler(调度器):负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列入队,当引擎需要时交还给引擎
- Downloader(下载器):负责下载Engine发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine,由引擎交给Spider来处理
- Spider(爬虫):负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler
- Item Pipeline(管道):负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过虑、存储)
- Downloader Middlewares(下载中间件):一个可自定义扩展下载功能的组件
- Spider Middlewares(Spider中间件):一个可自定义扩展和操作引擎和Spider中间件的功能组件。如进入Spider的Responses、从Spider出去的Requests
制作Scrapy爬虫的步骤:
1)新建项目(scrapy startproject xxx):新建一个新的爬虫项目
2)明确目标(编写items.py):明确想要抓取的目标
3)制作爬虫(spiders/xxspider.py):制作爬虫,开始爬取网页
4)存储内容(pipelines.py):设计管道,存储所爬取的内容
二、搭建Scrapy框架
1. 安装Scrapy
pip install Scrapy
安装异常处理,可参看:
[Scrapy安装]error:Microsoft Visual C++ 14.0 is required.Get it with "Microsoft Visual C++ Build Tools"_解决方案
2. 创建一个Scrapy项目
在开始爬取之前,需要创建一个新的Scarpy项目。自定义一个项目目录(如:scrapyProject),然后执行命令:
scrapy startproject {项目名称}
如:scrapy startproject mySpider
执行以上命令所生成的项目目录:
以上,mySpider为项目名称,表现为创建一个"mySpider"命名的文件夹
项目文件夹下主要文件的作用:
mySpider:项目的Python模块,将会从这里引用代码
mySpider / spiders /:存储爬虫代码的目录
mySpider / spiders / items.py:项目的目标文件(决定爬取的内容)
mySpider / spiders / middlewares.py:项目的中间件
mySpider / spiders / pipelines.py:项目的管道文件
mySpider / spiders / settings.py:项目的设置文件
scrapy.cfg:项目的配置文件
三、案例:利用Scrapy框架爬取某音乐排行榜信息
描述:利用Scrapy框架,获取某音乐网站排行榜中的音乐名称、艺术家的信息,然后保存到特定文件中(如:json文件)
被测URL:http://www.htqyy.com/top/hot
第1页:http://www.htqyy.com/top/musicList/hot?pageIndex=0&pageSize=20
第2页:http://www.htqyy.com/top/musicList/hot?pageIndex=1&pageSize=20
第3页:http://www.htqyy.com/top/musicList/hot?pageIndex=2&pageSize=20
1. 创建项目:musicSpide
scrapy startproject musicSpider
2. 在items.py中定义目标字段:title、artist
items.py
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html
import scrapy
# 定义目标数据的字段
class MusicspiderItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title=scrapy.Field() # 音乐名称
artist=scrapy.Field() # 艺术家
3. 利用scrapy命令生成编写爬虫的主体脚本:muSpider.py
进入项目目录:\scrapyProject\musicSpider
执行命令:
# 指定爬取域名的范围,如选用主域名
scrapy genspider muSpider "www.htqyy.com"
已在指定路径下创建好了 muSpider.py文件:
4. 编写muSpider.py文件,运行爬虫框架获取响应数据
muSpider.py
# -*- coding: utf-8 -*-
import scrapy
class MuspiderSpider(scrapy.Spider):
name = 'muSpider' # 爬虫可识别的名称
allowed_domains = ['www.htqyy.com'] # 爬取域名范围
start_urls = ['http://www.htqyy.com/top/musicList/hot?pageIndex=0&pageSize=20'] # 初始url
# 处理响应数据的方法
def parse(self, response):
filename="music.html"
data=response.body # 获取响应内容
open(filename,"wb").write(data) # 写入本地
执行命令:
# muSpider为以上第3步生成的爬虫主文件名
scrapy crawl muSpider
若出现异常提示:ModuleNotFoundError: No module named 'win32api'
则解决方案为:安装pywin32
操作命令:pip install pywin32
Scrapy框架运行OK,如下:
运行scrapy框架后生成所爬取的html数据文件:
5. 数据清洗,提取目标数据
利用正则提取目标字段(音乐名、艺术家)的内容,并存放到列表中,然后利用命令行调动scrapy框架运行生成存放目标内容的json文件
muSpider.py
# -*- coding: utf-8 -*-
import scrapy
import re
# 引入定义目标字段的MusicspiderItem类
from musicSpider.items import MusicspiderItem
class MuspiderSpider(scrapy.Spider):
name = 'muSpider' # 爬虫可识别的名称
allowed_domains = ['www.htqyy.com'] # 爬取域名范围
start_urls = ['http://www.htqyy.com/top/musicList/hot?pageIndex=0&pageSize=20'] # 初始url
# 处理响应数据的方法
def parse(self, response):
# filename="music.html"
data=response.body.decode() # 获取响应内容
# open(filename,"wb").write(data) # 写入本地
items=[] # 存放所有音乐信息的列表
titles=re.findall(r'target="play" title="(.*?)"',data) # 获取所有音乐名
artists=re.findall(r'title="(.*?)" target="_blank"',data) # 获取所有艺术家
for i in range(0,len(titles)):
mu_item=MusicspiderItem() # 创建item对象
mu_item["title"]=titles[i] # 将title内容赋给mu_item
mu_item["artist"]=artists[i] # 将artist内容赋给mu_item
items.append(mu_item) # 将mu_item追加到items列表中
return items
进入目录:\scrapyProject\musicSpider
执行命令:
# muSpider为以上第3步生成的爬虫主文件名
scrapy crawl muSpider -o music.json
执行结果:
以上,生成的json文件,其内容是二进制形式,没有展示出明文中英文字符,因此还需要对json转换处理
getResult.py
import json
with open(r'D:\CI_Env\Python_Test\Python爬虫\Scrapy框架\scrapyProject\musicSpider\music.json',"rb") as f:
result=json.load(f)
f.close()
print(result)
执行结果:
四、 利用yield关键字优化数据返回机制(效率)
1. yield关键字
- 列表联合return:构造完成所有的列表数据,才会将结果数据返回出去
- yield:将方法转换为一个生成器(generator),每构造成功一个item对象,都会将对应数据返回出去;占用内存少,压力相对小
generator.py
def ff1():
list1=[]
for i in range(1,10):
list1.append(i)
return list1
print(ff1())
print("------------------------------")
def ff2():
for i in range(1,10):
yield i
gen=ff2()
print(gen)
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
2. yield优化返回数据效率
muSpider.py
# -*- coding: utf-8 -*-
import scrapy
import re
# 引入定义目标字段的MusicspiderItem类
from musicSpider.items import MusicspiderItem
class MuspiderSpider(scrapy.Spider):
name = 'muSpider' # 爬虫可识别的名称
allowed_domains = ['www.htqyy.com'] # 爬取域名范围
start_urls = ['http://www.htqyy.com/top/musicList/hot?pageIndex=0&pageSize=20'] # 初始url
# 处理响应数据的方法
def parse(self, response):
# filename="music.html"
data=response.body.decode() # 获取响应内容
# open(filename,"wb").write(data) # 写入本地
# items=[] # 存放所有音乐信息的列表
titles=re.findall(r'target="play" title="(.*?)"',data) # 获取所有音乐名
artists=re.findall(r'title="(.*?)" target="_blank"',data) # 获取所有艺术家
for i in range(0,len(titles)):
mu_item=MusicspiderItem() # 创建item对象
mu_item["title"]=titles[i] # 将title内容赋给mu_item
mu_item["artist"]=artists[i] # 将artist内容赋给mu_item
yield mu_item
# items.append(mu_item) # 将mu_item追加到items列表中
# return items
执行命令:
scrapy crawl muSpider -o music2.json
执行结果:
五、piplines管道实现:对item后期处理&数据保存
管道文件:负责对item的后期处理or数据保存。以上是通过Scrapy自带的机制执行命令生成指定的json数据文件,而处理数据提取和清洗后的数据保存工作,可交由管道(piplines)专门处理
1. 编写piplines.py脚本
piplines.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
# 管道1:负责item的后期处理&数据保存
class MusicspiderPipeline(object):
# 定义初始化方法,列出需要初始化的参数(可省略)
def __init__(self):
self.file=open("music.txt","a") # 追加方式写入
# 管道每次接收到item后执行的方法(必须实现,不可省略)
# return item 必须存在
def process_item(self, item, spider):
content=str(item)+"\n"
self.file.write(content) # 写入数据到本地
return item
# 爬取结束时执行的方法(可省略)
def close_spider(self,spider):
self.spider.close()
2. 对管道进行ITEM_PIPELINES设置执行优先级
此时需要留意以上脚本中顶部注释中的提示语"Don't forget to add your pipeline to the ITEM_PIPELINES setting",需要对管道进行ITEM_PIPELINES设置执行优先级(可适用单个or多个管道的场景),如下:
/spiders/settings.py
# 设置管道优先级:0-1000数字越小,优先级越大
ITEM_PIPELINES = {
'musicSpider.pipelines.MusicspiderPipeline': 300,
}
3. 执行爬虫主体脚本,获取目标数据
执行命令:
scrapy crawl muSpider
执行结果:
以上,管道文件piplines.py中process_item()方法,每收到一个item对象,就会执行一次该方法;即每爬取1条数据,都会追加到指定文件中保存
六、自动翻页
对以上项目中的音乐名的翻页列表爬虫案例进行优化,实现多页翻页爬虫的效果
muSpider.py
# -*- coding: utf-8 -*-
import scrapy
import re
# 引入定义目标字段的MusicspiderItem类
from musicSpider.items import MusicspiderItem
class MuspiderSpider(scrapy.Spider):
name = 'muSpider' # 爬虫可识别的名称
allowed_domains = ['www.htqyy.com'] # 爬取域名范围
start_urls = ['http://www.htqyy.com/top/musicList/hot?pageIndex=0&pageSize=20'] # 初始url
# 处理响应数据的方法
def parse(self, response):
# filename="music.html"
data=response.body.decode() # 获取响应内容
# open(filename,"wb").write(data) # 写入本地
titles=re.findall(r'target="play" title="(.*?)"',data) # 获取所有音乐名
artists=re.findall(r'title="(.*?)" target="_blank"',data) # 获取所有艺术家
# 遍历将每一首音乐名、艺术家的存储在列表并返回
for i in range(0,len(titles)):
mu_item=MusicspiderItem() # 创建item对象
mu_item["title"]=titles[i] # 赋值
mu_item["artist"]=artists[i]
yield mu_item # 返回mu_item对象的数据
# 获取当前请求的url,提取出页码信息
url_1=response.url
pat1=r"pageIndex=(\d)"
page=re.search(pat1,url_1).group(1)
# 构造下一页url,发送下一次请求
page=int(page)+1
if page<5: # 限定5页
# 构造下一页url
next_url="http://www.htqyy.com/top/musicList/hot?pageIndex="+str(page)+"&pageSize=20"
# 发送下一次请求
# 在parse方法里发送请求,请求完成后会调用parse方法
yield scrapy.Request(next_url,callback=self.parse)
执行命令:
scrapy crawl muSpider
执行结果:
【总结】
本次通过Scrapy框架实现爬虫目标,相当于Scrapy中各个组件分工合作共同完成一个任务。本次使用组件对应作用为:
items.py:定义目标字段
muSpider.py:定义url链接、清洗响应数据
piplines.py:处理items.py中清洗后的数据,并保存目标数据到指定文件
settings.py:配置文件,如可配置管道的执行优先级