Scrapy框架

Scrapy,Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试. Scrapy是基于事件的架构,可以使用xpath解析HTML。

1.xpath

XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航。

  • 选取节点

XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。

表达式			描述
nodename	选取此节点的所有子节点。
/			从根节点选取。
//			从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
.			选取当前节点。
..			选取当前节点的父节点。
@			选取属性。

实例

路径表达式	结果
bookstore	选取 bookstore 元素的所有子节点。
/bookstore	选取根元素 bookstore。
注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book	选取属于 bookstore 的子元素的所有 book 元素。
//book			选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book	选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang	选取名为 lang 的所有属性。
  • 谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点。谓语被嵌在方括号中。

XPATH从1开始,而不是从0开始。

路径表达式				结果
/bookstore/book[1]		选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]	选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]	选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3]	选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang]			选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang='eng']	选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00]	选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title	选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。
  • 选取未知节点

XPath 通配符可用来选取未知的 XML 元素。

通配符			描述
*	        匹配任何元素节点。
@*			匹配任何属性节点。
node()		匹配任何类型的节点。
  • 选取若干路径
通过在路径表达式中使用“ ”运算符,您可以选取若干个路径。
//title | //price	选取文档中的所有 title 和 price 元素。
  • XPath 轴

轴可定义相对于当前节点的节点集。

轴名称			结果
ancestor	选取当前节点的所有先辈(父、祖父等)。
ancestor-or-self	选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
attribute	选取当前节点的所有属性。
child		选取当前节点的所有子元素。
descendant	选取当前节点的所有后代元素(子、孙等)。
descendant-or-self	选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following	选取文档中当前节点的结束标签之后的所有节点。
namespace	选取当前节点的所有命名空间节点。
parent		选取当前节点的父节点。
preceding	选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling	选取当前节点之前的所有同级节点。
self		选取当前节点。
  • 步的语法:轴名称::节点测试[谓语]

    例子 结果 child::book 选取所有属于当前节点的子元素的 book 节点。 attribute::lang 选取当前节点的 lang 属性。 child::* 选取当前节点的所有子元素。 attribute::* 选取当前节点的所有属性。 child::text() 选取当前节点的所有文本子节点。 child::node() 选取当前节点的所有子节点。 descendant::book 选取当前节点的所有 book 后代。 ancestor::book 选择当前节点的所有 book 先辈。 ancestor-or-self::book 选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点) child::*/child::price 选取当前节点的所有 price 孙节点。

2. XLink与XPointer

XLink 定义了一套标准的在 XML 文档中创建超级链接的方法。

XPointer 使超级链接可以指向 XML 文档中更多具体的部分(片断)。

<?xml version="1.0"?>

<homepages xmlns:xlink="http://www.w3.org/1999/xlink">

  <homepage xlink:type="simple"
  xlink:href="http://www.w3school.com.cn">Visit W3School</homepage>
  
  <homepage xlink:type="simple"
  xlink:href="http://www.w3.org">Visit W3C</homepage>
  
</homepages>

XLink 的命名空间是:”http://www.w3.org/1999/xlink”。

href="http://www.example.com/cdlist.xml#id('rock').child(5,item)"

假如超级链接指向某个 XML 文档,我们可以在 xlink:href 属性中把 XPointer 部分添加到 URL 后面,这样就可以导航(通过 XPath 表达式)到文档中某个具体的位置了。 我们通过唯一的 id “rock” 使用 XPointer 指向某个列表中的第五个项目。

  • XQuery 被设计用来查询 XML 数据 - 不仅仅限于 XML 文件,还包括任何可以 XML 形态呈现的数据,包括数据库。

3. scrapy 命令

Scrapy主要包括了以下组件:

  • 引擎(Scrapy) 用来处理整个系统的数据流处理, 触发事务(框架核心)
  • 调度器(Scheduler) 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
  • 下载器(Downloader) 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
  • 爬虫(Spiders) 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
  • 项目管道(Pipeline) 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
  • 下载器中间件(Downloader Middlewares) 位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
  • 爬虫中间件(Spider Middlewares) 介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。 调度中间件(Scheduler Middewares) 介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。

scrapy 可以在命令行操作,调试,建立工程。

  • 建立工程:scrapy startproject [prjName]
  • 生成爬虫类:scrapy genspider basic web
  • 测试爬虫:scrapy crawl [basic]

4. Twisted 简介

Twisted是用Python实现的基于事件驱动的网络引擎框架,Twisted支持许多常见的传输及应用层协议,包括TCP、UDP、SSL/TLS、HTTP、IMAP、SSH、IRC以及FTP。

Twisted对于其支持的所有协议都带有客户端和服务器实现,同时附带有基于命令行的工具,使得配置和部署产品级的Twisted应用变得非常方便。

Python中用于对流式对象比如socket和pipe进行多路I/O复用的select模块(UNIX规范第3版(SUSv3)描述了select)

事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。另外两种常见的编程范式是(单线程)同步以及多线程编程

当我们面对如下的环境时,事件驱动模型通常是一个好的选择:

  • 程序中有许多任务,而且…
  • 任务之间高度独立(因此它们不需要互相通信,或者等待彼此)而且…
  • 在等待事件到来时,某些任务会阻塞。

------

  • 反应堆(reactor)

Twisted实现了设计模式中的反应堆(reactor)模式,这种模式在单线程环境中调度多个事件源产生的事件到它们各自的事件处理例程中去。

Reactor可以感知网络、文件系统以及定时器事件。它等待然后处理这些事件,从特定于平台的行为中抽象出来,并提供统一的接口,使得在网络协议栈的任何位置对事件做出响应都变得简单。

while True:
    timeout = time_until_next_timed_event()
    events = wait_for_events(timeout)
    events += timed_events_until(now())
    for event in events:
        event.process()

回调是事件驱动编程模型中的基础,也是reactor通知应用程序事件已经处理完成的方式。随着程序规模不断扩大,基于事件驱动的程序需要同时处理事件处理成功和出错的情况,这使得程序变得越来越复杂。Deferred对象作为一个关键部分,用来管理延后的结果以及相应的回调链。

  • Transports

Transports代表网络中两个通信结点之间的连接。Transports负责描述连接的细节,比如连接是面向流式的还是面向数据报的,流控以及可靠性。TCP、UDP和Unix套接字可作为transports的例子。

  • Protocols

Protocols描述了如何以异步的方式处理网络中的事件。HTTP、DNS以及IMAP是应用层协议中的例子。

参考:

  1. 教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神
  2. XPath
  3. c++ pugixml
  4. Twisted 简介
  5. Python Twisted介绍
  6. Set 和 WeakSet 数据结构