2.4.1 Response
Response
对象是 bricks
在运行过程中的请求对象,Response
对象存放于 bricks.lib.response.Response
实例化
参数名 | 参数类型 | 参数描述 | 默认值 |
---|---|---|---|
content | Any | 响应的内容 | None |
status_code | int | 状态码 | 200 |
headers | Union[Header, dict, Mapping] | 响应头 | None |
url | str | 响应的 URL | "" |
encoding | str | 编码 | 无默认值,会自动根据编码猜测 |
reason | str | 原因 | "ok" |
cookies | bricks.lib.cookies.Cookies | 响应 cookie | None |
history | List["Response"] | 重定向历史 | None |
request | bricks.lib.request.Request | 原始请求 | None |
error | 错误信息 | empty | |
callback | Optional[Callable] | 回调函数 | None |
cost | 响应耗时 | 0 |
guess_encoding
根据响应内容猜测当前编码,猜测顺序为:
- 从
header
中获取编码 - 根据
http content
进行猜测 - 根据
html body
进行猜测 - 上述三步全部失败的时候,则设置为
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()"))
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)
参数:
xpath
:xpath
规则obj
:需要匹配的对象,默认为self.text
kwargs
:bricks.lib.extractors.XpathExtractor.extract
的其他关键字参数
xpath_first
对 response.text
进行 xpath
匹配, 并返回 **第一个 **匹配结果. 类似于直接使用 lxml
进行 xpath
匹配, 而不同的是, 不需要自己实例化HTML对象, 方法内部会自动进行实例化并缓存. 更多语法请参考: XPath (opens in a new tab)
参数:
xpath
:xpath
规则obj
:需要匹配的对象,默认为self.text
default
:匹配不到时的默认值kwargs
:bricks.lib.extractors.XpathExtractor.extract
的其他关键字参数
jsonpath
对 response.text
进行 JSONPath
匹配, 并返回匹配结果。类似于直接使用 jsonpath
进行 jsonpath
匹配。 更多语法请参考: JsonPath (opens in a new tab)
参数:
jpath
:jsonpath
规则obj
:需要匹配的对象,默认为self.text
strict
:是否严格匹配,为False
时可以匹配jsonp
字符串kwargs
:bricks.lib.extractors.JsonpathExtractor.extract
的其他关键字参数
jsonpath_first
对 response.text
进行 JSONPath
匹配, 并返回** 第一个 **匹配结果。类似于直接使用 jsonpath
进行 jsonpath
匹配。 更多语法请参考: JsonPath (opens in a new tab)
参数:
jpath
:jsonpath
规则obj
:需要匹配的对象,默认为self.text
strict
:是否严格匹配,为False
时可以匹配jsonp
字符串kwargs
:bricks.lib.extractors.JsonpathExtractor.extract
的其他关键字参数default
:匹配不到时的默认值
re
对 response.text
进行 regex
匹配, 并返回匹配结果。 类似于直接使用 re.findall
进行匹配。 更多语法请参考: 正则表达式 (opens in a new tab)
参数:
regex
:regex
规则obj
:需要匹配的对象,默认为self.text
kwargs
:bricks.lib.extractors.RegexExtractor.extract
的其他关键字参数
re_first
对 response.text
进行 regex
匹配, 并返回 第一个 匹配结果。 类似于直接使用 re.findall
进行匹配。 更多语法请参考: 正则表达式 (opens in a new tab)
参数:
regex
:regex
规则obj
:需要匹配的对象,默认为self.text
kwargs
:bricks.lib.extractors.RegexExtractor.extract
的其他关键字参数default
:匹配不到时的默认值
get
对 response.text
进行 jmespath
匹配, 并返回匹配结果。 类似于直接使用 jmespath
进行 jmespath
匹配。 更多语法请参考: JMESPath — JMESPath (opens in a new tab)
参数:
rule
:jmespath
规则obj
:需要匹配的对象,默认为self.json()
strict
:是否严格匹配,为False
时可以匹配jsonp
字符串kwargs
:lego.libs.extractors.JsonpExtractor.extract
的其他关键字参数
get_first
类似于直接使用 jmespath
进行 jmespath
匹配。 更多语法请参考: JMESPath — JMESPath (opens in a new tab)
参数:
rule
:jmespath
规则obj
:需要匹配的对象,默认为self.json()
strict
:是否严格匹配,为False
时可以匹配jsonp
字符串kwargs
:lego.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"}))
示例二: 嵌套匹配
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 字段
},
},
)
)
示例三: 匹配带过滤(需要引擎支持)
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 字段
},
},
)
)
示例四: 自定义引擎
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))
示例五: 嵌套 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"),
},
},
)
)