Welcome to xpaw 0.12.0

Key Features

  • A web scraping framework used to crawl web pages
  • Data extraction tools used to extract structured data from web pages

Installation

安装xpaw需要Python 3.5.3或更高版本的环境支持。

可以使用如下命令安装xpaw:

$ pip install xpaw

如果安装过程中遇到lxml安装失败的情况,可参考 lxml installation

Requirements

Table of Contents

Make Requests

如果我们只是想下载URL对应的网页,但又不想写爬虫这么复杂的东西,那么我们可以直接借助 make_requests() 函数发起请求并获取结果。

from xpaw import make_requests, HttpRequest

if __name__ == '__main__':
    requests = ['http://unknown', 'http://python.org', HttpRequest('http://python.org')]
    results = make_requests(requests)
    print(results)

请求可以是 strHttpRequest ,如果是 str 则认为提供的是 GET 请求的URL。

返回结果是一个 list ,和发起的请求一一对应,可能是 HttpResponseException 。 因此可以先通过 isinstance 判断是否是正常返回的结果 HttpResponse 。 其次,如果是 Exception ,则表示请求出现了错误,例如常见的有 ClientError , HttpError (非2xx的HTTP状态码)。

使用 make_requests() 可以实现请求的并发执行,并提供了错误重试等诸多可选功能。

Note

make_requests()Spider 中使用会报错。 在 Spider 中处理请求的过程已经是并发的,因而也无需使用 make_requests()

xpaw.run.make_requests(requests, **kwargs)
Parameters:
  • requests (str or HttpRequest) – 请求列表
  • kwargs – 相关配置参数,详见 Settings

Tutorial I: First Spider

在这个tutorial中,我们的爬取目标为: quotes.toscrape.com ,在此特别感谢 scrapinghub 提供了这个测试爬虫的网站。

我们的需求为爬取网站中所有的quotes并以json的形式保存下来,每个quote包含如下几个字段:

名称 含义
text quote的内容
author quote作者
author_url 作者的相关链接
tags quote的标签列表

例如对于这个quote:

_images/quote_sample.png

我们得到的json数据为:

{
    "text": "“I have not failed. I've just found 10,000 ways that won't work.”",
    "author": "Thomas A. Edison",
    "author_url": "http://quotes.toscrape.com/author/Thomas-A-Edison",
    "tags": ["edison", "failure", "inspirational", "paraphrased"]
}

Spider Overview

我们编写的spider需要继承 xpaw.Spider 类,需要实现的功能包括:

  • 生成初始入口链接
  • 从爬取的网页中提取出所需的数据和后续待爬取的链接

我们首先给出spider的完整代码,然后再逐一进行解释:

from urllib.parse import urljoin
import json

from xpaw import Spider, HttpRequest, Selector, run_spider


class QuotesSpider(Spider):
    quotes = []

    def start_requests(self):
        yield HttpRequest('http://quotes.toscrape.com/', callback=self.parse)

    def parse(self, response):
        selector = Selector(response.text)
        for quote in selector.css('div.quote'):
            text = quote.css('span.text')[0].text
            author = quote.css('small.author')[0].text
            author_url = quote.css('small+a')[0].attr('href')
            author_url = urljoin(str(response.url), author_url)
            tags = quote.css('div.tags a').text
            self.quotes.append(dict(text=text, tags=tags,
                                    author=author, author_url=author_url))
        next_page = selector.css('li.next a')
        if len(next_page) > 0:
            next_page_url = urljoin(str(response.url), next_page[0].attr('href'))
            yield HttpRequest(next_page_url, callback=self.parse)

    def close(self):
        with open('quotes.json', 'w') as f:
            json.dump(self.quotes, f, ensure_ascii=False, indent=4)


if __name__ == '__main__':
    run_spider(QuotesSpider, log_level='DEBUG')

Start Requests

xpaw在加载spider后会调用其 start_requests 函数来获取整个爬取过程的入口链接,我们需要在该函数中生成入口链接并用HttpRequest进行封装。 在这个任务中,我们从网站首页开始即可遍历所有quotes所在的网页,因此入口链接选择网站的首页即可。

def start_requests(self):
    yield HttpRequest('http://quotes.toscrape.com/', callback=self.parse)

Note

start_requests 函数的返回值需为可迭代对象,如tuple, list, generator等。

HttpRequest的 callback 用来指定该request对应的response由哪个函数来处理。

Note

callback 只能指定为spider自身的成员函数。

Storing Data

在这个任务中,我们在spider的 close 函数中完整了数据的保存。 当爬取工作完成后,xpaw会调用spider的 close 函数 (如果存在的话),因此我们借机在该函数中将所有爬取到的quotes以json的格式写入到文件中。

def close(self):
    with open('quotes.json', 'w') as f:
        json.dump(self.quotes, f, ensure_ascii=False, indent=4)

Running Spider

我们通过xpaw内置的 run_spider 函数来运行spider,函数的第一个参数为spider类,相关配置可以通过关键词参数的形式进行设置。 例如这里我们通过 log_level='DEBUG' 设定日志的级别为 DEBUG 。 具体的配置项可参考 Settings

if __name__ == '__main__':
    run_spider(QuotesSpider, log_level='DEBUG')

运行我们的spider后会在同级目录下生成了quotes.json文件,打开即可看到爬取的quotes数据。

Spider

用户自定义的spider需要继承 xpaw.spider.Spider ,并重写如下函数:

Note

parse() 是默认处理 HttpResponse 的函数,如果在每个生成的 HttpRequest 中都通过 callback 指定了相应的处理函数 ,也可以不重写该函数。

Spider API

class xpaw.spider.Spider

用户自定义的spider需要继承此类。

classmethod from_crawler(crawler)
Parameters:crawler (Crawler) – crawler

crawler通过该函数实例化spider,在该函数中会调用spider的构造器

config

保存了爬虫相关的配置项,包括自定义配置项,参见 Config

crawler

通过crawler可以访问爬虫的各个组件,参见 Crawler

logger

提供纪录日志的logger。

log(message, *args, level=logging.INFO, **kwargs)

通过logger纪录日志。

start_requests()

生成初始请求

Returns:HttpRequest 的可迭代对象。
parse(response)

解析爬取结果

Parameters:response (HttpResponse) – 爬取结果。
Returns:可迭代对象,可以是新的请求 HttpRequest ,和提取的数据 Itemdict 等。
open()

爬虫开始工作前会调用该函数。

close()

爬虫完成工作时会调用该函数。

Parsing Data to Callback Functions

我们可以通过 HttpRequestcallback 指定spider的某个成员函数来处理得到的 HttpResponse 。 例如:

def parse_index_page(self, response):
    yield xpaw.HttpRequest("http://www.example.com/some_page.html",
                           callback=self.parse_some_page)

def parse_some_page(self, response):
    # handle the response of "http://www.example.com/some_page.html"
    self.log('Visited: %s', response.url)

有些时候,我们同时想传递一些和 HttpRequest 相关的参数并能够在callback函数中获取到。 例如,我们可能希望纪录父级页面的URL,即是由哪个页面跳转而来的。 我们可以通过 HttpRequestmeta 实现参数的传递。 以下是一个纪录父级页面的URL的示例:

def parse_index_page(self, response):
    request = xpaw.HttpRequest("http://www.example.com/some_page.html",
                               callback=self.parse_some_page)
    request.meta['referer'] = response.url
    yield request

def parse_some_page(self, response):
    self.log('Visited: %s', response.url)
    self.log('Referer: %s', response.meta['referer'])

Note

Request Error Handling in Errback Functions

我们可以通过 HttpRequesterrback 指定spider的某个成员函数来处理请过程中出现的异常。 下面给出了一个区分不同的异常并进行处理的示例:

class ErrorHandlingSpider(Spider):
    start_urls = [
        "http://www.python.org/",  # 200 OK
        "http://www.httpbin.org/status/404",  # 404 Not Found
        "http://www.httpbin.org/status/500",  # 500 Service Not Available
        "http://unknown/",  # ClientError
    ]

    def start_requests(self):
        for url in self.start_urls:
            yield HttpRequest(url, errback=self.handle_error)

    def parse(self, response):
        self.logger.info('Successful response: %s', response)

    def handle_error(self, request, error):
        if isinstance(error, HttpError):
            response = error.response
            self.logger.error('HttpError on %s: HTTP status=%s', request.url, response.status)
        elif isinstance(error, ClientError):
            self.logger.error('ClientError on %s: %s', request.url, error)


if __name__ == '__main__':
    run_spider(ErrorHandlingSpider, retry_enabled=False)

Request & Response

我们通过 HttpRequestHttpResponse 封装爬取的请求和对应的结果。

通常情况下, HttpRequest 一部分来自于spider中 start_requests() 方法生成的初始请求,另一部分来自于 parse() 方法解析页面得到的新的请求。 针对每个 HttpRequest ,如果请求成功xpaw会生成对应的 HttpResponse ,一般无需我们自己去构造 HttpResponse

Request API

class xpaw.http.HttpRequest(url, method="GET", body=None, params=None, headers=None, proxy=None, timeout=20, verify_ssl=False, allow_redirects=True, auth=None, proxy_auth=None, priority=None, dont_filter=False, callback=None, errback=None, meta=None, render=None)

用户通过此类封装HTTP请求。

Parameters:
  • url (str or URL) – URL地址
  • method (str) – HTTP method,GETPOST
  • body (bytes or str or dict) – 请求发送的数据。如果类型为 dict ,会默认为发送json格式的数据。
  • params (dict) – 请求参数
  • headers (dict or HttpHeaders) – HTTP headers
  • proxy (str) – 代理地址
  • timeout (float) – 请求超时时间
  • verify_ssl (bool) – 是否校验SSL
  • allow_redirects (bool) – 是否自动重定向
  • auth (tuple) – 认证信息,用户名和密码
  • proxy_auth (tuple) – 代理认证信息,用户名和密码
  • priority (float) – 请求的优先级
  • dont_filter (bool) – 是否经过去重过滤器
  • callback (str or method) – 请求成功时的回调函数,必须是spider的成员函数,也可以传递递函数名称
  • errback (str or method) – 请求失败时的回调函数,必须是spider的成员函数,也可以传递函数名称
  • meta (dict) – meta 属性的初始值,用于存储请求相关的元信息
  • render – 是否使用浏览器渲染
url

URL地址

method

HTTP method,GETPOST

body

请求发送的数据

headers

HTTP headers

proxy

代理地址

timeout

请求超时时间

verify_ssl

是否校验SSL

allow_redirects

是否自动重定向

auth

认证信息,用户名和密码

proxy_auth

代理认证信息,用户名和密码

priority

请求的优先级

dont_filter

是否经过去重过滤器。xpaw会根据此属性决定该请求是否经过去重过滤器,如果经过去重过滤器,被认定为重复的请求会被忽略。

callback

请求成功时的回调函数,必须是spider的成员函数,也可以传递递函数名称。

errback

请求失败时的回调函数,必须是spider的成员函数,也可以传递函数名称。

meta

只读属性,是一个 dict ,用于存储请求相关的元信息。 用户可将自定义的元信息存储在 meta 中。

render

是否使用浏览器渲染

copy()

复制request

replace(**kwargs)

复制request并替换部分属性

class xpaw.http.HttpHeaders

tornado.httputil.HTTPHeaders

Response API

class xpaw.http.HttpResponse(url, status, body=None, headers=None, request=None, encoding=None)
Parameters:
  • url (str) – URL地址
  • status (int) – HTTP状态码
  • body (bytes) – HTTP body
  • headers (dict or HttpHeaders) – HTTP headers
  • request (HttpRequest) – 爬虫请求
  • encoding (str) – HTTP body的编码格式
url

URL地址,如果是xpaw生成的response则类型为 URL

status

HTTP状态码

body

HTTP body

encoding

指定HTTP body的编码,如果没有指定,则会根据response的header和body进行自动推断。

text

只读属性,获取 body 对应的文本内容,在没有设置 encoding 的情况下会自动对编码进行推断。

headers

HTTP headers,如果是xpaw生成的response则类型为 HttpHeaders

request

对应的 HttpRequest

meta

只读属性,即为对应的 HttpRequestmeta 属性。

copy()

复制response。

replace(**kwargs)

复制response并替换部分属性。

Selector

Selector是基于 lxmlcssselect 封装的网页内容选择器,用于定位数据所在的网页节点,并对数据进行提取。 Selector相关API可以参考 Selector API

Selector Usage

我们通过一个实例来说明Selector的使用方法,相关代码位于 examples/selector_usage.py

下面给出的是 quotes.toscrape.com 的简化版网页,我们需要提取网页中展示的quote。

<html>
<head>
    <title>Quotes to Scrape</title>
    <link rel="stylesheet" href="/static/main.css">
</head>
<body>
    <div class="quote" itemscope itemtype="http://schema.org/CreativeWork">
        <span class="text" itemprop="text">“I have not failed. I&#39;ve just found 10,000 ways that won&#39;t work.”</span>
        <span>by <small class="author" itemprop="author">Thomas A. Edison</small>
        <a href="/author/Thomas-A-Edison">(about)</a>
        </span>
        <div class="tags">
            Tags:
            <a class="tag" href="/tag/edison/page/1/">edison</a>
            <a class="tag" href="/tag/failure/page/1/">failure</a>
            <a class="tag" href="/tag/inspirational/page/1/">inspirational</a>
            <a class="tag" href="/tag/paraphrased/page/1/">paraphrased</a>
        </div>
    </div>
    <div class="quote" itemscope itemtype="http://schema.org/CreativeWork">
        <span class="text" itemprop="text">“It is our choices, Harry, that show what we truly are, far more than our abilities.”</span>
        <span>by <small class="author" itemprop="author">J.K. Rowling</small>
        <a href="/author/J-K-Rowling">(about)</a>
        </span>
        <div class="tags">
            Tags:
            <a class="tag" href="/tag/abilities/page/1/">abilities</a>
            <a class="tag" href="/tag/choices/page/1/">choices</a>
        </div>
    </div>
</body>
</html>
Constructing Selectors

假设上面的网页内容存储在变量 text 中,我们可以通过如下的方式构造Selector:

from xpaw import Selector

selector = Selector(text)
Locating Elements

我们可以使用CSS Selector语法或XPath语法定位数据所在的节点。

有关CSS Selector语法的详细信息,可以参考 CSS Selector Reference 。 有关XPath语法的详细信息可以参考 XPath Syntax

首先我们需要观察数据所在节点的在标签层次上的特征,然后再将这种特征通过CSS Selector语法或XPath语法进行描述。

例如,我们可以观察到每个quote都在一个 class=quote<div> 标签中,每个quote的内容都在一个 class=textspan 标签中。 接下来,我们可以用CSS Selector语法对这些特征进行描述,并借助Selector来提取quote的内容:

print('# CSS Selector, content of quotes:')
for quote in selector.css('div.quote'):
    print(quote.css('span.text')[0].text)
# CSS Selector, content of quotes:
“I have not failed. I've just found 10,000 ways that won't work.”
“It is our choices, Harry, that show what we truly are, far more than our abilities.”

也可以用XPath语法对这些特征进行描述,并借助Selector来提取quote的内容:

print('# XPath, content of quotes:')
for quote in selector.xpath('//div[@class="quote"]'):
    print(quote.xpath('.//span[@class="text"]')[0].text)
# XPath, content of quotes:
“I have not failed. I've just found 10,000 ways that won't work.”
“It is our choices, Harry, that show what we truly are, far more than our abilities.”

根据观察的特征不同,我们可能会写出不同的表达式。 例如,我们也可以认为每个quote的内容在 itemprop="text"span 标签中:

for quote in selector.css('div.quote'):
    print(quote.css('span[itemprop="text"]')[0].text)

cssxpath 是可以级联使用的,例如:

for t in selector.css('div.quote').css('span.text'):
    print(t.text)

cssxpath 也可以混合使用,例如:

for t in selector.xpath('//div[@class="quote"]').css('span.text'):
    print(t.text)
Extracting Data

除了前面展示的可以通过 text 属性获取节点中不包含标签的文本,我们还可以通过 string 属性获取完整的带标签的内容:

print('# CSS Selector, content of quotes, with HTML tags:')
for quote in selector.css('div.quote'):
    print(quote.css('span.text')[0].string)
# CSS Selector, content of quotes, with HTML tags:
<span class="text" itemprop="text">“I have not failed. I've just found 10,000 ways that won't work.”</span>
<span class="text" itemprop="text">“It is our choices, Harry, that show what we truly are, far more than our abilities.”</span>

对于选择出的节点列表,同样可以采用这样的方式获取数据,得到的即为数据的列表。 例如我们获取每个quote下面所有的tag:

print('# CSS Selector, quote tags')
for quote in selector.css('div.quote'):
    print(quote.css('a.tag').text)
# CSS Selector, quote tags
['edison', 'failure', 'inspirational', 'paraphrased']
['abilities', 'choices']

如果需要获取节点属性值,则可以使用 attr() 。 例如我们获取quote作者的链接:

print('# CSS Selector, author urls')
for quote in selector.css('div.quote'):
    print(quote.css('small+a')[0].attr('href'))
# CSS Selector, author urls
/author/Thomas-A-Edison
/author/J-K-Rowling

Selector API

class xpaw.selector.Selector(text=None, root=None, text_type=None)

节点和数据的选择器。

Parameters:
  • text (str) – HTML或XML文本
  • root – 根节点,textroot 只需指定其中一个,当指定 text 时,会自动创建 root
  • text_type (str) – htmlxml,默认为 html
root

根节点

css(css, **kwargs)

使用CSS Selector语法选择节点。

Parameters:css (str) – CSS Selector语法描述
Returns:选择的节点对应的 SelectorList
xpath(xpath, **kwargs)

使用XPath语法选择节点。

Parameters:xpath (str) – XPath语法描述
Returns:选择的节点对应的 SelectorList
string

获取节点包括标签在内的全部内容。

text

获取节点去掉标签后的文本内容。

attr(name)

获取节点的属性。

Parameters:name (str) – 属性名称
class xpaw.selector.SelectorList

SelectorList 是由 Selector 组成的 list

css(css, **kwargs)

对其中的每一个 Selector 使用CSS Selector语法选择节点。

Parameters:css (str) – CSS Selector语法描述
Returns:选择的节点对应的 SelectorList
xpath(xpath, **kwargs)

对其中的每一个 Selector 使用XPath语法选择节点。

Parameters:xpath (str) – XPath语法描述
Returns:选择的节点对应的 SelectorList
string

获取各个节点包括标签在内的全部内容,返回 list

text

获取各个节点去掉标签后的文本内容,返回 list

attr(name)

获取各个节点的属性,返回 list

Parameters:name (str) – 属性名称

Settings

爬虫相关配置项可以通过如下几种方式设定:

  • 命令行 - 直接在命令行中设定的配置项。
  • 命令行配置文件 - 在命令行中通过参数 -c, --config 指定的配置文件中的配置项。
  • 工程配置文件 - 在工程的配置文件 config.py 中设定的配置项。
  • 默认配置 - 默认的配置项。

配置的优先级为: 命令行 > 命令行配置文件 > 工程配置文件 > 默认配置 ,对于同一配置项,高优先级的配置会覆盖低优先级的配置。 在 make_requestsrun_spider 等函数中传递的关键字参数的优先级视为和命令行参数一致。

接下来我们会按类别依次给出爬虫相关的各个配置项。

Running

daemon
  • -d, --daemon
  • Default: False

是否在后台运行。

pid_file
  • --pid-file
  • Default: None

保存爬虫进程PID的文件。

Logging

log_level
  • -l, --log-level
  • Default: info

日志级别。

log_file
  • --log-file
  • Default: None

日志写入的文件。

Downloading

downloader_clients
  • Default: 100

下载时的并发量。

renderer_cores
  • Default: downloader_clients

渲染进程的并发量。

chrome_renderer_options
  • Type: dict

Chrome渲染器的配置,以 'NAME': {'arguments': [], 'experimental_options': {}} 的方式进行配置,其中 NAME 表示渲染器类别的名称。

default_headers
  • Default: None
  • Type: dict

默认添加的HTTP请求的header。

user_agent
  • Default: :desktop

指定HTTP请求头的User-Agent字段。

: 开头表示命令模式,命令分为终端类型和浏览器类型, 终端类型包括 desktopmobile,浏览器类型包括 chrome 。 多个命令之间用逗号 , 隔开,如 :mobile,chrome 表示移动端的Chrome浏览器。

其他字符串则直接视为User-Agent。

Note

只有当 default_headers 中没有设置 User-Agent 时, user_agent 配置才会生效。

random_user_agent
  • Default: False

随机设定HTTP请求头的User-Agent字段。

user_agent 为命令模式时,随机生成符合其约束的User-Agent;当 user_agent 为普通字符串时,则会覆盖其设置。

proxy
  • Default: None

设置HTTP请求的代理,可以为单个代理,也可以为多个代理的list。

Retry

retry_enabled
  • Default: True

是否重试失败的HTTP请求。

max_retry_times
  • Default: 3

最大重试次数。

retry_http_status
  • Default: None
  • Type: list , tuple

进行重试的HTTP状态码。

可以用 x 表示通配,例如 20x 表示 200202 等所有 20 开头的状态码, 4xx 表示所有 4 开头的状态码。

前面加 ! 表示取反,例如 !2xx 表示所有不是以 2 开头的状态码。

Spider Behaviour

speed_limit
  • Type: dict

rate 表示下载速率,单位:请求/秒, burst 表示下载时最大并发量。

max_depth
  • Default: None
  • Type: int

爬虫的爬取的最大深度, None 表示没有限制。

Components

spider
  • Default: None

使用的爬虫类或爬虫类路径。

extensions
  • Default: None

使用的拓展。

Errors

Built-in Errors

这里给出了内置的错误类型。

class xpaw.errors.NotEnabled

在加载组件的时候抛出的异常,表示该组件未启用。

class xpaw.errors.ClientError

在downloader发起请求过程中抛出的异常,例如服务器无法访问等。

class xpaw.errors.HttpError

非2xx响应抛出的异常。

class xpaw.errors.IgnoreRequest

在处理 HttpRequest 时抛出的异常,表示忽略该request,例如到达了一定的重试次数等。

class xpaw.errors.IgnoreItem

在处理 Item 时抛出的异常,表示忽略该item。

class xpaw.errors.UsageError

xpaw相关命令使用方法不正确时抛出的异常。

class xpaw.errors.CloseCrawler

在spider的处理 HttpResponse 的回调函数中可以抛出该异常,主动停止crawler。

Architecture Overview

这里我们会对xpaw的结构进行简要的介绍。

首先我们会给出爬虫运行过程中的数据流图,接着我们会对数据流中呈现的各个组件进行简要的介绍。

Data Flow

数据流以crawler为核心,并由crawler进行控制和驱动:

_images/data_flow.png
  1. crawler从spider中获取初始请求 HttpRequest
  2. crawler将得到 HttpRequest 放入到queue中。
  3. crawler不停地从queue中获取待处理的 HttpRequest
  4. crawler将 HttpRequest 交由downloader处理。
  5. downloader完成下载后生成 HttpResponse 返回给crawler。
  6. crawler将得到的 HttpResponse 交由spider处理。
  7. spider处理 HttpResponse 并提取数据 Item 和新的请求 HttpRequest
  8. crawler将得到的 HttpRequest 放入到queue中。

爬虫会持续运行直到所有生成的requests都被处理完且不再生成新的requests为止。

Components

Crawler

实现对各个组件的控制和驱动。

Queue

存储 HttpRequest 的队列。

Downloader

基于协程实现异步下载功能。

Spider

用户在 Spider 中实现采集任务的核心逻辑,包括网页解析、数据抽取、链接抽取等。

Core API

Crawler API

通常用户自定义的组件可以在class中定义类似如下的函数,来达到获取配置的目的:

@classmethod
def from_crawler(cls, crawler):
    return cls(crawler.config)

对于用户自定义的组件,xpaw会首先检查是否存在名为 from_crawler 的函数,如果存在则会通过调用 from_crawler 来实例化对象:

foo = FooClass.from_crawler(crawler)

如果不存在该函数,则会调用默认的不含参数的构造器来实例化:

foo = FooClass()

对于spider来讲,由于强制要求继承 Spider 类,且在该类中已经实现了 from_crawler 函数,我们可以直接在spider中通过 self.config 来获取配置,通过 self.crawler 来获取crawler。

from_crawler 提供了获取crawler的途径,通过crawler我们不仅可以获取到 config ,也可以获取到其他的我们需要使用的crawler的属性。

class xpaw.crawler.Crawler(config)

本地模式的crawler

Parameters:config (Config) – 爬虫相关的配置项
config

爬虫相关的配置项,对于 config 的使用可以参考 Config API

Config API

class xpaw.config.Config(__values=None, **kwargs)

管理爬虫配置的类。

get(name, default=None)

获取配置

Parameters:
  • name (str) – 参数名称
  • default – 缺省值
getbool(name, default=None)

获取 bool 型参数,如果值不能转换为 bool 类型,返回 None

getint(name, default=None)

获取 int 型参数,如果值不能转换为 int 类型,返回 None

getint(name, default=None)

获取 float 型参数,如果值不能转换为 float 类型,返回 None

getlist(name, default=None)

将参数值封装为 list 并返回。 如果参数值是 str ,则会根据 , 分隔为多个参数值。

set(name, value):

设置参数值

Parameters:
  • name (str) – 参数名称
  • value – 参数值
update(values):

更新参数

Parameters:values (dict or Config) – 新的参数
delete(name):

删除参数

Parameters:name – 参数名称
copy()

复制配置

Specific Problems

Cron Job

可以使用 @every 实现定时任务,每隔设定的时间会重复执行被修饰的 start_requests 函数:

from xpaw import Spider, HttpRequest, Selector, every, run_spider


class CronJobSpider(Spider):
    @every(seconds=10)
    def start_requests(self):
        yield HttpRequest("http://news.baidu.com/", callback=self.parse, dont_filter=True)

    def parse(self, response):
        selector = Selector(response.text)
        hot = selector.css("div.hotnews a").text
        self.log("Hot News:")
        for i in range(len(hot)):
            self.log("%s: %s", i + 1, hot[i])


if __name__ == '__main__':
    run_spider(CronJobSpider)

@every 可传入的参数:

  • hours : 间隔的小时数
  • minutes : 间隔的分钟数
  • seconds : 间隔的秒数

注意需要通过参数 dont_filter=True 来设置 HttpRequest 不经过去重过滤器,否则新产生的 HttpRequest 会视为重复的请求。

Dynamic Webpages

一种解决方案是借助Chrome的调试工具找到动态内容请求的接口,然后在爬虫中直接从接口拿数据。

另一种方案是在 HttpRequest 中设置 render=True ,则会默认使用Chrome浏览器对页面进行渲染。

from xpaw import Spider, HttpRequest, Selector, run_spider


class RenderingSpider(Spider):
    def start_requests(self):
        yield HttpRequest('http://quotes.toscrape.com/js/', callback=self.parse, render=True)

    def parse(self, response):
        selector = Selector(response.text)
        for quote in selector.css('div.quote'):
            text = quote.css('span.text')[0].text
            author = quote.css('small.author')[0].text
            self.log(author + ": " + text)


if __name__ == '__main__':
    run_spider(RenderingSpider)

Note

如果需要使用渲染功能,则需要提前装好Chrome驱动。

Changelog

0.12.0 (2019-08-10)

  • 移除爬虫工程初始化相关功能,推荐使用单文件spider或指定爬虫启动脚本
  • 统一middleware、pipeline、extension等概念,统一由 extensions 配置爬虫的拓展

0.11.2 (2019-08-06)

  • 重构Chrome渲染器,由每次新建Chrome进程变为维护每个Chrome进程的tab
  • 添加 chrome_renderer_options 配置项,实现同时运行多个具有不同设置的Chrome渲染器
  • 修复爬虫工程的配置模版

0.11.1 (2019-07-29)

  • 移除 HttpRequest 中的 params 属性,但在构建 HttpRequest 时依然可以传入 params

0.11.0 (2019-07-11)

  • 移除对aiohttp的依赖,改由tornado实现HTTP请求,新增pycurl依赖
  • 添加基于Selenium和Chrome driver的渲染器
  • 添加Docker镜像 jadbin/xpaw ,便于构建爬虫运行环境
  • 暂时移除对cookies和cookie jar的支持
  • 组件cluster更名为crawler,包含cluster命名的模块、对象、函数、配置等均作出了相应的替换
  • 运行爬虫工程的 run_crawler 接口更名为 run_spider_project
  • 非2xx的HttpResponse将视为请求失败并抛出 HttpError 异常进入错误处理流程
  • RetryMiddleware不再raise IgnoreRequest,即因达到重试次数上限而导致请求失败时不再封装为IgnoreRequest,将保留原有的HttpResponse或异常
  • HttpRequest proxy , timeout , verify_ssl , allow_redirects , auth , proxy_auth 由在 meta 中配置改为直接作为HttpRequest的属性
  • Selector之前在遇到异常时会返回空数组,现在改为直接抛出异常
  • 修改ProxyMiddleware的配置格式
  • 移除ImitatingProxyMiddleware
  • 修改SpeedLimitMiddleware的配置格式
  • 移除 config.py 中的 downloader_timeout , verify_ssl , allow_redirects 配置项
  • 移除 xpaw.FormData , xpaw.URL
  • 移除 xpaw.MultiDict , xpaw.CIMultiDict , 改由 xpaw.HttpHeaders 替代承载headers的功能
  • 移除请求超时错误TimeoutError,统一由ClientError表示downloader抛出的异常
  • default_headers 默认为 None , 浏览器默认的HTTP header改由UserAgentMiddleware根据设定的浏览器类型进行设置
  • xpaw.downloadermws 模块更名为 xpaw.downloader_middlewaresxpaw.spidermws 模块更名为 xpaw.spider_middlewares
  • @every 装饰器移至 xpaw.decorator 模块
  • 移除对 dump_dir 的支持

0.10.4 (2018-11-06)

  • 在生成初始请求过程中,捕获单个请求抛出的异常并记录日志

0.10.3 (2018-09-01)

  • ProxyMiddleware不会覆盖用户在HttpRequest meta 中设置的 proxy
  • CookiesMiddleware不会覆盖用户在HttpRequest meta 中设置的 cookie_jar
  • NetworkError更名为ClientError,同时请求超时改由TimeoutError表示

0.10.2 (2018-08-28)

  • Field添加 type 参数,表示该字段的类型,在获取该字段的值时会进行类型转换
  • 添加 allow_redirects 配置项,控制是否允许重定向,默认为 True
  • HttpRequest meta 添加 verify_sslallow_redirects 字段,用于精确控制单次请求的相关行为
  • 添加 StopCluster 异常,用于在spider在回调函数中停止cluster
  • 添加 request_ignored 事件
  • user_agent 默认值设置为 :desktop
  • 运行spider之后不会再移除主程序已经设置的signal handler

0.10.1 (2018-07-18)

  • 新增 make_requests 函数,用于发起请求并获取对应的结果,详见 Make Requests
  • log_level 支持小写字母配置,如 debug

0.10.0 (2018-07-15)

  • xpaw crawl 支持直接运行spider,支持指定配置文件,添加了更多的功能选项
  • 添加 daemon 配置项,支持以daemon模式运行爬虫
  • 添加 pid_file 配置项,支持将爬虫所在进程的PID写入文件
  • 添加 dump_dir 配置项,支持爬虫的暂停与恢复
  • 运行spider结束时移除配置的log handler,避免先后多次运行spider时打印多余的日志
  • 移除爬虫工程的入口文件setup.cfg,直接通过工程根目录下的config.py完成配置
  • 重构ProxyMiddleware配置项
  • 通过 speed_limit_enabled 控制限速中间件SpeedLimitMiddleware的开启/关闭,默认为关闭状态
  • 配置项 verify_ssl 的默认值更改为 False
  • 配置项 queue_cls 更名为 queue
  • 配置项 dupe_filter_cls 更名为 dupe_filter
  • cluster的 stats_center 更名为 stats_collector ,配置项 stats_center_cls 更名为 stats_collector
  • 调整了中间件加载顺序权值
  • HttpRequest对 auth , cookie_jar , proxy , proxy_auth 的配置移至 meta 属性中
  • SetDupeFilter更名为HashDupeFilter
  • 修改aiohttp的版本限制为>=3.3.2

0.9.1 (2018-04-16)

  • 修复了setup.py中读取README的编码设置问题
  • 不再只依赖于通过定时轮询判定job是否结束,单次下载完成后即判定job是否结束
  • 修改依赖库的版本限制

0.9.0 (2017-11-13)

  • 中间件的加载细分为内置中间件和用户自定义中间件两部分,内置中间件自动加载,用户中间件的加载由配置项确定
  • 中间件加载的顺序由配置的权值确定,权值越大越贴近downloader/spider
  • 添加 NotEnabled 异常,在中间件/拓展的构造函数中控制抛出该异常来实现开启或禁用该中间件/拓展。
  • 添加UserAgentMiddleware,支持选择PC端或移动端的User-Agent,支持随机User-Agent
  • 支持配置日志写入指定文件
  • 修复了HttpRequest的fingerprint计算时没有考虑端口号的bug
  • 移除ResponseNotMatchMiddleware
  • 移除ProxyAgentMiddle,原有功能并入ProxyMiddleware
  • 修改了RetryMiddleware,ProxyMiddleware,DepthMiddleware的参数配置方式
  • ForwardedForMiddleware更名为ImitatingProxyMiddleware,用于设置HTTP请求头的 X-Forwarded-ForVia 字段
  • 系统配置 downloader_verify_ssl 更名为 verify_ssldownloader_cookie_jar_enabled 更名为 cookie_jar_enabled
  • 更新了downloader和spider相关的错误处理流程
  • 更新了判定job结束的逻辑

0.8.0 (2017-11-5)

  • spider的 start_requestsparse 函数支持async类型和python 3.6中的async generator类型
  • spider中间件的handle_*函数支持async类型
  • 添加事件驱动相关的eventbus和events模块,支持事件的订阅/发送,可通过 cluster.event_bus 获取event bus组件
  • 捕获SIGINT和SIGTERM信号并做出相应处理
  • 添加extension模块,支持用户自定义拓展
  • 添加statscenter模块,用于收集,管理系统产生的各项统计量,可通过 cluster.stats_center 获取stats center组件; 系统配置添加 stats_center_cls 项,用于替换默认的stats center的实现
  • SetDupeFilter添加 clear 函数
  • 系统配置添加 downloader_verify_ssl 项,用于开启或关闭SSL证书认证
  • HttpRequest的 body 参数支持 bytes , str , FormData , dict 等形式
  • HttpRequest添加 params , auth , proxy_auth , priority 等属性
  • 添加深度优先队列LifoQueue,以及优先级队列PriorityQueue,默认 queue_cls 更改为 xpaw.queue.PriorityQueue
  • 支持设定HTTP请求的优先级并按优先级进行爬取
  • 添加item,pipeline模块,支持spider在处理response时返回BaseItem的实例或dict,并交由用户自定义的item pipelines进行处理
  • 实例化中间件的classmethod from_config 更改为 from_cluster ,现在 config 参数可以通过 cluster.config 获取
  • queue组件的 push , pop 函数,以及dupefilter组件的 is_duplicated 函数改为async类型
  • 移除queue组件和dupefilter组件的基类,RequestDequeue更名为FifoQueue
  • 系统不再默认调用dupefilter组件和queue组件的 openclose 函数,如果自定义的组件包含这些函数,可通过订阅相关事件的方式进行调用
  • 系统配置 dupefilter_cls 更名为 dupe_filter_cls ,cluster的 dupefilter 属性更名为 dupe_filter
  • RequestHeadersMiddleware更改为DefaultHeadersMiddleware,配置字段 request_headers 更改为 default_headers,功能由覆盖headers变为设置默认的headers
  • 修改了MaxDepthMiddleware更改为DepthMiddleware的参数配置方式,功能变为记录request的depth并对max depth加以限制
  • 修改了ProxyMiddleware和ProxyAgentMiddleware的参数配置方式
  • 移除CookieJarMiddleware,通过 downloader_cookie_jar_enabled 配置是否启用cookie
  • 重写了SpeedLimitMiddleware,通过 rate (采集速率) 和 burst (最大并发数) 来限制采集速率
  • 更新了 request_fingerprint 的计算方式
  • 修改aiohttp的版本限制为>=2.3.2

0.7.1 (2017-10-25)

  • 通过 @every 实现定时任务功能
  • HttpRequest添加 dont_filter 字段,为 True 时表示该请求不会被过滤
  • xpaw.run 模块中添加 run_spider 函数,便于在python代码中直接运行Spider类
  • xpaw.utils.run 模块中 run_crawler 函数移动至 xpaw.run 模块
  • 原utils, commands, downloadersmws, spidermws各合并为一个模块

0.7.0 (2017-10-24)

  • 使用继承Dupefilter的去重过滤器来实现去重功能,系统配置添加 dupefilter_cls 项,用于替换默认的去重过滤器
  • xpaw.utils.run 模块中添加 run_crawler 函数,便于在python代码中控制开启爬虫
  • 使用config.py替代config.yaml作为配置文件,移除对pyyaml的依赖
  • ForwardedForMiddleware移动到 xpaw.downloadermws.headers 模块下
  • 修改aiohttp的版本限制为>=2.2.0
  • 更新了downloader和spider相关的错误处理流程
  • 不再采用中间件的形式实现请求的去重功能,并移除相关的中间件
  • ProxyAgentMiddleware的 proxy_agent 配置下面 addr 字段更名为 agent_addr

0.6.5 (2017-05-09)

  • HttpRequest添加 errback 字段,表示无法正常获取到HttpResponse时触发的函数
  • ResponseMatchMiddleware的配置修改为列表
  • middleware的顺序修改为依次向downloader/spider靠近,层层包裹
  • 移除任务配置中随机生成的 task_id

0.6.4 (2017-05-05)

  • HttpResponse中的 url 字段源于aiohttp返回的ClientResponse中的 url 字段,实际应为 yarl.URL 对象
  • LocalCluster启动时不再新建一个线程
  • 优化日志工具中设置日志的接口

0.6.2 (2017-03-30)

  • HttpResponse添加 encodingtext 字段,分别用于获取网页的编码及字符串形式的内容
  • 添加ResponseMatchMiddleware,用于初步判断得到的页面是否符合要求
  • 添加CookieJarMiddleware,用于维护请求过程中产生的cookie,同时HttpRequest meta 中添加系统项 cookie_jar 作为发起请求时使用的cookie jar
  • HttpRequest meta 添加 timeout 字段,用于精确控制某个请求的超时时间
  • 系统配置添加 queue_cls 项,用于替换默认的请求队列

0.6.1 (2017-03-23)

  • 中间件添加 openclose 两个钩子函数,分别对应开启和关闭爬虫的事件
  • RetryMiddleware中可以自定义需要重试的HTTP状态码
  • 添加SpeedLimitMiddleware,用于爬虫限速
  • 添加ProxyMiddleware,用于为请求添加指定代理
  • 移除MongoDedupeMiddleware及对pymongo的依赖
  • 修改ProxyAgentMiddleware,RetryMiddleware在配置文件中的参数格式
  • DepthMiddleware更名为MaxDepthMiddleware

0.6.0 (2017-03-16)

  • First release