利用scrapy进行持久化存储

scrapy框架

  • 架构

    • 爬虫文件夹:spider
    • 管道文件: pipelines.py
    • 中间件文件: middlewares.py
    • item模块:items.py
    • 设置文件 :settings.py
  • 相关命令

    • 创建scrapy项目:scrapy startproject 项目名
    • 创建爬虫文件:
      • cd 项目名
      • scrapy genspider 爬虫文件名 www.xxx.com
    • 执行爬虫文件:scrapy crawl 爬虫文件名
    • 不查看日志:scrapy crawl 爬虫文件名 -nolog 
    • 项目初始化:
      • 配置settings:
        • UA伪装
        • 关闭robot.txt协议
        • 添加日志配置LOG_LEVEL
    • 持久化存储方式
      • 基于终端指定的存储
        • scrapy crawl 爬虫文件 -o xxx.csv(json,xml,csv....)
      • 基于管道持久化存储
        • 文件存储
        • MySql存储
        • Redis存储 

需求1:scrapy爬取不得姐首页中段子的内容和作者

1.先创建一个爬虫项目,在命令行输入

scrapy startproject budejiepro

进入项目目录,创建一个爬虫文件命名budejie

cd budejiepro
scrapy genspider first www.xxx.com

在项目的spiders中生成一个first.py的爬虫文件

2.开始爬虫之间我们先将setting.py文件中的`ROBOTSTXT_OBEY=True`改成**False**,否则scrapy会根据robots 协议来拒绝访问,我们还需要设置ua,这个准备爬取网站钱需要做的!!

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 
Safari/537.36'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False

3.我们打开爬虫文件budejie.py,开始对网页进行爬取
我们一开始配置的爬取网页的起始url为www.xxx.com,这里我们需要手动去修改,也可以一开始就配置正确的url,这里类下的allowed_domains是指允许自动发送请求的域名,只要在这个列表里面的url,scrapy才会自动发送请求,start_urls是起始url,scrapy会自动向起始url发送请求,并且获取响应数据.parse方法是用来实现解析数据,我们接下来的数据解析都在这里面完成
- 我们分析段子和作者所在的标签位置,这里就不做累赘说明,和之前的通用爬虫步骤一样

2c429432071f59a80c5f8e7cacdee54a.png  

但是要注意的是,我们爬取出来的作者和段子打印出来的数据会发现他是放在一个selector的选择器内,且这个选择器是放在一个列表内的,所以我们需要利用extract()来取93249c5c0de25254874c8e11e240e6a7.png  

author = li.xpath('./div[1]/div[2]/a/text()').extract()[0]
author = li.xpath('./div[1]/div[2]/a/text()').extract_first()

d1552232a1e01d23719ec9ea230b6358.png

问题:持久化存储,目前数据只在终端出现 ,返回的数据如果要进行持久化存储,需要封装到一个字典里面

# -*- coding: utf-8 -*-
import scrapy

class BudejieSpider(scrapy.Spider):
    name = 'budejie'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['http://www.budejie.com/text/']

    def parse(self, response):
        """
        在这里实现数据解析
        :param response:
        :return:
        """
        li_list = response.xpath('//div[@class="j-r-list"]/ul/li')
        name_list = list()
        for li in li_list:
            #xpath解析方法返回的是一个Selected标签,需要使用.extract()方法获取里面的文本数据
            # 如果能够确定返回的列表里面只有一个Selecter标签的话,就可以直接使用extract_first()方法获取文本
            # author = li.xpath('./div[1]/div[2]/a/text()').extract()[0]
            author = li.xpath('./div[1]/div[2]/a/text()').extract_first()
            content = li.xpath('./div[2]/div/a/text()').extract_first()
            # 返回的数据如果要进行持久化存储,需要封装到一个字典里面
            dic ={
                "author":author,
                "content":content
            }
            name_list.append(dic)

        return name_list
scrapy爬取不得姐首页中段子的内容和作者

需求2:需求:scrapy管道持久化储存校花网title和img_url

 - 爬取思路(忽略基本配置等操作)

  1.校花网的爬取其实和前面的不得姐的爬取思路是一致的,这次爬取的难点在于如何管道持久化存储,上面不得姐的例子我们是基于终端指令的持久化存储,通常要将数据封装到一个字典中返回,在通过终端指令的形式写入指定格式的文件中进行持久化操作;现在我们可以轻松的利用scrapy框架为我们设计的高效,便捷的持久化操作,我们可以直接拿来用

  2.管道持久化存储会涉及到两个py文件
    items.py(数据结构模板文件,定义数据属性)
    pipelines.py(管道文件,用来接收数据items,进行持久化操作)
  3 持久化流程
    校花.py爬取到网站数据后,需要将数据封装到items对象中
       我们在校花.py文件中使用yield关键字将items对象提交给pipelines管道持久化操作
    在管道文件中的process_item方法中接收爬虫文件提交过来的item对象,然后编写持久化存储的代码将item对象中存储的数据进行持久化存储
    settings.py配置文件中开启管道

# 首先先在setting.py文件中配置UA伪装,关闭robots.txt协议的日志设置
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False
LOG_LEVLE="ERROR"

#这一步是配置文件中开启管道
ITEM_PIPELINES = {   'xiaohuapro.pipelines.XiaohuaproPipeline': 300,}
import scrapy
from xiaohuapro.items import XiaohuaproItem

class XiaohuaSpider(scrapy.Spider):
    name = 'xiaohua'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['http://www.521609.com/meinvxiaohua/']

    def parse(self, response):
        li_list = response.xpath('//div[@class="index_img list_center"]/ul/li')

        for li in li_list:
            title = li.xpath('./a[2]/text()| ./a[2]/b/text()').extract_first()
            img_url = "http://www.521609.com" + li.xpath('./a[1]/img/@src').extract_first()
            print(title,img_url)
            # 从items.py文件中导入XiaohuaproItem类,并实例化一个item对象
            item = XiaohuaproItem()
            #
            # # 需要将爬取到的数据添加到对象中的属性中,其实可以讲item对象理解成为一个字典,通过字典的草错将数据存储
            item["title"] = title
            item["img_url"] = img_url

            # # 如何将item对象提交到管道?yield生成器知识~~
            # # 只需要使用yield关键字就可以将item对象提交到管道
            # #这个操作必须要放在循环里面,向管道提交多次数据
            #
            yield item
xiaohua.py
import scrapy

class XiaohuaproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    img_url = scrapy.Field()
items.py
import pymysql
import redis

class XiaohuaproPipeline(object):
    f = None
    def open_spider(self,spider):
        print("开始爬虫")
        self.f = open('./xiaohua.txt',"w",encoding="utf-8")

    def process_item(self, item, spider):
        """
        在这里实现管道持久化存储
        由于爬虫文件中会多次向管道提交数据,所以这个方法会执行很多次
        :param item: 就是items.py文件中scrapy.Item类实例化的一个对象
        :param spider:
        :return:
        """
        title = item["title"]
        img_url = item["img_url"]

        self.f.write(title+":"+img_url+"\n")
        return item

    def close_spider(self, spider):
        self.f.close()
        print("结束爬虫")


class MysqlPipeline(object):
    conn = None
    cursor = None
    def open_spider(self,spider):
        print("开始爬虫")
        self.conn = pymysql.Connect(host = "10.0.3.156",port=3306,user="root",password="",db="qishi8",charset="utf8")

    def process_item(self, item, spider):
        """
        在这里实现管道持久化存储
        由于爬虫文件中会多次向管道提交数据,所以这个方法会执行很多次
        :param item: 就是items.py文件中scrapy.Item类实例化的一个对象
        :param spider:
        :return:
        """
        self.cursor = self.conn.cursor()
        title = item["title"]
        img_url = item["img_url"]
        sql = "insert into xiaohua values('{}','{}')".format(title,img_url)
        try:
            self.cursor.execute(sql)
        except Exception as e:
            self.cursor.rollback()
        self.conn.commit()

        return item

    def close_spider(self, spider):
        self.cursor.close()
        self.conn.close()
        print("结束爬虫")
pipelines.py

猜你喜欢

转载自www.cnblogs.com/groundcontrol/p/12716147.html