Scrapy[爬虫专题(17)]

  介绍

  上一篇博客学习的是异步爬虫,打造了爬虫军队,代码要封装为函数形式。

  这一篇博客是讲解 scrapy框架,多用于商业爬虫,代码要封装为多文件形式。

  Scrapy是基于Twisted开发的,是一个异步的框架,性能是TA最大的优势,在这里我们并不需要手动实现异步的代码......  


                                                                                     《目录》

召唤爬虫


环境配置

回顾一下,爬虫 4 大标准步骤:

  1. 获取数据  -- requests
  2. 解析数据  -- bs4
  3. 提取数据  -- Tag
  4. 存储数据  -- csv

 右边是ta们分别对应的模块/对象,今天我们用 scrapy 代替......

   虽然电脑是 Mac,不过我尽量讲全 2 份。

   Windows:

  • win + R,输入 "cmd" 
  • pip install scrapy
  • 进入到 PyCharm 文件夹(dir...)
  • 输入 scrapy startproject name(项目名字,我输入的 dou_ban)
  • 用 PyCharm 打开刚刚创建的文件

   这个过程可能需要一些 cmd 命令,

接着,用 PyCharm 打开新创建的项目名,整个项目长这样:

就是这么牛皮,不仅文件帮我们创建好了,代码也写了部分.....


 Mac:

     command + space ,输入 "终端"

  •      pip3 install virtualenv    
  •      virtualenv venv --python=python3.6
  •      source venv/bin/activate(启动虚拟环境,每次创建scrapy项目都需要在终端输入ta)
  •      pip install scrapy
  •      进入到 PyCharm 文件夹,接着输入 scrapy startproject name(项目名字,我输入的 dou_ban)
  •      用 PyCharm 打开刚刚创建的文件

首先,在 spiders 文件夹里创建一个 file_name.py,这个文件是爬虫的核心即爬虫。

  1. 获取数据  -- file_name.py 
  2. 解析数据  -- file_name.py
  3. 提取数据  -- items.py
  4. 存储数据  -- settings.py

基础样式

 下面逐步学习:

         假设我们创建的项目是 dou_ban (scrapy startproject dou_ban),在 spiders文件夹创建了 豆瓣电影.py。

          接着,再右击 scrapy.crg 创建一个运行dou_ban这个项目的文件(即创建在最外层),名字随意。

        p.s. 如果是商业项目, 这个名字建议取为 main,表示ta是主文件。

项目运行

         在里面输入启动的代码即可:

from scrapy import cmdline
# 从 scrapy 导入 cmdline 模块
cmdline.execute(['scrapy','crawl','dou_ban'])
# 运行 dou_ban 这个项目

        发现,输入后是这样的:

    按住 comand + " , ",即打开设置:

 接着选择一个 py3 的解释器,并在里面下载 scrapy 模块即可。


召唤爬虫

       我们回到 豆瓣电影.py ,在这里面编辑爬虫的核心代码包含 获取数据、解析数据。

       今天编辑代码采用 面向对象的风格,因为在 scrapy 框架里面,这样的代码才显得优美。

       我先写好代码模版......

    获取数据

# 获取数据:定义一个爬虫类DoubanSpider
class DoubanSpider(scrapy.Spider):
# DoubanSpider类继承自scrapy.Spider类
    name = 'only name'
    # 项目名字,唯一的名字,麻辣小龙虾启动代码的名字
    allowed_domains = ['about_URL']
    # 只爬与这个URL里相关的网页,比较一般网页都会有广告页
    start_urls = ['start_url']
    # 从这个URL开始抓取


    def parse(self, response):
    # 解析数据
        print(response.text)
        # 不需要写 requests.get(),scrapy框架已经完成,只需要处理服务器响应的即可。

目标数据的URL规律:

       第 1 页:https://movie.douban.com/top250?start=0&filter=

       第 2 页:https://movie.douban.com/top250?start=25&filter=

       第 3 页:https://movie.douban.com/top250?start=50&filter=

       第 -1 页:  https://movie.douban.com/top250?start=225&filter=

发现改变的这是 start= 后面的数字,从 0 开始,步长 25。

      利用一个循环即可:

              https://book.douban.com/top250?start=' + str(x * 25) + '&filter='

       x 是计数器,之后再把数字转为字符,俩段字符合在一起就是完整的URL。

import scrapy

class DoubanSpider(scrapy.Spider):
    name = 'dou_ban'
    allowed_domains = ['https://movie.douban.com']
    start_urls = []
    for x in range(10):
        url = 'https://movie.douban.com/top250?start=' + str(x * 25) + '&filter='
        start_urls.append(url)

     这样爬虫第一步获取数据已经完成✅✅ 


  解析数据

       解析数据是召唤爬虫模版的第二个函数:parse()

      所有电影信息都在 <ol class="grid_view> 里面,每一个子标签 <li> 就是一部电影。

import scrapy, bs4

# 获取数据
class DoubanSpider(scrapy.Spider):
    name = 'dou_ban'
    allowed_domains = ['https://movie.douban.com']
    start_urls = []
    for x in range(10):
        url = 'https://movie.douban.com/top250?start=' + str(x * 25) + '&filter='
        start_urls.append(url)

# 解析数据
    def parse(self, response):
        # parse是默认处理response的方法
        soup = bs4.BeautifulSoup(response.text, 'html.parser')
        # 用BeautifulSoup解析response

# 提取数据
        min_tag = soup.find('ol', class_="grid_view")
        # 所有电影: 最小父级子标签<ol class="grid_view">
        for data in min_tag.find_all('li'):
            num = data.find('em', class_="").text
            name = data.find('span', class_="title").text
            comment = data.find('span', class_="rating_num").text
            link = data.find('a')['href']

   获取数据、解析数据的确是,提取数据却不是这样的。因为这样的风格太紧凑,我们是多文件,怎能把几个步骤都放到一起呢 ? 

提取数据

    特别是提取数据部分,是爬虫的核心,肯定需要单独处理......

    我们把提取数据部分放在 items.py,但为了让 爬虫文件(豆瓣电影.py)与 items.py 相互通信,在items.py中我们使用 scrapy.Field()传递数据,这是 scrapy 自带的传递数据的通道。

import scrapy

class DouBanItem(scrapy.Item):
# 定义一个类DoubanItem,继承自scrapy.Item,item类是框架自带里面有许多实用的属性、方法
    num = scrapy.Field()
    # 定义电影序号的数据属性
    name = scrapy.Field()
    # 定义电影名字的数据属性
    comment = scrapy.Field()
    # 定义电影信息的数据属性
    link = scrapy.Field()
    # 定义电影链接的数据属性

# items.py 放属性数据,需要什么数据就放什么......

就是怎么简单,这里只需要定义几个提取数据的属性即可。因为是双向通信,豆瓣电影.py(爬虫那个文件),提取数据格式就要改一下,类似字典......

以下是 scrapy 框架的写法,与不用框架写的差距就在这个地方。

from ..items import DouBanItem
# 通信需要引用DouBanItem,ta是items的类。又因为是items在当前文件的上一级目录,所以要用..items,这是一个固定用法。

# 提取数据
        min_tag = soup.find('ol', class_="grid_view")
        for data in min_tag.find_all('li'):
            movie = DouBanItem()
            # 创建一个 movie 类,用于通信
            movie["num"] = data.find('em', class_="").text
            movie["name"] = data.find('span', class_="title").text
            movie["comment"] = data.find('span', class_="rating_num").text
            movie["link"] = data.find('a')['href']
             yield movie
            # 用yield语句把item传递给引擎, 如果这个没写就不会传递数据

以下是不用框架写: 

# 提取数据
        min_tag = soup.find('ol', class_="grid_view")
        for data in min_tag.find_all('li'):
            num = data.find('em', class_="").text
            name = data.find('span', class_="title").text
            comment = data.find('span', class_="rating_num").text
            link = data.find('a')['href']

那么,整个豆瓣电影.py 代码如下:

import scrapy, bs4
from ..items import DouBanItem
# 需要引用DouBanItem,ta是items的类。又因为是items在当前文件的上一级目录,所以要用..items,这是一个固定用法。

# 获取数据
class DoubanSpider(scrapy.Spider):
    name = 'dou_ban'
    allowed_domains = ['https://movie.douban.com']
    start_urls = []
    for x in range(10):
        url = 'https://movie.douban.com/top250?start=' + str(x * 25) + '&filter='
        start_urls.append(url)

# 解析数据
    def parse(self, response):
        soup = bs4.BeautifulSoup(response.text, 'html.parser')

# 提取数据
        min_tag = soup.find('ol', class_="grid_view")
        for data in min_tag.find_all('li'):
            movie = DouBanItem()
            # 实例化DoubanItem这个类。
            movie["num"] = data.find('em', class_="").text
            movie["name"] = data.find('span', class_="title").text
            movie["comment"] = data.find('span', class_="rating_num").text
            movie["link"] = data.find('a')['href']
             yield movie
            # 用yield语句把item传递给引擎, 如果这个没写就不会传递数据

    设置反爬

                srcapy框架把设置放在了 settings.py 里,基本帮我们写好了,只需要改动一些参数即可。

     修改请求头:删除 USER_AGENT 的注释符号,并加深user-agent的内容。

     e.g. 

USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'

更多时候,我们会用到一个第三方库 fake-useragent,随机生成User-Agent,具体安装和用法:

     https://github.com/hellysmile/fake-useragent 

     反 robots协议,将 ROBOTSTXT_OBEY=True 改成 ROBOTSTXT_OBEY=False即可,scrapy默认遵守 robots协议。

   e.g. 

ROBOTSTXT_OBEY = False

   存储数据 

           在 settings.py 文件加一段代码即可,演示 csv 文件存储:

    Windows:

FEED_URI='./storage/data/%(name)s.csv'
FEED_FORMAT='CSV'
FEED_EXPORT_ENCODING='ansi'

    Mac:

FEED_URI='./storage/data/%(name)s.csv'
FEED_FORMAT='CSV'
FEED_EXPORT_ENCODING='utf-8'

 最后运行 麻辣小龙虾.py 即可。

    爬虫完毕,感谢 ! ! 

    接下来,爬虫专题更新多为反爬的内容......


scrapy组成

                                           scrapy整个框架是由 引擎、调度器、下载器、爬虫、数据管道组成。

  •        调度器:处理引擎发送过来的requests对象,并把请求的url以有序的方式排列成队,并等待引擎来提取即【异步】。
  • 下载中间件:下载器的秘书,会提前对引擎发送的诸多requests做处理 。 
  • 下载器:处理引擎发送过来的requests,进行网页爬取,并将返回的爬取到的内容(response)交给引擎即【获取数据】。
  • 爬虫中间件:爬虫的秘书,会提前接收并处理引擎发送来的爬取到的内容(response),过滤掉一些重复无用的东西。
  • 爬虫: 创建requests对象和接受引擎发送过来的下载器爬取到的内容(response),从中解析并提取出有用的数据即【解析、提取】。
  •        数据管道:存储和处理爬虫提取到的有用数据即【存储数据】。 

描述一下,爬豆瓣的scrapy框架流程:

  1.      引擎从爬虫那里,得到已经被封装成requests对象的URL。这就是为什么我们不需要写 requests.get 的原因。
  2.      引擎把requests对象交给了调度器,让ta实现队列完成异步爬虫,scrapy框架快速的原因。
  3.      引擎再把整个队列交给下载器,下载器火力全开后,把requests爬下来的打包成 response 给引擎。
  4.      引擎又把打包过的 response 给了爬虫让ta提取,最后给数据管道处理。
scrapy组成图示

组成一个 scrapy项目大致流程:

  1.      终端创建 scrapy 项目
  2.      定义 items 的属性
  3.      编辑 spiders 文件的爬虫代码
  4.      修改 settings 文件,包含反爬、存储
  5.      编写 main 文件,运行项目

除了 1 是最先,其余步骤可以不用按照顺序......

settings官方文档 : https://docs.scrapy.org/en/latest/topics/settings.html#std:setting-DOWNLOADER_MIDDLEWARES_BASE


爬虫框架

各种语言的爬虫框架:https://www.jianshu.com/p/7522e1fc3fb9

发布了124 篇原创文章 · 获赞 362 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_41739364/article/details/89392411