bricks
开发指南
2.4 解析篇
2.4.1 Response 对象

2.4.1 Response

Response 对象是 bricks 在运行过程中的请求对象,Response 对象存放于 bricks.lib.response.Response

实例化

参数名参数类型参数描述默认值
contentAny响应的内容None
status_codeint状态码200
headersUnion[Header, dict, Mapping]响应头None
urlstr响应的 URL""
encodingstr编码无默认值,会自动根据编码猜测
reasonstr原因"ok"
cookiesbricks.lib.cookies.Cookies响应 cookieNone
historyList["Response"]重定向历史None
requestbricks.lib.request.Request原始请求None
error错误信息empty
callbackOptional[Callable]回调函数None
cost响应耗时0

guess_encoding

根据响应内容猜测当前编码,猜测顺序为:

  1. header 中获取编码
  2. 根据 http content 进行猜测
  3. 根据 html body 进行猜测
  4. 上述三步全部失败的时候,则设置为 utf-8 编码

text

通过 str 的方式获取 response.content ,是一个计算属性

content

获取 response 的内容,一般情况下是 bytes,有些下载器可能直接设置的 string

html

返回 etree.HTML对象,可以直接调用 xpath 方法

from bricks.lib.response import Response
 
res = Response(content="<html><body><p>hello world</p></body></html>")
print(res.html)
print(res.html.xpath("//p/text()"))
 

picture 0

length

返回 response的响应长度,相当于 len(res.text)

from bricks.lib.response import Response
 
res = Response()
print(res.length)

size

返回 response的响应大小,单位为:bytes

from bricks.lib.response import Response
 
res = Response()
print(res.size)

json

相当于 json.loads(response.text)

from bricks.lib.response import Response
 
res = Response()
print(res.json())

xpath

response.text 进行 xpath 匹配, 并返回匹配结果. 类似于直接使用 lxml进行 xpath匹配, 而不同的是, 不需要自己实例化HTML对象, 方法内部会自动进行实例化并缓存. 更多语法请参考: XPath (opens in a new tab)

参数:

  • xpathxpath规则
  • obj:需要匹配的对象,默认为 self.text
  • kwargsbricks.lib.extractors.XpathExtractor.extract的其他关键字参数

xpath_first

response.text 进行 xpath 匹配, 并返回 **第一个 **匹配结果. 类似于直接使用 lxml进行 xpath匹配, 而不同的是, 不需要自己实例化HTML对象, 方法内部会自动进行实例化并缓存. 更多语法请参考: XPath (opens in a new tab)

参数:

  • xpathxpath规则
  • obj:需要匹配的对象,默认为 self.text
  • default:匹配不到时的默认值
  • kwargsbricks.lib.extractors.XpathExtractor.extract 的其他关键字参数

jsonpath

response.text 进行 JSONPath 匹配, 并返回匹配结果。类似于直接使用 jsonpath进行 jsonpath匹配。 更多语法请参考: JsonPath (opens in a new tab)

参数:

  • jpathjsonpath规则
  • obj:需要匹配的对象,默认为 self.text
  • strict:是否严格匹配,为 False时可以匹配 jsonp字符串
  • kwargsbricks.lib.extractors.JsonpathExtractor.extract的其他关键字参数

jsonpath_first

response.text 进行 JSONPath 匹配, 并返回** 第一个 **匹配结果。类似于直接使用 jsonpath进行 jsonpath匹配。 更多语法请参考: JsonPath (opens in a new tab)

参数:

  • jpathjsonpath规则
  • obj:需要匹配的对象,默认为 self.text
  • strict:是否严格匹配,为 False时可以匹配 jsonp字符串
  • kwargsbricks.lib.extractors.JsonpathExtractor.extract的其他关键字参数
  • default:匹配不到时的默认值

re

response.text 进行 regex 匹配, 并返回匹配结果。 类似于直接使用 re.findall进行匹配。 更多语法请参考: 正则表达式 (opens in a new tab)

参数:

  • regexregex规则
  • obj:需要匹配的对象,默认为 self.text
  • kwargsbricks.lib.extractors.RegexExtractor.extract的其他关键字参数

re_first

response.text 进行 regex 匹配, 并返回 第一个 匹配结果。 类似于直接使用 re.findall进行匹配。 更多语法请参考: 正则表达式 (opens in a new tab)

参数:

  • regexregex规则
  • obj:需要匹配的对象,默认为 self.text
  • kwargsbricks.lib.extractors.RegexExtractor.extract的其他关键字参数
  • default:匹配不到时的默认值

get

response.text 进行 jmespath 匹配, 并返回匹配结果。 类似于直接使用 jmespath 进行 jmespath 匹配。 更多语法请参考: JMESPath — JMESPath (opens in a new tab)

参数:

  • rulejmespath规则
  • obj:需要匹配的对象,默认为 self.json()
  • strict:是否严格匹配,为 False时可以匹配 jsonp字符串
  • kwargslego.libs.extractors.JsonpExtractor.extract的其他关键字参数

get_first

类似于直接使用 jmespath 进行 jmespath 匹配。 更多语法请参考: JMESPath — JMESPath (opens in a new tab)

参数:

  • rulejmespath规则
  • obj:需要匹配的对象,默认为 self.json()
  • strict:是否严格匹配,为 False时可以匹配 jsonp字符串
  • kwargslego.libs.extractors.JsonpExtractor.extract的其他关键字参数
  • default:匹配不到时的默认值

ok

判断响应是否成功,默认是判断状态码是否在 200-300 之间

is_json

判断响应是否是 json 格式

extract

通过一个规则字典去提取数据,并将提取到的数据全部组装到一个 items 里面

参数:

  • rules: 规则字典,如果只有一层, 那么 key 就是字段名, value 就是匹配规则,如果多层,那么 key 就是匹配规则,value 就是一个字典,字典的里面 key 就是字段名,value 就是字段规则, 可以无限层次嵌套; 嵌套要求: 当遇到列表需要遍历每一项的时候进行下一层级编写
  • engine: 提取引擎,也就是上面的 json / jsonpath / xpath / regex, 当然也是支持自定义的, 自定的话需要传入一个可以执行的函数, 要求该函数接收参数为一个字典, 字典内包含了 response, rules, request 三个参数, 函数需要返回一个列表作为匹配结果

示例一: 简单匹配

import json
from bricks.lib.response import Response
 
 
res = Response(
    content=json.dumps(
        {
            "name": "kem",
            "age": 18,
            "hobby": ["唱", "跳", "篮球"],
            "time": "两年半",
            "other1": "其他干扰项1",
            "other2": "其他干扰项2",
        }
    )
)
print(res.extract(engine="json", rules={"name": "name", "hobby": "hobby"}))

picture 1

示例二: 嵌套匹配

import json
from bricks.lib.response import Response
 
 
res = Response(
    content=json.dumps(
        {
            "code": 0,
            "msg": "success",
            "data": [
                {"name": "kem", "age": 18},
                {"name": "felix", "age": 18},
                {"name": "yujie", "age": 8},
                {"name": "yifeng", "age": 28},
            ],
        }
    )
)
print(
    res.extract(
        engine="json",
        rules={
            "code": "code",  # 从第一级获取 code 字段
            # 遍历 data 的每一项 (这是 jmespath 的语法)
            "data[]": {
                "name": "name",  # 获取每一项的 name 字段
                "age": "age",  # 获取每一项的 age 字段
            },
        },
    )
)

picture 2

示例三: 匹配带过滤(需要引擎支持)

import json
from bricks.lib.response import Response
 
 
res = Response(
    content=json.dumps(
        {
            "code": 0,
            "msg": "success",
            "data": [
                {"name": "kem", "age": 18},
                {"name": "felix", "age": 18},
                {"name": "yujie", "age": 8},
                {"name": "yifeng", "age": 28},
            ],
        }
    )
)
print(
    res.extract(
        engine="json",
        rules={
            "code": "code",  # 从第一级获取 code 字段
            # 遍历 data age为 18 的每一项 (这是 jmespath 的语法)
            "data[?age==`18`]": {
                "name": "name",  # 获取每一项的 name 字段
                "age": "age",  # 获取每一项的 age 字段
            },
        },
    )
)

picture 3

示例四: 自定义引擎

import json
from bricks.lib.response import Response
 
 
res = Response(
    content=json.dumps(
        {
            "code": 0,
            "msg": "success",
            "data": [
                {"name": "kem", "age": 18},
                {"name": "felix", "age": 18},
                {"name": "yujie", "age": 8},
                {"name": "yifeng", "age": 28},
            ],
        }
    )
)
 
 
def my_engine(opts: dict):
    resp = opts["response"]
    items = resp.extract(
        engine="json",
        rules={
            "code": "code",  # 从第一级获取 code 字段
            # 遍历 data age为 18 的每一项 (这是 jmespath 的语法)
            "data[?age==`18`]": {
                "name": "name",  # 获取每一项的 name 字段
                "age": "age",  # 获取每一项的 age 字段
            },
        },
    )
    ret = []
    for i in items:
        if i["name"] == "felix":  # felix 不配!
            continue
        ret.append(i)
    return ret
 
 
print(res.extract(engine=my_engine))

picture 4

示例五: 嵌套 Rule

Rule 是一个强大的对象, 为了解决单纯的规则可能没办法实现, 来拓展匹配规则的

参数

  • exprs: 匹配规则, Optional[Union[str, Callable]]; 可以是一个规则字符串, 也可以是一个函数, 让你自己来匹配
  • condition: 条件, Optional[Callable]; 当该条件不满足时, 不会进行匹配, 你需要返回一个 bool
  • default: 默认值, Optional[Any]; 当匹配不到时, 返回该默认值
  • pre_script: 前置脚本, Optional[Callable]; 可以是一个函数, 让你自己来处理数据
  • post_script: 后置脚本, Optional[Callable]; 可以是一个函数, 让你自己来处理数据
  • is_array: 用于指定匹配结果是否为 array, Optional[bool]; 默认情况下根据引擎默认值来判断
  • acquire: 是否为必须字段, Optional[bool]; 默认情况下为 True
  • const: 静态值, Optional[Any]; 忽略规则匹配, 返回该值
  • options: 其他参数, Optional[dict]; 需要和引擎配合的其他参数
  • engine: 提取引擎, Optional[Union[Type["Extractor"], str]]; 默认情况下根据当前配置的引擎来判断, 可以穿插着其他引擎来混合适应, 但是不建议
import json
from bricks.lib.response import Response
from bricks.lib.extractors import Rule
 
 
res = Response(
    content=json.dumps(
        {
            "code": 0,
            "msg": "success",
            "data": [
                {"name": "kem", "age": 18},
                {"name": "felix", "age": 18},
                {"name": "yujie", "age": 8},
                {"name": "yifeng", "age": 28},
            ],
        }
    )
)
print(
    res.extract(
        engine="json",
        rules={
            "code": "code",  # 从第一级获取 code 字段
            # 遍历 data age为 18 的每一项 (这是 jmespath 的语法)
            "data[?age==`18`]": {
                "name": "name",  # 获取每一项的 name 字段
                "age": "age",  # 获取每一项的 age 字段
                "msg": Rule(const="hahaha"),
            },
        },
    )
)

picture 5