Python入门实战:网络爬虫实现

242 阅读11分钟

1.背景介绍

随着互联网的飞速发展,越来越多的人依赖于互联网上的资源。如何从互联网上收集数据、整理分析并利用这些数据进行决策,成为了各个行业的需求。传统的数据采集方式主要依靠硬件设备或者编写脚本,但这些方式在处理复杂、快速变化的网站时效率低下且难以应对大量数据。近年来人工智能技术和机器学习方法不断涌现,已经成为新时代数据采集的主流手段之一。然而,由于复杂的数据结构和非结构化的文档,传统的基于规则的解决方案难以处理大规模数据的爬取。因此,本文将以一个简单实例——网站数据采集为例,阐述基于Python语言和Web scraping框架scrapy的网络爬虫的基本原理、基本流程、具体实现和扩展思路。 本文通过一个小型案例来介绍如何使用Python及Scrapy框架来实现网络爬虫。在这个案例中,我们会爬取网页上的某个特定的信息,并提取出其中的关键词和摘要等信息保存到本地。本案例基于中文维基百科词条页面,所以需要熟悉Chromium浏览器的使用。

2.核心概念与联系

2.1 Web Scraping简介

网络爬虫(web crawling) 是一种按照一定的规则,自动地抓取网络上网页的程序。一般情况下,网络爬虫会按照设定的抓取策略向网站发起请求,获取网站的数据,然后再下载、解析、过滤、存储等后续操作,形成所需的数据。常见的网络爬虫有:搜索引擎蜘蛛(Googlebot、BaiduSpider)、网站收录(Sitemap、robots.txt)、互动式爬虫(AJAX、JavaScript渲染引擎)。

2.2 Python简介

Python是一种解释性语言,具有简洁、易读、高效、动态的特点。它用于数据处理、人工智能、系统编程、Web开发等领域。Python的语法清晰、可读性强,支持多种编程范式,是目前最流行的编程语言之一。Python的包管理工具pip可以方便地安装第三方库,提升开发效率。

2.3 Scrapy简介

Scrapy是一个开源的基于Python的网络爬虫框架,可以用来抓取网页,也可以用来抓取API数据。它可以轻松地处理复杂的网页结构,并且提供了很多功能,例如:数据缓存、下载器中间件、爬取管道、网页跟踪、可定制的调度器、插件系统等。 Scrapy框架是一个快速开发的框架,它的框架设计非常容易上手,而且功能也比较齐全。本文将围绕Scrapy framework提供的一个小型案例来阐述如何使用Python及Scrapy框架来实现网络爬虫。

3.核心算法原理和具体操作步骤以及数学模型公式详细讲解

3.1 数据抓取流程图

3.2 Web Scraping基本原理

Web scraping 的过程就是模拟人的行为去获取网站上的数据。简单的说,就是通过编写代码自动发送 HTTP 请求给指定的网站,获取网站源码,解析 HTML 或 XML 文件,提取想要的数据,然后保存到本地文件或数据库中。

3.2.1 模拟人类检索行为

Web scraping 通过“爬虫”的方式来完成数据抓取工作。爬虫按照一定模式在互联网上浏览网页,爬虫能够识别出那些带有特定信息的网页,并进一步跟踪这些网页上的链接,继续寻找更多有用信息。也就是说,爬虫模仿人的行为来浏览网页,分析网页结构,找到感兴趣的信息。通过网络爬虫,我们可以抓取到网站中隐藏的宝贵信息。

3.2.2 HTTP协议

HTTP(HyperText Transfer Protocol)即超文本传输协议,它定义了客户端和服务器之间交换数据的格式,使得 Web 抓取更加简单、高效。HTTP协议定义了四个主要的消息类型:

  • GET 请求:GET 请求用于从服务器获取资源。
  • POST 请求:POST 请求用于提交表单或者上传文件。
  • PUT 请求:PUT 请求用于更新资源。
  • DELETE 请求:DELETE 请求用于删除资源。

3.2.3 浏览器

浏览器是人们用来访问互联网的主要工具,也是Web抓取的重要组成部分。浏览器负责处理用户输入、呈现网页以及执行各种脚本,其中包括 JavaScript。Chrome、Firefox、Internet Explorer、Safari、Opera 等都是常用的浏览器。

3.3 安装Python环境

首先需要确保自己电脑上已安装Python,如果没有的话,请参考以下步骤安装。

  1. 根据自己的操作系统选择合适的版本下载。

  2. 在下载好的安装包上点击“运行”,等待安装程序运行完毕。

  3. 检查是否成功安装,打开命令提示符,输入python,出现如下图所示的内容表示安装成功:

3.4 安装Scrapy

Scrapy是一个用Python写的开源爬虫框架,我们可以使用pip命令安装Scrapy。

  1. 打开命令提示符,输入pip install scrapy。等待安装完成。

  2. 安装过程中可能出现权限错误,如遇到这种情况,可以尝试使用管理员权限打开命令提示符,或者直接在下载路径下右键以管理员身份运行cmd.exe。

  3. 安装好Scrapy之后,可以输入scrapy命令检查是否安装成功。出现如下图所示的内容则代表安装成功:

  4. 如果出现版本号太旧或者其他错误提示,可以尝试卸载当前版本的Scrapy,然后使用pip install --upgrade pip setuptools wheel升级pip安装工具,然后重新安装Scrapy。

3.5 创建第一个Scrapy项目

创建一个Scrapy项目,可以让我们更方便地构建我们的爬虫。

  1. 打开命令提示符,进入任意文件夹,创建一个名为myproject的文件夹,输入cd myproject切换到该目录。

  2. 使用scrapy startproject myproject创建Scrapy项目。等待完成。

    D:\>mkdir myproject
    D:\>cd myproject
    D:\myproject>scrapy startproject myproject
    
    Creating new project'myproject'
    Please see documentation at: https://docs.scrapy.org/en/latest/intro/tutorial.html
    
    Done! You can start your first spider with:
    
      cd myproject
      scrapy genspider example example.com
    
  3. 此时,myproject文件夹下会生成两个子文件夹:scrapy.cfg和myproject。

    D:\myproject>dir
    
     卷的序列号为 E04C-D107
    
     DirectoryName  :.
     FileType       : 文件夹
     CreationTime   : 2020/7/19 上午11:35:44
     LastWriteTime  : 2020/7/19 上午11:35:44
     修改时间        : 2020/7/19 上午11:35:44
    
    
     DirectoryName  :..
     FileType       : 文件夹
     CreationTime   : 2020/7/19 上午11:36:07
     LastWriteTime  : 2020/7/19 上午11:36:07
     修改时间         : 2020/7/19 上午11:36:07
    
    
    
     DirectoryName  : scrapy.cfg
     FileType       : 文本文件           C:\Windows\system32\drivers\etc\hosts              0 个字节            0 个字节
     CreationTime   : 2020/7/19 上午11:35:44
     LastWriteTime  : 2020/7/19 上午11:35:44
     修改时间        : 2020/7/19 上午11:35:44
    
    
     DirectoryName  : myproject
     FileType       : 文件夹
     CreationTime   : 2020/7/19 上午11:35:44
     LastWriteTime  : 2020/7/19 上午11:35:44
     修改时间        : 2020/7/19 上午11:35:44
    
    
     DirectoryName  : __pycache__
     FileType       : 文件夹
     CreationTime   : 2020/7/19 上午11:35:44
     LastWriteTime  : 2020/7/19 上午11:35:44
     修改时间        : 2020/7/19 上午11:35:44
    
    
    
  4. 执行以上命令后,会在myproject文件夹下创建一个新的Scrapy项目,包括scrapy.cfg和myproject两个子文件夹。

3.6 创建第一个爬虫

在myproject文件夹内创建一个爬虫example.py。

  1. 输入cd myproject进入到myproject文件夹下。

  2. 输入scrapy genspider example example.com创建一个新的爬虫example。

  3. 会看到一个新的文件example.py被创建出来。

    D:\myproject>cd example
    D:\myproject\example>dir
    
     卷的序列号为 E04C-D107
    
     目录名称      :.
     物理位置      : D:\myproject\example
     最后修改时间  : 2020/7/19 上午11:36:43
     尺寸          :               0 bytes
                            总计 0 bytes
     项            : 0 个
    
     目录名称      :..
     物理位置      : D:\myproject
     最后修改时间  : 2020/7/19 上午11:36:43
     尺寸          :               0 bytes
                            总计 0 bytes
     项            : 0 个
    
     目录名称      : __pycache__
     物理位置      : D:\myproject\example\__pycache__
     最后修改时间  : 2020/7/19 上午11:36:43
     尺寸          :               0 bytes
                            总计 0 bytes
     项            : 0 个
    
     目录名称      : items
     物理位置      : D:\myproject\example\items
     最后修改时间  : 2020/7/19 上午11:36:43
     尺寸          :               0 bytes
                            总计 0 bytes
     项            : 0 个
    
     目录名称      : middlewares
     物理位置      : D:\myproject\example\middlewares
     最后修改时间  : 2020/7/19 上午11:36:43
     尺寸          :               0 bytes
                            总计 0 bytes
     项            : 0 个
    
     目录名称      : pipelines
     物理位置      : D:\myproject\example\pipelines
     最后修改时间  : 2020/7/19 上午11:36:43
     尺寸          :               0 bytes
                            总计 0 bytes
     项            : 0 个
    
     目录名称      : settings
     物理位置      : D:\myproject\example\settings
     最后修改时间  : 2020/7/19 上午11:36:43
     尺寸          :               0 bytes
                            总计 0 bytes
     项            : 0 个
    
     目录名称      : spiders
     物理位置      : D:\myproject\example\spiders
     最后修改时间  : 2020/7/19 上午11:36:43
     尺寸          :               0 bytes
                            总计 0 bytes
     项            : 0 个
    
     D:\myproject\example>notepad example.py
    
    
  4. 用记事本打开example.py文件,编辑一下代码。

    import scrapy
    
    class ExampleSpider(scrapy.Spider):
        name = "example"
        allowed_domains = ["example.com"]
        start_urls = ['http://example.com']
        
        def parse(self, response):
            page_title = response.css('title::text').get()
            self.logger.info("Page title is %s", page_title)
            
            for quote in response.css('div.quote'):
                yield {
                    'author': quote.xpath('.//span[@class="author"]/text()').get(),
                    'text': quote.xpath('.//span[@class="text"]/text()').get(),
                }
                
            next_page_url = response.css('li.next a::attr(href)').get()
            if next_page_url:
                absolute_url = response.urljoin(next_page_url)
                yield scrapy.Request(absolute_url, callback=self.parse)
    
  5. 每当爬虫抓取到新的网页,就会调用parse()函数。在这里,我们简单打印了网页的标题并提取了页面中所有引用的内容。如果发现还有下一页,就递归请求下一页并调用parse()函数。

3.7 配置Scrapy项目

配置Scrapy项目是指为爬虫做一些必要的设置,比如URL列表、解析规则等。

在配置文件中我们可以指定爬虫的属性,比如名字、起始URL、域名、头部信息、代理设置等。我们可以在settings.py文件中配置项目。

  1. 在myproject文件夹下新建settings.py文件,添加以下代码。

    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
    
    ROBOTSTXT_OBEY = False
    
    DOWNLOAD_DELAY = 2 # 延迟两秒下载每一页
    
    CONCURRENT_REQUESTS = 16 # 设置最大并发数为16
    
    SPIDER_MIDDLEWARES = {
      'scrapy.spidermiddlewares.httperror.HttpErrorMiddleware': None, # disable default HttpErrorMiddleware
    }
    
    CLOSESPIDER_PAGECOUNT = 1 # 只爬取第一页
    
    DOWNLOADER_MIDDLEWARES = {
       'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
       'scrapy_fake_useragent.middleware.RandomUserAgentMiddleware': 400, # enable RandomUserAgentMiddleware
       'scrapy.downloadermiddlewares.retry.RetryMiddleware': 90, # retry failed requests
    }
    
    FAKEUSERAGENT_FALLBACK = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
    
  2. USER_AGENT属性用于设置爬虫的User-Agent,爬虫默认的User-Agent为空字符串。我们这里设置成了Chrome的User-Agent。ROBOTSTXT_OBEY属性用于禁止爬虫遵循robot.txt文件中定义的用户代理规范。DOWNLOAD_DELAY属性用于设置爬虫的请求间隔,这里设置为2秒。CONCURRENT_REQUESTS属性用于设置爬虫同时运行的请求数目。SPIDER_MIDDLEWARES属性用于禁用Scrapy默认的HttpErrorMiddleware。CLOSESPIDER_PAGECOUNT属性用于限制爬虫只爬取前N页。DOWNLOADER_MIDDLEWARES属性用于设置下载器中间件。FAKEUSERAGENT_FALLBACK属性用于设置用户代理的备选值。

3.8 运行爬虫

我们可以使用以下命令来运行爬虫。

  1. 输入cd myproject进入到myproject文件夹下。

  2. 输入scrapy crawl example启动爬虫。

    D:\myproject>cd example
    D:\myproject\example>scrapy crawl example
    

... 2020-07-19 13:03:37 [scrapy.core.engine] INFO: Spider opened 2020-07-19 13:03:37 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2020-07-19 13:03:37 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023 2020-07-19 13:03:37 [scrapy.core.engine] DEBUG: Crawled (200) <GET example.com> (referer: None) 2020-07-19 13:03:37 [scrapy.core.scraper] DEBUG: Scraped from <200 example.com>: u'\r\n\r\n Example Domain\r\n \r\n \r\n * {\r\n margin: 0;\r\n padding: 0;\r\n box-sizing: border-box;\r\n }\r\n\r\n body {\r\n font-family: sans-serif;\r\n line-height: 1.4;\r\n color: #333;\r\n max-width: 50em;\r\n margin: 0 auto;\r\n padding: 2em;\r\n }\r\n\r\n h1,\r\n p {\r\n margin-bottom: 1em;\r\n }\r\n\r\n header {\r\n background-color: #eee;\r\n padding: 1em;\r\n }\r\n\r\n nav {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n }\r\n\r\n nav ul {\r\n list-style: none;\r\n display: flex;\r\n }\r\n\r\n nav li {\r\n margin-left: 1em;\r\n }\r\n\r\n footer {\r\n text-align: center;\r\n margin-top: 2em;\r\n opacity: 0.5;\r\n }\r\n\r\n

\r\n

Example Domain

\r\n \r\n \r\n\r\n \r\n \r\n

About

\r\n

This domain is for use in illustrative examples in documents. You may use this\r\n domain in literature without prior coordination or asking for permission.

\r\n \r\n \r\n

Contact

\r\n \r\n

Email: info@example.com

\r\n

Twitter: @example

\r\n \r\n \r\n \r\n\r\n \r\n © 2020 by ExmplPleDomaine. All rights reserved.\r\n \r\n' 2020-07-19 13:03:37 [scrapy.core.engine] INFO: Closing spider (finished) 2020-07-19 13:03:37 [scrapy.statscollectors] INFO: Dumping Scrapy stats: {'finish_reason': 'finished', 'item_scraped_count': 0, 'log_count/DEBUG': 3, 'log_count/INFO': 7, 'memusage/max': 536870912, 'memusage/startup': 54776320, 'request_depth_max': 1, 'response_received_count': 1, 'scheduler/dequeued': 1, 'scheduler/dequeued/memory': 1, 'scheduler/enqueued': 1, 'scheduler/enqueued/memory': 1, 'start_time': datetime.datetime(2020, 7, 19, 11, 3, 37, 399591)}


3. 命令运行结束后,可以看到爬虫运行日志。如果不想显示控制台输出,可以添加`-s`参数。

D:\myproject\example>scrapy crawl example -s LOG_LEVEL=ERROR


4. 命令运行结束后,会在myproject文件夹下生成一个名为output.csv的文件,里面包含爬取的结果。

## 3.9 扩展思路
Web scraping 有很多应用场景,除了网站数据采集,还包括内容审核、数据清洗、广告过滤、社会网络分析等。本文仅用一个小例子展示了爬虫的基本原理和流程,希望大家能根据自身需求选择合适的框架和技术来实现数据采集。