Python

[CP_14] Python爬虫框架01:Scrapy框架创建项

2019-04-15  本文已影响0人  Fighting_001

目录结构

一、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爬虫的步骤:
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关键字

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:配置文件,如可配置管道的执行优先级

上一篇下一篇

猜你喜欢

热点阅读