zoukankan      html  css  js  c++  java
  • 网络爬虫第五章之Scrapy框架

     

    第一节:Scrapy框架架构

    Scrapy框架介绍

    写一个爬虫,需要做很多的事情。比如:发送网络请求、数据解析、数据存储、反反爬虫机制(更换ip代理、设置请求头等)、异步请求等。这些工作如果每次都要自己从零开始写的话,比较浪费时间。因此Scrapy把一些基础的东西封装好了,在他上面写爬虫可以变的更加的高效(爬取效率和开发效率)。因此真正在公司里,一些上了量的爬虫,都是使用Scrapy框架来解决。

    Scrapy架构图:

    1. 流程图(1):

    Scrapy框架模块功能:

    1. Scrapy Engine(引擎)Scrapy框架的核心部分。负责在SpiderItemPipelineDownloaderScheduler中间通信、传递数据等。
    2. Spider(爬虫):发送需要爬取的链接给引擎,最后引擎把其他模块请求回来的数据再发送给爬虫,爬虫就去解析想要的数据。这个部分是我们开发者自己写的,因为要爬取哪些链接,页面中的哪些数据是我们需要的,都是由程序员自己决定。
    3. Scheduler(调度器):负责接收引擎发送过来的请求,并按照一定的方式进行排列和整理,负责调度请求的顺序等。
    4. Downloader(下载器):负责接收引擎传过来的下载请求,然后去网络上下载对应的数据再交还给引擎。
    5. Item Pipeline(管道):负责将Spider(爬虫)传递过来的数据进行保存。具体保存在哪里,应该看开发者自己的需求。
    6. Downloader Middlewares(下载中间件):可以扩展下载器和引擎之间通信功能的中间件。
    7. Spider Middlewares(Spider中间件):可以扩展引擎和爬虫之间通信功能的中间件。

    第二节:Scrapy快速入门

    安装和文档:

    1. 安装:通过pip install scrapy即可安装。
    2. Scrapy官方文档:http://doc.scrapy.org/en/latest
    3. Scrapy中文文档:http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html

    注意:

    1. ubuntu上安装scrapy之前,需要先安装以下依赖:
      sudo apt-get install python3-dev build-essential python3-pip libxml2-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev,然后再通过pip install scrapy安装。
    2. 如果在windows系统下,提示这个错误ModuleNotFoundError: No module named 'win32api',那么使用以下命令可以解决:pip install pypiwin32

    快速入门:

    创建项目:

    要使用Scrapy框架创建项目,需要通过命令来创建。首先进入到你想把这个项目存放的目录。然后使用以下命令创建:

    scrapy startproject [项目名称]
    

    目录结构介绍:


    以下介绍下主要文件的作用:

    1. items.py:用来存放爬虫爬取下来数据的模型。
    2. middlewares.py:用来存放各种中间件的文件。
    3. pipelines.py:用来将items的模型存储到本地磁盘中。
    4. settings.py:本爬虫的一些配置信息(比如请求头、多久发送一次请求、ip代理池等)。
    5. scrapy.cfg:项目的配置文件。
    6. spiders包:以后所有的爬虫,都是存放到这个里面。

    使用Scrapy框架爬取糗事百科段子:

    使用命令创建一个爬虫:

    scrapy gensipder qsbk "qiushibaike.com"

    创建了一个名字叫做qsbk的爬虫,并且能爬取的网页只会限制在qiushibaike.com这个域名下。

    爬虫代码解析:

    import scrapy
    
    class QsbkSpider(scrapy.Spider):
        name = 'qsbk'
        allowed_domains = ['qiushibaike.com']
        start_urls = ['http://qiushibaike.com/']
    
        def parse(self, response):
            pass

    其实这些代码我们完全可以自己手动去写,而不用命令。只不过是不用命令,自己写这些代码比较麻烦。
    要创建一个Spider,那么必须自定义一个类,继承自scrapy.Spider,然后在这个类中定义三个属性和一个方法。

    1. name:这个爬虫的名字,名字必须是唯一的。
    2. allow_domains:允许的域名。爬虫只会爬取这个域名下的网页,其他不是这个域名下的网页会被自动忽略。
    3. start_urls:爬虫从这个变量中的url开始。
    4. parse:引擎会把下载器下载回来的数据扔给爬虫解析,爬虫再把数据传给这个parse方法。这个是个固定的写法。这个方法的作用有两个,第一个是提取想要的数据。第二个是生成下一个请求的url。

    修改settings.py代码

    在做一个爬虫之前,一定要记得修改setttings.py中的设置。两个地方是强烈建议设置的。

    1. ROBOTSTXT_OBEY设置为False。默认是True。即遵守机器协议,那么在爬虫的时候,scrapy首先去找robots.txt文件,如果没有找到。则直接停止爬取。
    2. DEFAULT_REQUEST_HEADERS添加User-Agent。这个也是告诉服务器,我这个请求是一个正常的请求,不是一个爬虫。

    完成的爬虫代码

    1. 爬虫部分代码:

      import scrapy
       from abcspider.items import QsbkItem
      
       class QsbkSpider(scrapy.Spider):
           name = 'qsbk'
           allowed_domains = ['qiushibaike.com']
           start_urls = ['https://www.qiushibaike.com/text/']
      
           def parse(self, response):
               outerbox = response.xpath("//div[@id='content-left']/div")
               items = []
               for box in outerbox:
                   author = box.xpath(".//div[contains(@class,'author')]//h2/text()").extract_first().strip()
                   content = box.xpath(".//div[@class='content']/span/text()").extract_first().strip()
                   item = QsbkItem()
                   item["author"] = author
                   item["content"] = content
                   items.append(item)
               return items
    2. items.py部分代码:

       import scrapy
       class QsbkItem(scrapy.Item):
           author = scrapy.Field()
           content = scrapy.Field()
    3. pipeline部分代码:

      import json
      
       class AbcspiderPipeline(object):
           def __init__(self):
      
               self.items = []
      
           def process_item(self, item, spider):
               self.items.append(dict(item))
               print("="*40)
               return item
      
           def close_spider(self,spider):
               with open('qsbk.json','w',encoding='utf-8') as fp:
                   json.dump(self.items,fp,ensure_ascii=False)

    运行scrapy项目

    运行scrapy项目。需要在终端,进入项目所在的路径,然后scrapy crawl [爬虫名字]即可运行指定的爬虫。如果不想每次都在命令行中运行,那么可以把这个命令写在一个文件中。以后就在pycharm中执行运行这个文件就可以了。比如现在新创建一个文件叫做start.py,然后在这个文件中填入以下代码:

    from scrapy import cmdline
    
    cmdline.execute("scrapy crawl qsbk".split())

    第三节:CrawlSpider

    在上一个糗事百科的爬虫案例中。我们是自己在解析完整个页面后获取下一页的url,然后重新发送一个请求。有时候我们想要这样做,只要满足某个条件的url,都给我进行爬取。那么这时候我们就可以通过CrawlSpider来帮我们完成了。CrawlSpider继承自Spider,只不过是在之前的基础之上增加了新的功能,可以定义爬取的url的规则,以后scrapy碰到满足条件的url都进行爬取,而不用手动的yield Request

    CrawlSpider爬虫:

    创建CrawlSpider爬虫:

    之前创建爬虫的方式是通过scrapy genspider [爬虫名字] [域名]的方式创建的。如果想要创建CrawlSpider爬虫,那么应该通过以下命令创建:

    scrapy genspider -t crawl [爬虫名字] [域名]

    LinkExtractors链接提取器:

    使用LinkExtractors可以不用程序员自己提取想要的url,然后发送请求。这些工作都可以交给LinkExtractors,他会在所有爬的页面中找到满足规则的url,实现自动的爬取。以下对LinkExtractors类做一个简单的介绍:

    class scrapy.linkextractors.LinkExtractor(
        allow = (),
        deny = (),
        allow_domains = (),
        deny_domains = (),
        deny_extensions = None,
        restrict_xpaths = (),
        tags = ('a','area'),
        attrs = ('href'),
        canonicalize = True,
        unique = True,
        process_value = None
    )

    主要参数讲解:

    • allow:允许的url。所有满足这个正则表达式的url都会被提取。
    • deny:禁止的url。所有满足这个正则表达式的url都不会被提取。
    • allow_domains:允许的域名。只有在这个里面指定的域名的url才会被提取。
    • deny_domains:禁止的域名。所有在这个里面指定的域名的url都不会被提取。
    • restrict_xpaths:严格的xpath。和allow共同过滤链接。

    Rule规则类:

    定义爬虫的规则类。以下对这个类做一个简单的介绍:

    class scrapy.spiders.Rule(
        link_extractor, 
        callback = None, 
        cb_kwargs = None, 
        follow = None, 
        process_links = None, 
        process_request = None
    )

    主要参数讲解:

    • link_extractor:一个LinkExtractor对象,用于定义爬取规则。
    • callback:满足这个规则的url,应该要执行哪个回调函数。因为CrawlSpider使用了parse作为回调函数,因此不要覆盖parse作为回调函数自己的回调函数。
    • follow:指定根据该规则从response中提取的链接是否需要跟进。
    • process_links:从link_extractor中获取到链接后会传递给这个函数,用来过滤不需要爬取的链接。

     

    第四节:Scrapy Shell

    我们想要在爬虫中使用xpath、beautifulsoup、正则表达式、css选择器等来提取想要的数据。但是因为scrapy是一个比较重的框架。每次运行起来都要等待一段时间。因此要去验证我们写的提取规则是否正确,是一个比较麻烦的事情。因此Scrapy提供了一个shell,用来方便的测试规则。当然也不仅仅局限于这一个功能。

    打开Scrapy Shell:

    打开cmd终端,进入到Scrapy项目所在的目录,然后进入到scrapy框架所在的虚拟环境中,输入命令scrapy shell [链接]。就会进入到scrapy的shell环境中。在这个环境中,你可以跟在爬虫的parse方法中一样使用了。

     第五节:Request 和Response

    第六节:下载文件和图片

     第七节:Downloader Middlewares(下载器中间件):

    from scrapy import signals
    import random
    
    class UserAgentDownloadMiddleware(object):
        USER_AGENTS = [
            'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv,2.0.1) Gecko/20100101 Firefox/4.0.1'
         'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)'
         'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50'
    ] def process_request(self,request,spider): user_agent = random.choice(self.USER_AGENTS) # 随机选择一个请求头 request.headers['User-Agent'] = user_agent

    请求头获取网站:www.useragentstring.com 或者 http://www.jsons.cn/useragent/

    ip代理池中间件

    在以下代理商中购买代理:

    1,芝麻代理:http://http.zhimadaili.com/

    2,太阳代理:http://http.taiyangdaili.com/

    3,快代理:http://http.kuaidaili.com/

    4,讯代理:http://http.xdaili.com/

    5,蚂蚁代理:http://http.mayidaili.com/

    等购买代理。

    使用ip代理池:

    示例代码如下:

    # 开放代理池设置
    class IPProxyDownloadMiddleware(object):
        PROXIES = ["178.44.170.153:8080", "110.44.113.182:8080",
                   "209.126.124.73:8888"]
    
        def process_request(self, request, spider):
            proxy = random.choice(self.PROXIES)
            request.meta['proxy'] = proxy
    import base64

    #
    独享代理池设置 class IPProxyDownloadMiddleware(object): def process_request(self, request, spider): proxy = '121.199.6.124:16816' user_password = "970138074:rxcd35fd" request.meta['proxy'] = proxy #bytes b64_user_password = base64.b64encode(user_password.encode('utf-8')) request.headers['Proxy-Authorization'] = 'basic ' + b64_user_password.decode('utf-8')
  • 相关阅读:
    R语言:提取路径中的文件名字符串(basename函数)
    课程一(Neural Networks and Deep Learning),第三周(Shallow neural networks)—— 0、学习目标
    numpy.squeeze()的用法
    课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 4、Logistic Regression with a Neural Network mindset
    Python numpy 中 keepdims 的含义
    课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 3、Python Basics with numpy (optional)
    课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 2、编程作业常见问题与答案(Programming Assignment FAQ)
    课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 0、学习目标
    课程一(Neural Networks and Deep Learning),第一周(Introduction to Deep Learning)—— 0、学习目标
    windows系统numpy的下载与安装教程
  • 原文地址:https://www.cnblogs.com/lcy0302/p/11027857.html
Copyright © 2011-2022 走看看