爬虫(七)scrapy入门

Scrapy爬虫框架入门

Scrapy概述

Scrapy是Python开发的一个非常流行的网络爬虫框架,可以用来抓取Web站点并从页面中提取结构化的数据,被广泛的用于数据挖掘、数据监测和自动化测试等领域。下图展示了Scrapy的基本架构,其中包含了主要组件和系统的数据处理流程(图中带数字的红色箭头)。
这里写图片描述

组件

  1. Scrapy引擎(Engine):Scrapy引擎是用来控制整个系统的数据处理流程。
  2. 调度器(Scheduler):调度器从Scrapy引擎接受请求并排序列入队列,并在Scrapy引擎发出请求后返还给它们。
  3. 下载器(Downloader):下载器的主要职责是抓取网页并将网页内容返还给蜘蛛(Spiders)。
  4. 蜘蛛(Spiders):蜘蛛是有Scrapy用户自定义的用来解析网页并抓取特定URL返回的内容的类,每个蜘蛛都能处理一个域名或一组域名,简单的说就是用来定义特定网站的抓取和解析规则。
  5. 条目管道(Item Pipeline):条目管道的主要责任是负责处理有蜘蛛从网页中抽取的数据条目,它的主要任务是清理、验证和存储数据。当页面被蜘蛛解析后,将被发送到条目管道,并经过几个特定的次序处理数据。每个条目管道组件都是一个Python类,它们获取了数据条目并执行对数据条目进行处理的方法,同时还需要确定是否需要在条目管道中继续执行下一步或是直接丢弃掉不处理。条目管道通常执行的任务有:清理HTML数据、验证解析到的数据(检查条目是否包含必要的字段)、检查是不是重复数据(如果重复就丢弃)、将解析到的数据存储到数据库(关系型数据库或NoSQL数据库)中。
  6. 中间件(Middlewares):中间件是介于Scrapy引擎和其他组件之间的一个钩子框架,主要是为了提供自定义的代码来拓展Scrapy的功能,包括下载器中间件和蜘蛛中间件。

数据处理流程

Scrapy的整个数据处理流程由Scrapy引擎进行控制,通常的运转流程包括以下的步骤:

  1. 引擎询问蜘蛛需要处理哪个网站,并让蜘蛛将第一个需要处理的URL交给它。

  2. 引擎让调度器将需要处理的URL放在队列中。

  3. 引擎从调度那获取接下来进行爬取的页面。

  4. 调度将下一个爬取的URL返回给引擎,引擎将它通过下载中间件发送到下载器。

  5. 当网页被下载器下载完成以后,响应内容通过下载中间件被发送到引擎;如果下载失败了,引擎会通知调度器记录这个URL,待会再重新下载。

  6. 引擎收到下载器的响应并将它通过蜘蛛中间件发送到蜘蛛进行处理。

  7. 蜘蛛处理响应并返回爬取到的数据条目,此外还要将需要跟进的新的URL发送给引擎。

  8. 引擎将抓取到的数据条目送入条目管道,把新的URL发送给调度器放入队列中。

上述操作中的2-8步会一直重复直到调度器中没有需要请求的URL,爬虫停止工作。

scrapy安装环境:

1. 建立一个新的文件夹放你爬虫项目文件如:shit
2. 建立python虚拟环境,虚拟环境的文件名为venv
    python -m venv venv 
3. 安装依赖包, 安装以后才能安装scrapy, 这个依赖包直接pip好像安装不了, 推荐去官网下载后在本地后进行安装:
    pip install j:\Twisted-18.4.0-cp36-cp36m-win_amd64.whl
4. 更新你的pip包管理工具
    python -m pip install -U pip
5. 安装你的爬虫框架scrapy
    pip install scrapy

开始scrapy项目:

以豆瓣电影top250为例子:
1.在当前文件夹下建立scrapy爬虫项目
    scrapy startproject douban .
2. 创建你的爬虫movie, 网站名为:www.douban.movie.com
    scrapy genspider movie www.douban.movie.com
3. 安装依赖包pypiwin32
    pip install pypiwin32
4. 在 scrapy shell + 你的爬取域名中可以查看爬取该网页的一些状态内容等信息
    scrapy shell https://movie.douban.com/top250
5. 启动scrapy开始爬取movie项目
    scrapy crawl movie
6. 启动scrapy爬取movie项目, 将爬取到的内容重定向输出到result.json里面.
    scrapy crawl movie -o result.json
当你成功创建scrapy项目并且创建了爬虫以后,用pycharm打开该项目你会发现以下的文件树结构:

这里写图片描述

当你创建好项目以后, 首先找到douban文件夹下的settings.py文件,进行如下的设置(有些默认已经打开的我这边不做详解):
# 设置代理名
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) ' \
         'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
# 是否遵守robots协议
ROBOTSTXT_OBEY = True
# 并发请求数量(默认为16), 因为是做实验, 设置为2个就好了, 以免请求太快被封IP
CONCURRENT_REQUESTS = 2 
# 设置下载延时(默认3s)
DOWNLOAD_DELAY = 5
# 开启页面缓存
HTTPCACHE_ENABLED = True
HTTPCACHE_EXPIRATION_SECS = 0
HTTPCACHE_DIR = 'httpcache'
HTTPCACHE_IGNORE_HTTP_CODES = []
HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
# 当你要做数据持久化, 那么要打开以下的通道, 后面的数字300代表优先级:
ITEM_PIPELINES = {
   'douban.pipelines.DoubanPipeline': 300,
}
要持久化数据, 那么肯定要筛选出需要数据, 在douban文件夹下的items.py中对该数据进行scrapy.Field()初始化,如下:
import scrapy

class MovieItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    score = scrapy.Field()
接下来是爬虫文件部分,在douban文件夹下的spiders文件夹下的movie.py文件.
import scrapy

from douban.items import MovieItem


class MoiveSpider(scrapy.Spider):
    # scrapy下的爬虫项目名称
    name = 'movie'
    # 允许通过的域名
    allowed_domains = ['movie.douban.com']
    # 起始爬取的urls(统一资源定位符)
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        # 在浏览器里面可以选中标签直接copy Xpath查询语句
        li_list = response.xpath('//*[@id="content"]/div/div[1]/ol/li')
        for li in li_list:
            # 创建一个MovieItem对象
            item = MovieItem()
            # extract 抽取的是列表  extract_first 抽取的是文本内容
            # 给item里面title key进行赋值, 下同
            item['title'] = li.xpath('div/div[2]/div[1]/a/span[1]/text()').extract_first()
            item['score'] = li.xpath('div/div[2]/div[2]/div/span[2]/text()').extract_first()
            item['motto'] = li.xpath('div/div[2]/div[2]/p[2]/span/text()').extract_first()
            # 返回的是一个生成器, 他会传到管道(pipelines.py)里面进行数据处理
            yield item

        # 通过css选择器语法获取所有的有href属性a标签里面的href属性的值, 并且正确使用正则表达式匹配除href属性的值是以\?start=.*的href属性值.
        # 其中正则表达式的意思是匹配含有\?start=.*(.*代表任意数字字母)的所有属性值
        href_list = response.css('a[href]::attr("href")').re('\?start=.*')
        for href in href_list:
            # 对响应里面的href值使用urljoin方法,可以将里面一些不完整的域名自动补全.
            url = response.urljoin(href)
            # 返回生成器, 将需要爬取的域名传入进去 并且执行回调函数callback
            yield scrapy.Request(url=url, callback=self.parse)
使用scrapy爬取迁木网世界大学排名
文件树如下:

这里写图片描述

items.py文件
import scrapy


class QianmuItem(scrapy.Item):
    rank = scrapy.Field()
    name = scrapy.Field()
    name_eng = scrapy.Field()
    country = scrapy.Field()
pipelines.py文件
import pymongo as pymongo


class QianmuPipeline(object):
    def __init__(self):
        mongo_client = pymongo.MongoClient(host='116.196.107.233', port=27017)
        self.db = mongo_client.qianmu

    def process_item(self, item, spider):
        rank = [{
            'rank':item['rank'],
            'name':item['name'],
            'name_eng':item['name_eng'],
            'country':item['country']
        }]
        self.db.rank.insert(rank)

        return item

爬虫文件qmrank.py

import scrapy

from qianmu.items import QianmuItem


class QmrankSpider(scrapy.Spider):
    name = 'qmrank'
    allowed_domains = ['www.qianmu.org']
    start_urls = ['http://www.qianmu.org/ranking/1528.htm']

    def parse(self, response):
        tr_list = response.xpath('//*[@id="page-wrapper"]/div/div[2]/div/div/div/div[2]/div/div[5]/table/tbody/tr')
        for tr in tr_list:
            item = QianmuItem()
            item['rank'] = tr.xpath('td[1]/text()').extract_first()
            item['name'] = tr.xpath('td[2]/a/text()').extract_first() if tr.xpath('td[2]/a/text()').extract_first() else tr.xpath('td[2]/text()').extract_first()
            item['name_eng'] = tr.xpath('td[3]/text()').extract_first()
            item['country'] = tr.xpath('td[4]/text()').extract_first()
            yield item

scrapy代理的设置:参考scrapy代理设置

猜你喜欢

转载自blog.csdn.net/qq_41637554/article/details/80612298
今日推荐