首页 > 技术文章 > Scrapy使用

Hedger-Lee 2020-06-09 14:29 原文

Scrapy概述

框架:scrapy,pyspider

就是一个集成了各种功能且具有很强通用性(可以被应用在各种不同的需求中)的一个项目模板.

我们只需要学习框架中封装好的相关功能的使用即可.

scrapy集成了哪些功能:

高性能的数据解析操作,持久化存储操作,高性能的数据下载的操作.....

环境的安装

a. pip3 install wheel

b. 下载twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted

c. 进入下载目录,执行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl

d. pip3 install pywin32

e. pip3 install scrapy

Scrapy使用

scrapy基本使用

  • 创建一个工程:scrapy startproject 工程名称
  • 必须在spiders这个目录下创建一个爬虫文件
    • cd proName
    • scrapy genspider spiderName www.xxx.com
  • 执行工程:scrapy crawl spiderName

创建爬虫文件生成的模板

import scrapy

class FirstcrawlSpider(scrapy.Spider):
    name = 'firstcrawl' # 创建的爬虫文件名称
    # allowed_domains = ['www.xx.com'] # 允许访问的url
    start_urls = ['http://www.xx.com/'] # 要访问的url列表

    def parse(self, response):
        pass

配置文件settings.py分析

是否遵从robots协议

# Obey robots.txt rules
ROBOTSTXT_OBEY = False # 默认为True,需要改成False

是否进行UA伪装

# 添加USER_AGENT配置
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'

设定日志等级

LOG_LEVEL = 'ERROR'
# 默认打印到屏幕终端,配置LOG_FILE则将日志输出到文件中
LOG_FILE = './log.txt'

持久化存储

基于终端指令

特性:只可以将parse方法的返回值存储到本地的磁盘文件中

指令:scrapy crawl spiderName -o filePath

def parse(self, response):
    div_list = response.xpath('//*[@id="content-left"]/div')
    all_data = []
    for div in div_list:
        # author = div.xpath('./div[1]/a[2]/h2/text()')[0].extract()
        author = div.xpath('./div[1]/a[2]/h2/text()').extract_first()
        content = div.xpath('./a[1]/div/span//text()').extract()
        content = ''.join(content)
        dic = {
            'author':author,
            'content':content
        }
        all_data.append(dic)
    return all_data

基于管道

实现流程:

1.数据解析

注意点:scrapy的xpath进行数据解析后返回的列表元素为Selector对象,然后必须通过extract或者extract_first这两个方法将Selector对象中的对应数据取出

2.在item类中定义相关的属性

配置items文件

class QiubaiproItem(scrapy.Item):
    # define the fields for your item here like:
    author = scrapy.Field() 
    #Field可以将其理解成是一个万能的数据类型
    content = scrapy.Field()

3.将解析的数据存储或者封装到一个item类型的对象(items文件中对应类的对象)

# 将解析的数据存储到item对象
item = QiubaiproItem() # 对items文件中的类进行实例化
item['author'] = author
item['content'] = content

4.向管道提交item

数据存储到item对象中后,向管道提交item

 # 将item提交给管道
yield item  

注意点:item一定是提交给了优先级最高的管道类,再由该管道类传递给其它类

5.在管道文件的process_item方法中接收item进行持久化存储

配置pipelines文件

class QiubaiproPipeline(object):
    fp = None
    def open_spider(self,spider):
        print('开始爬虫......')
        self.fp = open('qiushibaike.txt','w',encoding='utf-8')

    #该方法每接收一个item就会调用一次
    def process_item(self, item, spider):
        author = item['author']
        content= item['content']

        self.fp.write(author+':'+content+'\n')
        return item #item是返回给了下一个即将被执行的管道类

    def close_spider(self,spider):
        print('结束爬虫!')
        self.fp.close()

管道类中的process_item方法就是处理传进来的item对象,然后对该对象进行持久化存储,这个方法每次接收一个item对象都会调用一次,上面是写入到文件中,也可以存到数据库中,后面会有介绍。

而这里面的open_spider方法和close_spider方法分别是在爬虫执行之前和执行完成之后调用的。

6.在配置文件中开启管道

管道类写好后,必须要在配置文件中开启管道,否则不生效

ITEM_PIPELINES = {
   'imgPro.pipelines.ImgproPipeline': 300,
}

可以开启多个管道,后面的数字是优先级,数字越小,优先级越高

将一份数据存储到不同的平台

比如可以将一份数据写入文件又可以存到不同的数据库中

分析:

​ 1.管道文件中的一个管道类负责数据的一种形式的持久化存储

​ 2.爬虫文件向管道提交的item只会提交给优先级最高的那一个管道类

而优先级最高的管道类中的process_item方法,会有一个return item,表示的是将

当前管道接收的item返回/提交给下一个即将被执行的管道类

结论:只要编写不同平台的管道类即可

存到mysql数据库

配合pymysql模块操作mysql数据库,对数据进行持久化存储

class MysqlPL(object):
    conn = None
    cursor = None
    
    def open_spider(self,spider):
        self.conn = pymysql.Connect(host='127.0.0.1',port=3306,user='root',password='123',db='spider',charset='utf8')
        print(self.conn)
        
    def process_item(self,item,spider):
        author = item['author']
        content = item['content']

        sql = 'insert into qiubai values ("%s","%s")'%(author,content)
        self.cursor = self.conn.cursor()
        try:
            self.cursor.execute(sql)
            self.conn.commit()
        except Exception as e:
            print(e)
            self.conn.rollback()
        return item
    
    def close_spider(self,spider):
        self.cursor.close()
        self.conn.close()

存到Redis数据库

使用redis模块操作Redis数据库对数据进行持久化存储

注意点:redis如何存入字典对象报错时,可以就换一个redis模块版本

pip install -U redis==2.10.6

class RedisPL(object):
    conn = None
    def open_spider(self,spider):
        self.conn = Redis(host='127.0.0.1',port=6379)
        print(self.conn)
    def process_item(self,item,spider):
        self.conn.lpush('all_data',item)
        

在Scrapy中手动发送请求

手动发送GET请求

scrapy自动发送的都是GET请求,会对start_urls的url依次发送GET请求

使用的场景:爬取多个页码对应的页面源码数据

yield scrapy.Request(url,callback)
# url为要访问的url
# callback为回调函数,对数据进行分析处理

手动发送POST请求

data = { #post请求的请求参数
    'kw':'aaa'
}
yield scrapy.FormRequest(url,formdata=data,callback)
data为要发送的数据,如form表单中的用户名和密码

对start_urls中的url发POST请求,必须重写父类中的start_request方法

def start_requests(self):
    for url in self.start_urls:
        yield scrapy.FormRequest(url,formdata=data,callback=self.parse)

Scrapy五大核心组件

1.引擎(Scrapy)

​ 用来处理整个系统的数据流处理, 触发事务(框架核心)

2.调度器(Scheduler)

​ 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址

3.下载器(Downloader)

​ 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)

4.爬虫(Spiders)

​ 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面

5.项目管道(Pipeline)

​ 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。

推荐阅读