Scrapy学习二:基本概念进阶(未完成)

来源:互联网 发布:达梦数据库安装教程 编辑:程序博客网 时间:2024/06/03 20:34

基本概念详述

原始文档链接:https://docs.scrapy.org/en/latest/#basic-concepts 以及其中的后续链接。
前置链接:Scrapy学习一

  1. Command line tool —— 命令行工具
    管理Scrapy项目的工具
  2. Spiders —— 爬虫
    这个不用解释了吧
  3. Selectors —— 选择器
    使用CSS or XPath从网页提取数据
  4. Scrapy shell
    测试提取代码的可交互shell
  5. Items
    定义爬取的数据
  6. Item Loaders —— Item装载器
    用提取的数据构成Item
  7. Item Pipeline
    后续处理,以及存储爬获的数据。小型项目中留空
  8. Feed exports
    使用预定义的多种格式或存储输出爬获的数据
  9. Requests and Responses —— 请求和响应
    了解HTTP request和response报文中的class
  10. Link Extractors —— 链接提取器
    处理后续链接的实用类
  11. Settings —— 设置
    学习如何配置Scrapy可选项
  12. Exceptions —— 异常处理
    理解所有可用异常代码的意义

一、命令行工具

自0.10版中出现了命令行工具以后,Scrapy也可以由 scrapy 命令行命令控制进行工作。

注:有如下术语:command-line tool(命令行工具), Scrapy tool(Scrapy工具)都表达同一意思;但区别于术语:sub-commands(子命令),commands(命令),Scrapy commands(Scrapy命令)。

Scrapy工具提供了许多实用命令,有些命令针对多目标,有些针对每个目标可设置不同参数和选项集。

注:scrapy deploy 命令在1.0版本中被移除,以更好的支持 scrapyd-deploy 命令。详见:如何部署你的项目

1.1 配置设置

Scrapy所有参数配置在文件 scrapy.cfg 中。文件位置可以是:

1. /etc/scrapy.cfg 或 c:\scrapy\scrapy.cfg 作为系统级全局配置2. ~/.config/scrapy.cfg ($XDG_CONFIG_HOME) 或 ~/.scrapy.cfg ($HOME) 作为用户级全局配置,3. 在一个Scrapy项目中,作为项目级配置

配置文件的优先级为:项目级配置 覆盖 用户级配置 覆盖 系统级配置。

Scrapy还有一些环境变量,如:

  • SCRAPY_SETTINGS_MODULE
  • SCRAPY_PROJECT
  • SCRAPY_PYTHON_SHELL

1.2 Scrapy默认项目结构

在深入命令行工具之前,我们有必要先了解一下一个Scrapy项目的目录结构:

scrapy.cfgmyproject/    __init__.py    items.py    pipelines.py    settings.py    spiders/        __init__.py        spider1.py        spider2.py        ...

可以看到,scrapy.cfg 在项目根目录,spiders/目录下可以并存多个spider。
回到 scrapy.cfg ,在之前的学习中我们建立过一个 tutorial 项目,它的配置文档是这样的:

# Automatically created by: scrapy startproject## For more information about the [deploy] section see:# https://scrapyd.readthedocs.org/en/latest/deploy.html[settings]default = tutorial.settings[deploy]#url = http://localhost:6800/project = tutorial

我们可以看到,这是由 scrapy startproject 命令创建的配置文档,另一种创建配置文档的途径是 deploy (部署)。

1.3 使用 Scrapy 工具

我们尝试着运行一下 Scrapy 工具,如果不带正确的参数,并且不在一个项目内,会返回默认的帮助:

C:\ 项目外 > ScrapyScrapy 1.2.1 - no active projectUsage:  scrapy <command> [options] [args]Available commands:  bench         Run quick benchmark test  commands  fetch         Fetch a URL using the Scrapy downloader  genspider     Generate new spider using pre-defined templates  runspider     Run a self-contained spider (without creating a project)  settings      Get settings values  shell         Interactive scraping console  startproject  Create new project  version       Print Scrapy version  view          Open URL in browser, as seen by Scrapy  [ more ]      More commands available when run from project directoryUse "scrapy <command> -h" to see more info about a command

当进入项目,运行命令 scrapy

C:\tutorial> scrapyScrapy 1.2.1 - project: tutorial

会自动识别出项目。当然没有带正确的参数以前,返回的仍旧是一个默认的帮助页。

1.4 创建项目

我们之前已经学习过如何创建项目。但更通常地:

scrapy startproject myproject [project_dir]

项目由上述命令创建,项目名称为 myproject,项目位置为 project_dir 。当然如果不指定项目位置,默认就是项目当前位置。

1.5 控制项目

我们进入项目文件夹

cd project_dir

开始学习在项目内使用scrapy工具。

首先,你可以使用如下命令创建一个 spider:

scrapy genspider mydomain mydomain.com

之前提到过,一些命令必须在项目内部执行(例如:crawl);而 genspider 是全局命令。

注:关于Scrapy命令是项目内的还是全局的,可以参考:https://docs.scrapy.org/en/latest/topics/commands.html#topics-commands-ref

有些命令在项目内外运行时结果是不一样的。例如: fetch 命令,如果抓取的url指定了 spider,那么项目内的 spider 将被覆盖。(就像 user_agent 属性会覆盖 user-agent)。这样的覆盖是故意的,目的是为了使用 fetch 命令时能够获悉 spider 如何下载网页。

1.6 可用的命令

我们总是可以使用帮助命令:

scrapy -h

来查看所有可用命令。并使用:

scrapy <COMMAND> -h

来获得更详细的命令帮助信息。

如之前所说,命令分项目内的 Project-only commands 和项目外的 Global commands:

Global commands:

startprojectgenspidersettingsrunspidershellfetchviewversion

Project-only commands:

crawlchecklisteditparsebench

接下来将详细叙述它们。

1.6.1 startproject

  • 语法: scrapy startproject <project_name> [project_dir]
  • 基于项目:否
  • 用途:创建一个新的Scrapy项目,以 project_name 命名,目录为 project_dir 。如果不指定 project_dir,默认以 project_name 创建目录。
  • 示例:
    $ scrapy startproject myproject

1.6.2 genspider

  • 语法: scrapy genspider [-t template] <name> <domain>
  • 基于项目:否
  • 用途:创建一个新的spider。位置为(项目外)当前文件夹或(项目内)当前项目的 spiders/ 目录下。参数讲被传入 class 下的name属性,参数用来生成 allowed_domains 以及 start_urls。
  • 示例:

列举可用spider模板:

$ scrapy genspider -lAvailable templates:  basic  crawl  csvfeed  xmlfeed

使用默认模板basic创建名为example的spider:

$ scrapy genspider example example.com

使用模板crawl创建名为scrapyorg的spider,域限定 scrapy.org

$ scrapy genspider -t crawl scrapyorg scrapy.org

这些只是使用预定义模板创建spider的快捷命令,你也可以自己创建并修改xxxspider.py源文件。

1.6.3 crawl

  • 语法: scrapy crawl
  • 基于项目:yes
  • 用途:在项目中启动一个spider
  • 示例:$ scrapy crawl myspider

1.6.4 check

  • 语法: scrapy check [-l]
  • 基于项目:是
  • 用途:检查spiders py代码。如错误会详述错误,如正确则没有返回输出。
  • 示例:
$ scrapy check -lfirst_spider  * parse  * parse_itemsecond_spider  * parse  * parse_item
$ scrapy check[FAILED] first_spider:parse_item>>> 'RetailPricex' field is missing[FAILED] first_spider:parse>>> Returned 92 requests, expected 0..4

1.6.5 list

  • 语法: scrapy list
  • 基于项目:yes
  • 用途:列述当前项目种所有可用的spider。
  • 示例:
$ scrapy listspider1spider2

1.6.6 edit

  • 语法: scrapy edit
  • 基于项目:yes
  • 用途:编辑名为的spider。没人会用这个功能,你大可在自己的Python IDE中编辑代码。
  • 示例:$ scrapy edit spider1

1.6.7 fetch

  • 语法: scrapy fetch
  • 基于项目:否
  • 用途:用 Scrapy downloader 下载指定的 ,把输出写到 standard output。

这个命令有趣的地方是它会以spider中定义的方式获取目标url。例如如果spider中定义了 USER_AGENT 属性,那么这个命令会使用它来覆盖默认配置中的 User Agent。所以使用这条命令就能真是地看到spider所获取的页面。

同时注意到fetch命令是项目无关的,这表示如果在项目外输入了fetch命令,它也能获取页面,但只会使用默认的Scrapy下载器设定。

  • 支持的选项:
--spider=SPIDER: 强制使用指定的spider,忽略spider自动检测--headers: 显示响应的 HTTP header 而不是 body--no-redirect: 禁止 HTTP 3xx 重定向自动跳转 (默认为自动跳转)--nolog: 无日志
  • 示例:
$ scrapy fetch --nolog http://www.example.com/some/page.html[ ... html 内容 ... ]$ scrapy fetch --nolog --headers http://www.example.com/{'Accept-Ranges': ['bytes'], 'Age': ['1263   '], 'Connection': ['close     '], 'Content-Length': ['596'], 'Content-Type': ['text/html; charset=UTF-8'], 'Date': ['Wed, 18 Aug 2010 23:59:46 GMT'], 'Etag': ['"573c1-254-48c9c87349680"'], 'Last-Modified': ['Fri, 30 Jul 2010 15:30:18 GMT'], 'Server': ['Apache/2.2.3 (CentOS)']}

1.6.8 view

  • 语法: scrapy view
  • 基于项目:否
  • 用途:在浏览器中打开指定的URL,页面为spider“看到”的响应内容。由于有时spider“看到”的会跟你直接在真实的浏览器中看到的不一样,这个命令对于查看这之间的区别非常有用。
  • 支持的选项:
--spider=SPIDER: 强制使用指定的spider,忽略spider自动检测--no-redirect: 禁止 HTTP 3xx 重定向自动跳转 (默认为自动跳转)
  • 示例:
$ scrapy view http://www.example.com/some/page.html[ ... browser starts ... ]

1.6.9 shell

  • 语法: scrapy shell [url]
  • 基于项目:否
  • 用途:打开一个Scrapy shell,如果指定了URL,则基于此URL;否则打开一个空的shell。同时shell也支持打开本地文件,格式如类UNIX系统的相对路径 ./ or ../ 或直接使用绝对路径。
  • 支持的选项:
--spider=SPIDER: 强制使用指定的spider,忽略spider自动检测-c code: 在shell中对 code 求值, 显示结果并退出。code 形如'(response.status, response.url)'--no-redirect: 禁止 HTTP 3xx 重定向自动跳转 (默认为自动跳转)
  • 示例:
$ scrapy shell http://www.example.com/some/page.html[ ... scrapy shell starts ... ]$ scrapy shell --nolog http://www.example.com/ -c '(response.status, response.url)'(200, 'http://www.example.com/')# shell follows HTTP redirects by default$ scrapy shell --nolog http://httpbin.org/redirect-to?url=http%3A%2F%2Fexample.com%2F -c '(response.status, response.url)'(200, 'http://example.com/')# you can disable this with --no-redirect# (only for the URL passed as command line argument)$ scrapy shell --no-redirect --nolog http://httpbin.org/redirect-to?url=http%3A%2F%2Fexample.com%2F -c '(response.status, response.url)'(302, 'http://httpbin.org/redirect-to?url=http%3A%2F%2Fexample.com%2F')

1.6.10 parse

  • 语法: scrapy parse [options]
  • 基于项目:是
  • 用途:默认为使用项目中spider内的parse()函数处理给的的URL,或使用 –callback 选项指定回调函数来提取数据。
    Fetches the given URL and parses it with the spider that handles it, using the method passed with the –callback option, or parse if not given.

  • Supported options:

--spider=SPIDER: bypass spider autodetection and force use of specific spider--a NAME=VALUE: set spider argument (may be repeated)--callback or -c: spider method to use as callback for parsing the response--pipelines: process items through pipelines--rules or -r: use CrawlSpider rules to discover the callback (i.e. spider method) to use for parsing the response--noitems: don’t show scraped items--nolinks: don’t show extracted links--nocolour: avoid using pygments to colorize the output--depth or -d: depth level for which the requests should be followed recursively (default: 1)--verbose or -v: display information for each depth level
  • 示例:
$ scrapy parse http://www.example.com/ -c parse_item[ ... scrapy log lines crawling example.com spider ... ]>>> STATUS DEPTH LEVEL 1 <<<# Scraped Items  ------------------------------------------------------------[{'name': u'Example item', 'category': u'Furniture', 'length': u'12 cm'}]# Requests  -----------------------------------------------------------------[]

1.6.11 settings

  • 语法: scrapy settings [options]
  • 基于项目:否
  • 用途:获取Scrapy设置。人工查看配置文件时一般不使用这个方法。在项目外显示全局配置,在项目内显示项目配置。

  • 示例:

$ scrapy settings --get BOT_NAMEscrapybot$ scrapy settings --get DOWNLOAD_DELAY0

更多帮助参考:scrapy settings -h

1.6.12 runspider

  • 语法: scrapy runspider

1.6.13 version

  • 语法: scrapy version [-v]
  • 基于项目:no
  • 用途:显示Scrapy版本号。和 -v 一起用时会同时打印其他相关版本号如 Python, Twisted,lxml,libxml2,pyOpenSSL等等。

1.6.14 bench

New in version 0.17.

  • 语法: scrapy bench
  • 基于项目:否
  • 用途:运行benchmark。

三、选择器

爬取网页后,通常你还需要从HTML源文件中提取有用数据。我们有很多库可以用:

  • BeautifulSoup
  • lxml

(这个就不翻了)

Scrapy有其独特的数据提取机制,因为它“选择”HTML文档中的某些部分所以称它为选择器。通常HTML可表述为 XPath 或 CSS 格式:

  • XPath
  • CSS

(这个也不翻了)

Scrapy 选择器基于lxml库,所以它们的数据提取速度和精度是十分相近的。

本章将阐述选择器如何工作并详述API。虽然Scrapy选择器基于lxml库,但Scrapy旨在数据提取,而抛弃了lxml中不相干的功能,所以其API短小精悍。

完整的选择器API参考链接:https://docs.scrapy.org/en/latest/topics/selectors.html#topics-selectors-ref

3.1 构造选择器

Scrapy选择器是实例化的 Selector 类,输入为 text 或 TextResponse 对象。根据不同的输入对象(HTML或XML),选择器会自动选择提取规则,无需手动指定:

>>> from scrapy.selector import Selector>>> from scrapy.http import HtmlResponse

输入为文本:

>>> body = '<html><body><span>good</span></body></html>'>>> Selector(text=body).xpath('//span/text()').extract()[u'good']

输入为HTML响应:

>>> response = HtmlResponse(url='http://example.com', body=body)>>> Selector(response=response).xpath('//span/text()').extract()[u'good']

简单起见,可以使用 response 对象的 .selector 属性,方式如下:

>>> response.selector.xpath('//span/text()').extract()[u'good']

3.2 使用选择器

我们使用 Scrapy shell 来阐述如何使用选择器这一问题。Scrapy shell 在之前我们已初步涉及,更详细地教程在本文的下一章。

本小节要使用的示例在:https://doc.scrapy.org/en/latest/_static/selectors-sample1.html

直接在浏览器中使用如下代码来查看其HTML源代码:

view-source:https://doc.scrapy.org/en/latest/_static/selectors-sample1.html

HTML源代码如下:

<html> <head>  <base href='http://example.com/' />  <title>Example website</title> </head> <body>  <div id='images'>   <a href='image1.html'>Name: My image 1 <br /><img src='image1_thumb.jpg' /></a>   <a href='image2.html'>Name: My image 2 <br /><img src='image2_thumb.jpg' /></a>   <a href='image3.html'>Name: My image 3 <br /><img src='image3_thumb.jpg' /></a>   <a href='image4.html'>Name: My image 4 <br /><img src='image4_thumb.jpg' /></a>   <a href='image5.html'>Name: My image 5 <br /><img src='image5_thumb.jpg' /></a>  </div> </body></html>

首先,在cmd中打开Scrapy shell:

scrapy shell http://doc.scrapy.org/en/latest/_static/selectors-sample1.html

等待shell装载完成,你会得到 response shell变量和对应的 response.selector 属性。由于我们处理的是HTML,选择器会自动使用HTML解析数据。

我们来看一下HTML代码,然后构建一个 XPath 来选择 title tag中的文字:

>>> response.selector.xpath('//title/text()')[<Selector (text) xpath=//title/text()>]

由于 XPath和CSS十分常用,所以 response 定义了更简便的方法: response.xpath() 和 response.css() :

>>> response.xpath('//title/text()')[<Selector (text) xpath=//title/text()>]>>> response.css('title::text')[<Selector (text) xpath=//title/text()>]

跟前面一样,这两个简便方法也返回一个 SelectorList 实例:一个list结构的新 selector。

接下来我们通过这个API来提取内嵌img图像的数据:

>>> response.css('img').xpath('@src').extract()[u'image1_thumb.jpg', u'image2_thumb.jpg', u'image3_thumb.jpg', u'image4_thumb.jpg', u'image5_thumb.jpg']

如果是要提取文字型数据,必须使用如下:

>>> response.xpath('//title/text()').extract()[u'Example website']

如果只想提取第一个符合的数据,使用基础教程中提到过的 .extract_first() 。

>>> response.xpath('//div[@id="images"]/a/text()').extract_first()u'Name: My image 1 '

当没有查询结果时返回None:

>>> response.xpath('//div[@id="not-exists"]/text()').extract_first() is NoneTrue

此外,当没有查询结果时,我们可以修改参数使默认的None改成我们需要的其他值,如 ‘not-found’:

>>> response.xpath('//div[@id="not-exists"]/text()').extract_first(default='not-found')'not-found'

现在我们分别用xpath和css提取示例中的所有URL和图片链接:

>>> response.xpath('//base/@href').extract()[u'http://example.com/']>>> response.css('base::attr(href)').extract()[u'http://example.com/']>>> response.xpath('//a[contains(@href, "image")]/@href').extract()[u'image1.html', u'image2.html', u'image3.html', u'image4.html', u'image5.html']>>> response.css('a[href*=image]::attr(href)').extract()[u'image1.html', u'image2.html', u'image3.html', u'image4.html', u'image5.html']>>> response.xpath('//a[contains(@href, "image")]/img/@src').extract()[u'image1_thumb.jpg', u'image2_thumb.jpg', u'image3_thumb.jpg', u'image4_thumb.jpg', u'image5_thumb.jpg']>>> response.css('a[href*=image] img::attr(src)').extract()[u'image1_thumb.jpg', u'image2_thumb.jpg', u'image3_thumb.jpg', u'image4_thumb.jpg', u'image5_thumb.jpg']

3.3 selector嵌套

无论是 .xpath() 还是 .css() 方法,都返回一个List结构的选择器,所以你也可以对其再次调用选择方法:

>>> links = response.xpath('//a[contains(@href, "image")]')>>> links.extract()[u'<a href="image1.html">Name: My image 1 <br><img src="image1_thumb.jpg"></a>', u'<a href="image2.html">Name: My image 2 <br><img src="image2_thumb.jpg"></a>', u'<a href="image3.html">Name: My image 3 <br><img src="image3_thumb.jpg"></a>', u'<a href="image4.html">Name: My image 4 <br><img src="image4_thumb.jpg"></a>', u'<a href="image5.html">Name: My image 5 <br><img src="image5_thumb.jpg"></a>']>>> for index, link in enumerate(links):...     args = (index, link.xpath('@href').extract(), link.xpath('img/@src').extract())...     print 'Link number %d points to url %s and image %s' % argsLink number 0 points to url [u'image1.html'] and image [u'image1_thumb.jpg']Link number 1 points to url [u'image2.html'] and image [u'image2_thumb.jpg']Link number 2 points to url [u'image3.html'] and image [u'image3_thumb.jpg']Link number 3 points to url [u'image4.html'] and image [u'image4_thumb.jpg']Link number 4 points to url [u'image5.html'] and image [u'image5_thumb.jpg']
原创粉丝点击