Skip to content

解析 HTTP 响应包

L edited this page May 3, 2022 · 1 revision

本文档讨论了如何以最简洁的方式解析 HTTP 响应正文.

获取一个 response

获得响应包, 你可以使用 Rex::Proto::Http::ClientHttpClient mixin 来发出 HTTP 请求. 如果你正在编写一个模块, 你应该使用 mixin.

以下是使用 HttpClient#send_request_cgi 方法的示例:

res = send_request_cgi({'uri'=>'/index.php'})

res 的返回值是 Rex::Proto::Http::Response 对象, 但也有可能由于连接/响应超时而获得 NilClass

获取 response body

使用 Rex::Proto::Http::Response 对象, 你可以通过以下方式获取 HTTP body:

data = res.body

如果你想获取原始 HTTP 响应 (包括 code、headers、body 等) , 那么你可以简单地执行以下操作:

raw_res = res.to_s

但在本文档中, 我们只关注 res.body

选择正确的解析

格式 解析器
HTML Nokogiri
XML Nokogiri
JSON JSON

如果你需要解析的格式不在列表中, 则回退到 res.body.

通过 Nokogiri 解析 HTML

当你有一个带有 HTML 的 Rex::Proto::Http::Response 时, 调用的方法是:

html = res.get_html_document

这将为你返回一个 Nokogiri::HTML::Document, 它允许你使用 Nokogiri API.

Nokogiri 中有两种常用的查找元素的方法: #at#search. 主要区别在于 #at 方法将只返回第一个结果, 而 #search 将返回所有找到的结果 (在一个数组中) .

以下示例作为你的 HTML 响应:

<html>
<head>
	<title>Hello, World!</title>
</head>
<body>
	<div class="greetings">
		<div id="english">Hello</div>
		<div id="spanish">Hola</div>
		<div id="french">Bonjour</div>
	</div>
</body>
<html>

简单使用 #at

如果 #at 方法用于查找 DIV 元素:

html = res.get_html_document
greeting = html.at('div')

那么 greeting 变量应该是一个 Nokogiri::XML::Element 对象, 它为我们提供了这个 HTML 块 (同样, 因为 #at 方法只返回第一个结果) :

<div class="greetings">
<div id="english">Hello</div>
<div id="spanish">Hola</div>
<div id="french">Bonjour</div>
</div>

从特定元素树中获取元素

html = res.get_html_document
greeting = html.at('div//div')

那么 greeting 变量应该给我们这个 HTML 块:

<div id="english">Hello</div>

抓取具有特定属性的元素

假设我不想要英文, 我想要西班牙文. 然后我们可以这样做:

html = res.get_html_document
greeting = html.at('div[@id="spanish"]')

抓取具有特定文本的元素

假设我只知道有一个 DIV 元素文本包含 "Bonjour", 我想获取它, 那么我可以这样做:

html = res.get_html_document
greeting = html.at('//div[contains(text(), "Bonjour")]')

或者假设我不知道 "Bonjour" 这个词在哪个元素中, 那么我可以对此有点模糊:

html = res.get_html_document
greeting = html.at('[text()*="Bonjour"]')

#search 基本使用

#search 方法返回一个元素数组. 假设我们要查找所有 DIV 元素, 那么方法如下:

html = res.get_html_document
divs = html.search('div')

提取 text

当你有一个元素时, 你总是可以调用 #text 方法来抓取文本. 例如:

html = res.get_html_document
greeting = html.at('[text()*="Bonjour"]')
print_status(greeting.text)

#text 方法也可以用作去除所有 HTML 标记的技巧

html = res.get_html_document
print_line(html.text)

以上将打印:

"\n\nHello, World!\n\n\n\nHello\nHola\nBonjour\n\n\n"

如果你确实想保留 HTML 标记, 则不要调用 #text, 而是调用 #inner_html.

访问属性值

获取元素, 只需调用 #attributes.

遍历 DOM 树

使用 #next 方法移动到下一个元素.

使用 #previous 方法回滚到前一个元素.

使用 #parent 方法查找父元素.

使用 #children 方法获取所有子元素.

使用 #traverse 方法进行复杂的解析.

解析 XML

To get the XML body from Rex::Proto::Http::Response, do:

xml = res.get_xml_document

这与解析 HTML 非常相似.

解析 JSON

在 Rex::Proto::Http::Response 获取 JSON 解析, 请执行以下操作:

json = res.get_json_document

参考

Clone this wiki locally