从零开始学爬虫7——scrapy

简介: 爬虫——scrapy
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。

1 基本使用

  1. 创建scrapy项目:终端输入 scrapy startproject 项目名称
  2. scrapy项目的结构
    项目名字

    项目名字
     spiders文件夹 (存储的是爬虫文件)
            init
         自定义的爬虫文件    核心功能文件 
        init
     items        定义数据结构的地方 爬取的数据都包含哪些  是一个继承自scrapy.Item的类
        middleware   中间件    代理
     pipelines    管道   里面只有一个类,用于进行下载数据的后续处理,默认是300优先级,值越小优先级越高(1-1000)
        settings     配置文件 比如:是否遵守robots协议,User‐Agent定义等
    
  3. 创建爬虫文件:

    • 跳转到spiders文件夹 cd 目录名字/目录名字/spiders

      • scrapy genspider 爬虫名字 网页的域名
    • 爬虫文件的基本组成:

      • 继承scrapy.Spider类

        • name = 'baidu' : 运行爬虫文件时使用的名字
        • allowed_domains : 爬虫允许的域名,在爬取的时候,如果不是此域名之下的url,会被过滤掉
        • start_urls : 声明了爬虫的起始地址,可以写多个url,一般是一个
        • parse(self, response) :解析数据的回调函数

          response的属性和方法
              response.text   获取的是响应的字符串
              response.body   获取的是二进制数据
              response.xpath  可以直接使用xpath方法来解析response中的内容,返回值类型是selector列表
              response.extract()   提取seletor对象的data属性值
              response.extract_first() 提取的seletor列表的第一个数据
  4. 运行爬虫文件:scrapy crawl 爬虫名称

    注意:应在spiders文件夹内执行

以爬取百度为例:

import scrapy

class BaiduSpider(scrapy.Spider):
    # 爬虫的名字  用于运行爬虫的时候 使用的值
    name = 'baidu'
    # 允许访问的域名
    allowed_domains = ['http://www.baidu.com']
    # 起始的url地址  指的是第一次要访问的域名
    # start_urls 是在allowed_domains的前面添加一个http://
    #             在 allowed_domains的后面添加一个/
    start_urls = ['http://www.baidu.com/']

    # 是执行了start_urls之后 执行的方法   方法中的response 就是返回的那个对象
    # 相当于 response = urllib.request.urlopen()
    #       response  = requests.get()
    def parse(self, response):
        print('苍茫的天涯是我的爱')

2 工作原理

(1)引擎 ‐‐‐》自动运行,无需关注,会自动组织所有的请求对象,分发给下载器
(2)下载器 ‐‐‐》从引擎处获取到请求对象后,请求数据
(3)spiders ‐‐‐》Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例
如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。
(4)调度器 ‐‐‐》有自己的调度规则,无需关注
(5)管道(Item pipeline) ‐‐‐》最终处理数据的管道,会预留接口供我们处理数据
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。
每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行
一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
以下是item pipeline的一些典型应用:
1. 清理HTML数据
2. 验证爬取的数据(检查item包含某些字段)
3. 查重(并丢弃)
4. 将爬取结果保存到数据库中

以汽车之家为例

import scrapy

class CarSpider(scrapy.Spider):
    name = 'car'
    allowed_domains = ['https://car.autohome.com.cn/price/brand-15.html']
    # 注意如果你的请求的接口是html为结尾的  那么是不需要加/的
    start_urls = ['https://car.autohome.com.cn/price/brand-15.html']

    def parse(self, response):
        name_list = response.xpath('//div[@class="main-title"]/a/text()')
        price_list = response.xpath('//div[@class="main-lever"]//span/span/text()')

        for i in range(len(name_list)):
            name = name_list[i].extract()
            price = price_list[i].extract()
            print(name,price)

3 scrapy shell

什么是scrapy shell?

Scrapy终端,是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。 其本意是用来测试提取数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码。该终端是用来测试XPath或CSS表达式,查看他们的工作方式及从爬取的网页中提取的数据。 在编写您的spider时,该终端提供了交互性测试您的表达式代码的功能,免去了每次修改后运行spider的麻烦。一旦熟悉了Scrapy终端后,您会发现其在开发和调试spider时发挥的巨大作用。
# 进入到scrapy shell的终端  直接在window的终端中输入scrapy shell 域名
# 如果想看到一些高亮 或者 自动补全  那么可以安装ipython  pip install ipython

# scrapy shell www.baidu.com

4 例:当当网

yield、管道封装、多管道下载、多页下载

dang.py

import scrapy
# 这样写会报错,但是不碍事
from scrapy_dangdang_095.items import ScrapyDangdang095Item

class DangSpider(scrapy.Spider):
    name = 'dang'
    # 如果是多页下载的话 那么必须要调整的是allowed_domains的范围 一般情况下只写域名
    allowed_domains = ['category.dangdang.com']
    start_urls = ['http://category.dangdang.com/cp01.01.02.00.00.00.html']

    base_url = 'http://category.dangdang.com/pg'
    page = 1

    def parse(self, response):
#       pipelines 下载数据
#       items     定义数据结构的
#         src = //ul[@id="component_59"]/li//img/@src
#         alt = //ul[@id="component_59"]/li//img/@alt
#         price = //ul[@id="component_59"]/li//p[@class="price"]/span[1]/text()
#         所有的seletor的对象 都可以再次调用xpath方法
        li_list = response.xpath('//ul[@id="component_59"]/li')

        for li in li_list:
            src = li.xpath('.//img/@data-original').extract_first()
            # 第一张图片和其他的图片的标签的属性是不一样的
            # 第一张图片的src是可以使用的  其他的图片的地址是data-original
            if src:
                src = src
            else:
                src = li.xpath('.//img/@src').extract_first()

            name = li.xpath('.//img/@alt').extract_first()
            price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()

            book = ScrapyDangdang095Item(src=src,name=name,price=price)

            # 获取一个book就将book交给pipelines
            yield book


#       每一页的爬取的业务逻辑全都是一样的,所以我们只需要将执行的那个页的请求再次调用parse方法
# 就可以了
#         http://category.dangdang.com/pg2-cp01.01.02.00.00.00.html
#         http://category.dangdang.com/pg3-cp01.01.02.00.00.00.html
#         http://category.dangdang.com/pg4-cp01.01.02.00.00.00.html

        if self.page < 100:
            self.page = self.page + 1

            url = self.base_url + str(self.page) + '-cp01.01.02.00.00.00.html'

#             怎么去调用parse方法
#             scrapy.Request就是scrpay的get请求
#             url就是请求地址
#             callback是你要执行的那个函数  注意不需要加()
            yield scrapy.Request(url=url,callback=self.parse)

items.py

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy

class ScrapyDangdang095Item(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 通俗的说就是你要下载的数据都有什么

    # 图片
    src = scrapy.Field()
    # 名字
    name = scrapy.Field()
    # 价格
    price = scrapy.Field()

pipelines.py

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter

# 如果想使用管道的话 那么就必须在settings中开启管道
class ScrapyDangdang095Pipeline:
    # 在爬虫文件开始的之前就执行的一个方法
    def open_spider(self,spider):
        self.fp = open('book.json','w',encoding='utf-8')

    # item就是yield后面的book对象
    def process_item(self, item, spider):
        # 以下这种模式不推荐  因为每传递过来一个对象 那么就打开一次文件  对文件的操作过于频繁

        # # (1) write方法必须要写一个字符串 而不能是其他的对象
        # # (2) w模式 会每一个对象都打开一次文件 覆盖之前的内容
        # with open('book.json','a',encoding='utf-8')as fp:
        #     fp.write(str(item))

        self.fp.write(str(item))
        return item

    # 在爬虫文件执行完之后  执行的方法
    def close_spider(self,spider):
        self.fp.close()

import urllib.request

# 多条管道开启
#    (1) 定义管道类
#   (2) 在settings中开启管道
# 'scrapy_dangdang_095.pipelines.DangDangDownloadPipeline':301
class DangDangDownloadPipeline:
    def process_item(self, item, spider):
        url = 'http:' + item.get('src')
        filename = './books/' + item.get('name') + '.jpg'
        urllib.request.urlretrieve(url = url, filename= filename)
        return item

5 嵌套网页数据下载

import scrapy
from scrapy_movie_099.items import ScrapyMovie099Item

class MvSpider(scrapy.Spider):
    name = 'mv'
    allowed_domains = ['www.dytt8.net']
    start_urls = ['https://www.dytt8.net/html/gndy/china/index.html']

    def parse(self, response):
#         要第一个的名字 和 第二页的图片
        a_list = response.xpath('//div[@class="co_content8"]//td[2]//a[2]')

        for a in a_list:
            # 获取第一页的name 和 要点击的链接
            name = a.xpath('./text()').extract_first()
            href = a.xpath('./@href').extract_first()

            # 第二页的地址是
            url = 'https://www.dytt8.net' + href

            # 对第二页的链接发起访问
            yield  scrapy.Request(url=url,callback=self.parse_second,meta={'name':name})

    def parse_second(self,response):
        # 注意 如果拿不到数据的情况下  一定检查你的xpath语法是否正确
        src = response.xpath('//div[@id="Zoom"]//img/@src').extract_first()
        # 接受到请求的那个meta参数的值
        name = response.meta['name']
        movie = ScrapyMovie099Item(src=src,name=name)
        yield movie
相关实践学习
基于函数计算快速搭建Hexo博客系统
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
4月前
|
数据采集 存储 数据处理
Scrapy:Python网络爬虫框架的利器
在当今信息时代,网络数据已成为企业和个人获取信息的重要途径。而Python网络爬虫框架Scrapy则成为了网络爬虫工程师的必备工具。本文将介绍Scrapy的概念与实践,以及其在数据采集和处理过程中的应用。
24 1
|
5月前
|
数据采集 调度 Python
Scrapy爬虫中合理使用time.sleep和Request
Scrapy爬虫中合理使用time.sleep和Request
|
14天前
|
数据采集 存储 中间件
【专栏】随着技术发展,Scrapy将在网络爬虫领域持续发挥关键作用
【4月更文挑战第27天】Scrapy是Python的高效爬虫框架,以其异步处理、多线程和中间件机制提升爬取效率。它的灵活性体现在可定制化组件、支持多种数据库存储及与Selenium、BeautifulSoup等工具集成。Scrapy易于扩展,允许自定义下载器和解析器。在实践中,涉及项目配置、Spider类编写、数据抓取、存储与分析。面对动态网页和反爬机制,Scrapy可通过Selenium等工具应对,但需注意法规与道德规范。随着技术发展,Scrapy将在网络爬虫领域持续发挥关键作用。
|
19天前
|
数据采集 存储 JSON
Python爬虫面试:requests、BeautifulSoup与Scrapy详解
【4月更文挑战第19天】本文聚焦于Python爬虫面试中的核心库——requests、BeautifulSoup和Scrapy。讲解了它们的常见问题、易错点及应对策略。对于requests,强调了异常处理、代理设置和请求重试;BeautifulSoup部分提到选择器使用、动态内容处理和解析效率优化;而Scrapy则关注项目架构、数据存储和分布式爬虫。通过实例代码,帮助读者深化理解并提升面试表现。
22 0
|
2月前
|
数据采集 Web App开发 搜索推荐
项目配置之道:优化Scrapy参数提升爬虫效率
项目配置之道:优化Scrapy参数提升爬虫效率
|
2月前
|
数据采集 存储 数据可视化
介绍一下常见的爬虫框架或库,如`Scrapy`。
【2月更文挑战第22天】【2月更文挑战第70篇】介绍一下常见的爬虫框架或库,如`Scrapy`。
|
3月前
|
数据采集 JavaScript 前端开发
深度剖析Selenium与Scrapy的黄金组合:实现动态网页爬虫
深度剖析Selenium与Scrapy的黄金组合:实现动态网页爬虫
|
4月前
|
数据采集 存储 调度
Scrapy:解锁网络爬虫新境界
在当今信息爆炸的时代,获取并处理大量网络数据是互联网行业中至关重要的一环。Python网络爬虫框架Scrapy作为一款高效、灵活的工具,为开发者提供了强大的能力来抓取、解析和存储各类网页信息。本文将介绍Scrapy的概念、主要特点以及实践经验,帮助读者掌握这一工具,并在实际项目中应用。
|
4月前
|
数据采集 存储 机器人
Scrapy网络爬虫框架——从入门到实践
网络爬虫已经成为了信息获取的必备工具之一,而Scrapy作为Python中最流行的网络爬虫框架之一,具有高效、可扩展、易用等特点。本文将深入介绍Scrapy框架的概念和实践,帮助读者快速掌握构建高质量网络爬虫的方法。
82 0
|
4月前
|
数据采集 存储 调度
Scrapy:从入门到实践的网络爬虫框架
Scrapy是一款强大的Python网络爬虫框架,可以帮助开发者更高效地抓取互联网上的数据。本文将介绍Scrapy的概念和基本原理,详细讲解如何使用Scrapy框架实现一个简单的网络爬虫,并分享一些实战经验和技巧。