zoukankan      html  css  js  c++  java
  • Scrapy 框架 (学习笔记-1)

    环境:

    1.windows 10
    2.Python 3.7
    3.Scrapy 1.7.3
    4.mysql 5.5.53

    一、Scrapy 安装

    1. Scrapy:是一套基于Twisted的一部处理框架,是纯Python实现的爬虫框架,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容或者各种图片。
    1. 安装命令:pip install scrapy
    2. 查看是否安装成功,命令: scrapy

    二、项目实战

    1. 抓取豆瓣电影('https://movie.douban.com/top250')Top250数据,并将数据保存为csv,json和存储到数据库中
    2. 一个完整项目基本包括:新建项目、明确目标、制作爬虫、存储内容四个步骤。

    (一)、新建项目

    1. 创建项目
        命令: scrapy startproject [项目名称]     例:scrapy startproject Douban
        项目目录结构:
            # Douban
                # Douban
                    # spiders
                        # __init__.py
                    # __init__.py
                    # items.py
                    # middlewares.py
                    # pipelines.py    
                    # settings.py
                # scrapy.cfg
    2.创建爬虫 
        在spiders下执行命令: scrapy genspider [爬虫名] [待爬取网站的域名]    例:scrapy genspider douban_top250 movie.douban.com (此时spiders目录下会生成一个'douban_top250.py'爬虫文件)

    == 注意:爬虫名称不能与项目名称重复 ==

    (二)、明确目标


    1. 明确要抓取哪些数据,并在 items.py 文件中进行定义.

       例:
            import scrapy
    
            class DoubanItem(scrapy.Item):
                # define the fields for your item here like:
                # name = scrapy.Field()
    
                # 序号
                serial_num = scrapy.Field()
                # 电影名称
                movie_name = scrapy.Field()
                # 电影介绍
                introduce = scrapy.Field()
                # 电影评论数
                evaluate_num = scrapy.Field()
                # 电影描述
                describe = scrapy.Field()
                # 电影星级
                star = scrapy.Field()

    (三)、制作爬虫

    1.打开爬虫文件(douban_top250.py)

        # -*- coding: utf-8 -*-
        import scrapy
    
        class DoubanTop250Spider(scrapy.Spider):
            # 爬虫名称
            name = 'douban_top250'
            # 允许的域名
            allowed_domains = ['movie.douban.com']
            # 入口URL
            start_urls = ['https://movie.douban.com/top250']
    
            def parse(self, response):
                pass

    2.在settings.py文件中开启 'USER_AGENT' 并设置为正确的代理

    3.输出爬取的信息 例:

      def parse(self, response):
            print(response.text)
    4.执行爬虫运行命令: scrapy crawl [爬虫名称]   例: scrapy crawl douban_top250

    == 注意:必须在 spiders 文件夹下执行 scrapy crawl 命令 ==

    5.解析爬取的网页数据,例:
    # -*- coding: utf-8 -*-
    import scrapy
    from Douban.items import DoubanItem
    class DoubanTop250Spider(scrapy.Spider):
        # 爬虫名称
        name = 'douban_top250'
        # 允许的域名
        allowed_domains = ['movie.douban.com']
        # 入口URL
        start_urls = ['https://movie.douban.com/top250']
    
        # 默认的解析方法
        def parse(self, response):
            # 导入item文件,实例对象
            res = DoubanItem()
            # 书写详细的xpath语句对数据进行解析
            # 获取第一页的所有电影
            movie_list = response.xpath('//div[@class="article"]/ol[@class="grid_view"]/li')
            # 循环获得的电影
            for movie in movie_list:
                # 获取电影序号
                res['serial_num'] = movie.xpath('.//div[@class="item"]/div[@class="pic"]/em/text()').extract_first()
                # 获取电影名称
                titles = movie.xpath('.//div[@class="item"]/div[@class="info"]/div[@class="hd"]/a/span/text()').extract()
                movie_name = ''
                for title in titles:
                    movie_name = movie_name + "".join(title.split())
                res['movie_name'] = movie_name
                # 获取电影介绍
                res['introduce'] = "".join(movie.xpath('.//div[@class="bd"]/p/text()').extract_first().split())
                # 获取电影评论数
                res['evaluate_num'] = movie.xpath('.//div[@class="star"]/span[4]/text()').extract_first()
                # 获取电影描述
                res['describe'] = movie.xpath('.//div[@class="bd"]/p[@class="quote"]/span/text()').extract_first()
                # 获取电影的评分
                res['score'] = movie.xpath('.//div[@class="star"]/span[2]/text()').extract_first()
                # 将结果提交至管道pipelines里面,进行数据的清洗以及存储
                yield res
            # 解析下一页规则
            string = response.xpath('.//span[@class="next"]/a/@href').extract_first()
            if string :
                href = self.start_urls[0] + string
                yield scrapy.Request(href,callback=self.parse)

    (四)、存储内容


    1、将数据保存为 json、csv 文件

       命令:scrapy crawl [爬虫名称] -o [保存文件名]
        例:
            1. scrapy crawl douban_top250 -o douban1.json
            2. scrapy crawl douban_top250 -o douban2.csv

    2、将数据保存至数据库中

      1. 创建mysql数据库及相关表
        2. 在settings.py文件中开启 EXTENSIONS 设置
        3. 在pipelines.py文件中导入pymysql模块
        4. pipelines.py文件中类的命名是创建项目时自动生成的,一般为: [项目名称]Pipeline
        5. 在类中process_item方法内进行保存数据操作
        例:
    # -*- coding: utf-8 -*-
    
    # 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
    
    # 导入pymysql模块
    import pymysql
    
    class DoubanPipeline(object):
    
        # 初始化相关属性
        def __init__(self):
            # 连接database
            try:
                self.conn = pymysql.connect(
                    host="127.0.0.1",  # 数据库IP地址
                    port=3306,  # 端口号
                    db="python_movie",  # 数据库名称
                    user="root",  # 用户名
                    password="root",  # 密码
                    charset="utf8",  # 编码格式
                    use_unicode=True,  # 指定字符的编码、解码格式
                    cursorclass=pymysql.cursors.DictCursor,  # 数据返回格式
                )
                # 得到一个可以执行SQL语句的光标对象
                self.cursor = self.conn.cursor()
            except Exception as e:
                print(e)
    
        # 开启爬虫时执行,只执行一次
        def open_spider(self,spider):
            pass
    
        # 处理提取的数据(保存数据)
        def process_item(self, item, spider):
            sql = "INSERT INTO movie (serial,`name`,introduce,evaluate,`describe`,score) VALUES (%s,%s,%s,%s,%s,%s)"
            # 执行sql语句
            try:
                self.cursor.execute(sql, tuple(item.values()))
                self.conn.commit()
            except Exception as e:
                print(e)
    
        # 关闭爬虫时执行,只执行一次。 (如果爬虫中间发生异常导致崩溃,close_spider可能也不会执行)
        def close_spider(self, spider):
            self.cursor.close()
            self.conn.close()

    (五)、下载中间件编写


    1. 设置代理 IP

    1.在middlewares.py文件中编写
    2.创建一个类,继承 object,在此类中编写代理IP
    3.在类中创建方法
    def process_request(self,request,spider):
            pass
    注意:这个方法名称是固定默认的,
    4.在process_request方法中设置request中的meta属性中的prproxy参数,参数值为自己的代理服务器与端口号
    request.meta['proxy'] = '[IP地址/域名]:[端口号 ]'
    5.在process_request方法中设置代理的用户名与密码,固定格式为:
    proxy_name_pass = '[用户名]:[密码]'
    注意:用户名与密码中间用':'号分割
    6.需要用base64.b64encode()对用户名与密码进行加密,而且base64.b64encode()只接受bytes格式的字符串,故:
    proxy_name_pass = base64.b64encode(b'[用户名]:[密码]')
    7.设置http请求头
    request.headers['Proxy-Authorization'] = 'Basic ' + proxy_name_pass.decode()
    8.将代理中间添加至settings.py中的 DOWNLOADER_MIDDLEWARES 中进行注册
    例:
    在 middlewares.py 中编写中间件
    class my_proxy(object):
        # 这个方法名 'process_request' 是固定的
        def process_request(self,request,spider):
            # 设置代理服务器IP地址
            request.meta['proxy'] = "这里写代理IP:这里写端口号"
            # 设置代理服务器账号与密码(注意账号与密码用 ':' 号分割,并且将字符串变为bytes格式)
            proxy_name_pass = b"这里写账号:这里写密码"
            # 加密账号与密码
            encode_name_pass = base64.b64encode(proxy_name_pass)
            # 设置代理服务请求头(注意:Basic后面必须加空格,而且加密后的账号与密码必须转为字符串格式才能拼接)
            request.headers['Proxy-Authorization'] = 'Basic ' + encode_name_pass.decode()  
    在 settings.py 中设置中间件
    # 注意,后面的数字,表示中间件的优先级,多个中间价同时启用时优先级不可以相同
    DOWNLOADER_MIDDLEWARES = {
       'Douban.middlewares.DoubanDownloaderMiddleware': 543,
       'Douban.middlewares.my_proxy': 544,
    }

    2. 设置 User-Agent

    1.同上,在middlewares.py中创建一个类,在默认的process_request()方法中编写中间件
    2.同上,将编写的中间件添加至settings.py中的 DOWNLOADER_MIDDLEWARES 中进行注册
    3.具体操作直接上代码:
    例:
    在 middlewares.py 中编写中间件
    # 设置代理IP中间件
    class my_proxy(object):
        def process_request(self,request,spider):
            # 设置代理服务器IP地址
            request.meta['proxy'] = "这里写代理IP:这里写端口号"
            # 设置代理服务器账号与密码(注意账号与密码用 ':' 号分割,并且将字符串变为bytes格式)
            proxy_name_pass = b"这里写账号:这里写密码"
            # 加密账号与密码
            encode_name_pass = base64.b64encode(proxy_name_pass)
            # 设置代理服务请求头(注意:Basic后面必须加空格,而且加密后的账号与密码必须转为字符串格式才能拼接)
            request.headers['Proxy-Authorization'] = 'Basic ' + encode_name_pass.decode()
    
    # 设置随机User_Agent中间件
    class my_user_agent(object):
        def process_request(self,request,spider):
            # 在网络上搜索User_Agent列表
            USER_AGENT_LIST = [
                 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
                 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
                 "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
                 "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
                 "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
                 "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
                 "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
                 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
                 "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
                 "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
                 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
                 "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
                 "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
                 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
                 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
                 "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
            ]
            # 随机获取一个user_agent,而random.choice()函数,表示从序列中随机选取一个元素
            user_agent = random.choice(USER_AGENT_LIST)
            # 设置Http请求头中的User_Agent
            request.headers['User_Agent'] = user_agent
    在 settings.py 中设置中间件
    # 注意,后面的数字,表示中间件的优先级,多个中间价同时启用时优先级不可以相同
    DOWNLOADER_MIDDLEWARES = {
       'Douban.middlewares.DoubanDownloaderMiddleware': 543,
       'Douban.middlewares.my_proxy': 544,
       'Douban.middlewares.my_user_agent': 545,
    }

    == 注意:1. 中间件定义编写完成以后,一定要在 settings.py 文件中的 DOWNLOADER_MIDDLEWARES = {} 中注册中间件,表示启用此中间件;2. 爬虫文件名和爬虫名称不能相同,spider 目录内不能存在相同爬虫名称的项目文件 ==

    交流群:887934385 

  • 相关阅读:
    SPOJ 694 (后缀数组) Distinct Substrings
    POJ 2774 (后缀数组 最长公共字串) Long Long Message
    POJ 3693 (后缀数组) Maximum repetition substring
    POJ 3261 (后缀数组 二分) Milk Patterns
    UVa 1149 (贪心) Bin Packing
    UVa 12206 (字符串哈希) Stammering Aliens
    UVa 11210 (DFS) Chinese Mahjong
    UVa (BFS) The Monocycle
    UVa 11624 (BFS) Fire!
    HDU 3032 (Nim博弈变形) Nim or not Nim?
  • 原文地址:https://www.cnblogs.com/pypypy/p/12002180.html
Copyright © 2011-2022 走看看