基于Scrapy框架的文件管道实现文件抓取(基于Scrapy框架实现多级页面的抓取)
前言
本文中介绍 如何基于 Scrapy 框架的文件管道实现文件抓取(基于Scrapy框架实现多级页面的抓取),并以抓取 第一PPT 网站的 PPT 模板为例进行展示,同时抓取此网站数据的方式也是对如何使用 Scrapy 框架实现多级页面的抓取进行详解。
正文
1、Scrapy框架抓取文件原理
Scrapy框架 提供了文件管道类 FilesPipeline,来抓取文件,在使用时需要导入from scrapy.pipelines.files import FilesPipeline
,并且重新 get_media_requests() 方法,如果对保存的文件名有要求,则需要重写 file_path() 方法;通过 settings.py 文件中的 FILES_STORE 属性可以设置文件保存路径。
2、Scrapy框架抓取文件实现步骤
-
爬虫文件:将文件链接 yield 到管道
-
管道文件:导入并继承 scrapy 的 FilesPipeline 类,重写get_media_requests() 方法 和 file_path() 方法;
from scrapy.pipelines.files import FilesPipeline class XxxPipeline(FilesPipeline): def get_media_requests(self,xxx): # 把链接交给调度器入队列 def file_path(self,xxx): # 此处生成文件名 return filename
-
settings.py:在全局配置文件中,通过 FILES_STORE=“路径” 指定文件保存的位置。
3、Scrapy框架抓取文件案例
-
案例需求:爬取 第一PPT 网站下栏目分类各个类别的PPT模板并保存到本地
-
一级页面分析:
一级页面url地址:http://www.1ppt.com/xiazai/
提取数据:
li_list = "//div[@class='col_nav clearfix']/ul/li"
第一个不是
1.1>栏目分类名称:./a/text()
1.2>栏目分类链接:./a/@href
:访问资源的路径 需要和 https://www.1ppt.com 进行拼接
-
二级页面分析:进入到了某个栏目分类
提取数据:li_list = "//div/dl/dd/ul[@class='tplist']/li"
2.1>PPT名称:./h2/a/text()
2.2>进入详情页链接:./h2/a/@href
:访问资源的路径 需要和 https://www.1ppt.com 进行拼接
-
三级页面分析:三级页面:进入到了PPT详情页
提取数据:
3.1>进入下载页的链接//ul[@class='downurllist']/li/a/@href
:访问资源的路径 需要和 https://www.1ppt.com 进行拼接
-
四级页面分析:进入到了PPT下载页
提取数据://ul[@class='downloadlist']/li[@class='c1']/a/@href
4.1>具体PPT的下载链接 --> 交给项目管道文件处理
-
创建Scrapy项目:编写items.py文件
这里要明确最后要保存的只有 大分类的名称 及PPT下载链接import scrapy class PptItem(scrapy.Item): # 定义什么? 管道文件需要什么? # 大分类名称、具体PPT文件名、PPT下载链接 parent_name = scrapy.Field() ppt_name = scrapy.Field() download_url = scrapy.Field()
-
编写爬虫文件:
import scrapy from ..items import PptItem import json class PptSpider(scrapy.Spider): name = "ppt" allowed_domains = ["www.1ppt.com"] start_urls = ["http://www.1ppt.com/xiazai/"] def parse(self, response): """ 一级页面的解析函数,提取数据:分类名称和链接 :param response: :return: """ li_list = response.xpath("//div[@class='col_nav clearfix']/ul/li") for li in li_list[1:]: # 从第二个元素开始 item = PptItem() # 创建item对象 item["parent_name"] = li.xpath("./a/text()").get() class_href = "https://www.1ppt.com" + li.xpath("./a/@href").get() # 将class_href交给调度器入队列 yield scrapy.Request(url=class_href, meta={"meta1": item}, callback=self.parse_second_page) def parse_second_page(self, response): """ 二级页面的解析函数,提取数据:PPT名称 & 进入详情页链接 :return: """ # 接受上一个解析函数传过来的meta对象 meta1 = response.meta["meta1"] # 开始解析提取数据 li_list = response.xpath("//div/dl/dd/ul[@class='tplist']/li") for li in li_list: item = PptItem() # 创建item对象 item["parent_name"] = meta1["parent_name"] item["ppt_name"] = li.xpath("./h2/a/text()").get() ppt_info_url = "https://www.1ppt.com" + li.xpath("./h2/a/@href").get() # 将ppt_info_url交给调度器入队列 yield scrapy.Request(url=ppt_info_url, meta={"meta2": item}, callback=self.parse_third_page) def parse_third_page(self, response): """ 三级页面的解析函数,提取数据:进入下载页的链接 :param response: :return: """ meta2 = response.meta["meta2"] enter_download_page = "https://www.1ppt.com" + response.xpath("//ul[@class='downurllist']/li/a/@href").get() # 直接交给调度器入队列 yield scrapy.Request(url=enter_download_page, meta={"item": meta2}, callback=self.parse_fourth_page) def parse_fourth_page(self, response): """ 四级页面的解析函数,提取数据:具体PPT的下载链接 :param response: :return: """ item = response.meta["item"] item["download_url"] = response.xpath("//ul[@class='downloadlist']/li[@class='c1']/a/@href").get() # 一条完整的item数据提取完成,交给管道文件处理 yield item
注意:四级页面中meta参数的使用
-
在管道文件中导入导入并继承 scrapy 的 FilesPipeline类,重写get_media_requests() 方法 和 file_path() 方法:
import os import scrapy from scrapy.pipelines.files import FilesPipeline class PptPipeline(FilesPipeline): def get_media_requests(self, item, info): """ 重写get_media_requests()方法,将文件下载链接交给调度器入队列 :param item: :param info: :return: """ yield scrapy.Request(url=item["download_url"], meta={"item": item}) def file_path(self, request, response=None, info=None, *, item=None): """ 重写file_path(),调整文件保存路径及文件名 :param request: :param response: :param info: :param item: :return: """ item = request.meta["item"] # filename:工作总结PPT/xxxxxxxxxxppt.zip filename = '{}/{}{}'.format( item["parent_name"], item["ppt_name"], os.path.splitext(item["download_url"])[1] ) return filename
-
在全局配置文件中,通过 FILES_STORE=“路径” 指定文件保存的位置
FILES_STORE = "./pptfiles/"
-
创建run.py文件运行爬虫:
from scrapy import cmdline cmdline.execute("scrapy crawl ppt".split())
-
运行效果: