(数据分析之数据采集与操作续)网络爬虫框架——Scrapy

 金诚   2018-03-30 12:47   217 人阅读  1 条评论

Scrapy——开源爬虫框架

Scrapy中的数据流由执行引擎ENGINE控制,如下所示:

    1. 引擎ENGINE从SPIDERS中获得初始请求。
    2. 引擎ENGINE将所有的请求请求放置调度程序SCHEDULER中和并接受调度程序发来的指令,以便于执行下一个请求抓取。
    3. 调度程序SCHEDULER的作用是用于返回下一个执行的请求,供给ENGINE去执行
    4. 引擎ENGINE发送请求到 下载器DOWNLOADER,通过 下载器中间件(见 process_request())。
    5. 一旦页面完成下载, Downloader会生成一个响应RESPONSE(包含该页面)并将其发送到引擎,并通过 Downloader Middlewares(请参阅 参考资料process_response())。
    6. 引擎ENGINER接收来自 下载器返回的响应RESPONSE并将其发送到所述SPIDERS进行处理,通过SPIDERS中间件(见 process_spider_input())。
    7. Spider处理响应,并通过 SPIDERS中间件(请参阅 参考资料)返回抓取的项目和新的请求(接下来)到 引擎。process_spider_output()
    8. 引擎ENGINE发送一个处理结果至项目管道ITEMPIPELINES,同时将请求发送至调度程序SCHEDULER,然后询问是否有下一次抓取请求。
    9. 该过程重复(从第1步开始),直到调度程序没有更多请求 。
    10. </ol start="1.">

总结来看整个框架有6大非常重要的概念:

      1. SPIDERS:小蜘蛛
      2. REQUESTS:请求体集合
      3. ENGINE:处理引擎
      4. SCHEDULER:请求调度器
      5. ITEMPIPELINES:项目管道
      6. DOWDLOADER:下载引擎
      7. </ol start="1.">

编写爬虫的过程,其实就是告诉SPIDRES 我们想爬的数据源,Scrapy框架会替我们完成组装请求、网络下载的过程,我们只需要定义SCHEDULER,控制多个小爬虫的优先级顺序,接着在ITEMPIPLINES中接受Scrapy爬取得数据结果集,对这些结果集进行清洗、校验、数据化存储(db、csv、json等)。

当你有更高的需求,比如提升下载速度,你可能会关注DOWDLOADER下载引擎模块,以及探寻6大模块的联系,你可能会关注ENGINE模块。

快速上手爬虫,是本节的目的。让我们来记住下面的指令吧!

Scrapy之旅

Scrapy安装

java
pip install scrapy (可能需要额外安装visual c++ build tools)

<pre class="line-numbers prism-highlight" data-start="1"><code class="language-null"><br /><br /><br /><br />下面开始scrapy体验之旅。

## 创建项目

在任何目录的任何地方,键入下方的指令,可以创建一个scrapy的项目
python
scrapy startproject tutorial

输出:

第一只小蜘蛛

在tutorial/spiders目录下创建一个名为quotes_spider.py的文件

输入下面的代码:

这个小蜘蛛有几个重要的组成:

  • 继承了Spider类scrapy.Spider
  • name,定义了蜘蛛的名称,一个scrapy工程,每个蜘蛛的name必须是唯一的。
  • start_requests() 这里是蜘蛛开始抓取的位置,在这里可以发起一连串的请求
  • parse() 这个函数可以处理引擎返回的响应体,下载每一个你希望下载的数据。

运行小蜘蛛

运行小蜘蛛很简单,只需要小心翼翼的跳入与scrapy.cfg 同级目录,并且输入以下指令即可:

  • crawl 表示开始抓取
  • quotes 是我们当初为小蜘蛛定义的名称

如果一切正常,小蜘蛛的编码没有任何错误,并且光标也处于scrapy.cfg的同级目录,那么我们会看到下面的语句:

在中括号[]里包含模块 名称,倒数第三行quotes就是小蜘蛛的 名称,在这里也看到了解析响应体的日志——文件保存成功!

你一定好奇HTML是如何被解析并保存到本地的,继续瞧,在后面的部分会解决你的 疑惑。

一种便利的写法去调用start_requests方法

在写第一只小蜘蛛的时候,我们定义了一个start_requests()函数,里面的语句较为繁琐,这里我们提供了另一种发起请求的写法:

使用 start_urls 列表!

在scrapy框架里,start_urls 列表与start_requests()函数式等价的,后者会发起一系列的请求,前者列表里的url参数,会默认被scrapy框架里的start_requests()调用。

这种写法的好处是,你只需要提供url,就够啦!

提取数据

有一节课程讲的非常棒 点击跳转

普通的写法,键入下面的命令,即可开始提取数据

scrapy shell 'http://quotes.toscrape.com/page/1/'

请记住,当运行scrapy脚本的时候,将url包裹起来,linux平台使用单引号包裹,windows平台有些小差别,需要使用双引号包裹
在windows平台下 ,这么写:
scrapy shell "http://quotes.toscrape.com/page/1/"
看到区别了吗?对,就是双引号。

输入上述指令后,你肯定能看到这些输出日志:

除去最开始 一堆scrapy log 日志外,最有用的就是 scrapy的提示文档

在“>>>”处,我们可以键入命令,控制scrapy做一些提取数据的操作

再提取数据之前,我们可以先查看url对应的html文件

这个指令可以吊起浏览器,打开本地保存的html文件;html是被crapy下载到本地的。

好了,我们尝试着提取数据:

比如:

通过response对象,我们总算从指定的url中提取到了些数据。

分析out输出的结果,是一个SelectorList对象,代表了一个存储许多Selector对象的列表,Selector对象代表了XML/HTML文件的元素。通过Selector对象,可以查询包含在HTML文件中的元素和数据。

Selector是重点,css()函数式重点!

对于css函数输入的参数值,我们并无从下手,比如为什么要写title,写成其他的值有没有效果?

css查询

语法:param::param

如果加上::text,会返回<title>标签中的内容

比如:

结果不太好看?再比如:

如果只写text,会返回整个<title>标签

小思考: 为什么会有extract()函数?

另一个使初学者好奇的,是extract()函数。首先我们要知道,我们正在处理的是一种特殊的对象——SelectorList,当我们想获取某些实实在在的数据,字符串、时间、url链接等,我们需要的SelectorList的属性对应的值,而不是只满足于拿到SelectorList对象。

这样我们就明白了,extract()是SelectorList对象的一个函数,可以帮助我们从指定标签拿到我们想要的数据

extract_first()能够提取SelectorList结果集的第一个值,使用这个函数有一个潜在风险,css()函数的查询结果为None的时候,并不存在第一个结果集,因此会抛出异常。切记哟。

也可以使用列表索引,从SelectorList中取值

除了extract()、extract_first(),我们还可以使用正则表达式

XPath 强大的选择表达式

scrapy选择器还支持XPath表达式,XPath是scrapy的作者强力推荐的功能:

Using XPath, you’re able to select things like: select the link that contains the text “Next Page”. This makes XPath very fitting to the task of scraping, and we encourage you to learn XPath even if you already know how to construct CSS selectors, it will make scraping much easier.

XPath强大到以至于笔者要单独开一篇讲解XPath的文章了,事实上,此时笔者对XPath的见解也非常浅薄。

留一个记录。日后一定补上XPath的说明和介绍。

提取作者和注解

如果你通过view(response)查看了响应体对应的html文件,就发现了html文件里的内容非常通俗易懂

我们从中计划从中一部分,计划使用scrapy,将我们希望截取的内容提炼出来

这一部分的内容,我们需要分析一下:

当我们对html文件的内容有一定清晰的认识后,接下来我们要在html中定位到这个名为quote的div,我们可以通过div.quote的语法格式,作为css()函数的输入参数。

输出:

输出结果是一个Selector列表,可以看到html中有多个名为quote的div,我们只需拿到其中一个,通过列表切片即可

拿到第一条quote,我们将结果赋值给一个临时变量,这个变量代表了Selector对象,接着我们的目标,就是从中取出文章的title、作者、标签

提取title

输出结果:

提取author

输出结果:

提取tag

输出结果:

使用蜘蛛提取数据

让我们回到蜘蛛上来,直到现在,我们的quote蜘蛛还并没有任何特殊的提取能力,它仅仅能够下载两个html文件而已。

现在我们加上上一节我们学到的response的知识

输出:

在命令行面板上,你将看到

修改后的蜘蛛,parse函数返回的是字典对象,在输出结果清晰可见的看到字典对象的text、tag、author属性的值。

恭喜你,目前已经入门scrapy的提取数据了!

存储提取的数据

scrapy提供了一种简单的保存方式:

上面这段话,可以将输出结果保存成一个json文件

你也可以使用这种方式保存:

本次数据提取之旅,这样做就足够了;但如果你想处理非常复杂的数据,就必须使用scrape item,这就要求我们必须写Item Pipeline。

沿着链接的指引

查看html上标记的next字符,表示当前页面的下一个页面链接。

我们希望拿到

 

  • 标签下的标签中的href属性,可以这样做先拿到带有链接的标签

    再从标签里拿到链接,可以通过 a::attr(href)获取

    当我们在shell界面完成上述这些测试后,再次修改scrapy中的quote小蜘蛛

    很多人好奇urljoin()代表什么意思,能返回什么样的值:

    我们通过测试可以看到urljoin()返回的是服务器根目录地址;那么就很容易理解,html中标签写的href链接,是相对于服务器根目录的地址了。

    便利的创建Requests

    对于scrapy.Request()这种需要传递绝对路径的写法,很多人纷纷表示不满。别急,scrapy提供了接收相对路径的方法:

    这样,就能向scrapy框架返回一个Request实例,供引擎调取做后续处理。

    更多的示例和组件

    parse_author、parse、response.follow、scrapy.Rquest

    使用蜘蛛的参数

    Scrapy常用命令

    • help: 查看帮助, scrapy --help • version: 查看版本信息,
    • scrapy version, 查看scrapy版本
    • scrapy version –v,查看相关模块的版本
    • startproject, 新建工程, scrapy startproject porj_name
    • genspider,生成spider模板, scrapy genspider spider_name url
    • list,列出所有的spider, scrapy list
    • view, 返回网页源代码并在浏览器中打开, scrapy view url
    • 有时页面渲染的结果和查看结果是不同的
    • parse, 调用工程spider中的parse解析url, scrapy parse url • shell, 进入交互式调试模式, scrapy shell url
    • bench, 可以用来检测scrapy是否安装成功

    参考

    1. scrapy shell 提取数据最佳练习
    2. using XPath with Scrapy Selectors here
    3. scrapy Selectors
    4. W3C XPath文档
    5. 正则表达式指引教程
    6. </ol start="1.">

 

本文地址:http://www.yangchaofan.cn/archives/442
版权声明:本文为原创文章,版权归 金诚 所有,欢迎分享本文,转载请保留出处!

1
说点什么

avatar
1 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
0 Comment authors
数据分析之数据采集与操作 – 程序员黄金屋 Recent comment authors
  Subscribe  
最新 最旧 得票最多
提醒
trackback

[…] 文章字数超限制了,请点击这篇阅读scrapy […]