【问题标题】:Using regex to find keyword in http response使用正则表达式在 http 响应中查找关键字
【发布时间】:2013-06-06 13:20:44
【问题描述】:

我之前问过一个类似的问题,推荐 Nokogiri 作为解决方案。我用过 Nokogiri,它确实很好用。

但由于某些原因,我必须使用正则表达式从 HTTP 响应正文中提取关键字。

关键字格式如下:

<HTML>
<HEAD> <TITLE>TestExample [Date]</TITLE></HEAD>
</HTML>

这里,Date 是一个动态变量,我需要从 HTTP 响应正文中提取“TestExample [Date]”。此外,&lt;title&gt; 可以是小写或大写。

假设“响应”具有 http 响应,我尝试执行以下操作:

>> response
=> "<HTML>\n<HEAD> <TITLE>TestExample [Date]</TITLE></HEAD>\n</HTML>"

然后做一个正则表达式来搜索:

>> regex
=> /<title>TestExample (.*?)<\/title>/mi

当我执行response[regex] 时,没有结果。 response.match(regex) 和 response.scan(regex) 没有结果。

我如何使用正则表达式来完成这项任务?


更新:

对于这个任务,这个正则表达式可以正常工作:

response.match(/<title>(.*)<\/title>/mi).captures.first

【问题讨论】:

  • 我猜是错字,更新 "/title/mi" 为 "/title>TestExample (.*?) /mi"
  • 我迷路了。为什么不能使用 nokogiri 获取&lt;title&gt; 的内容,然后用正则表达式搜索内容?
  • @tlewin 是的,这是一个错字。感谢您的关注。我盯着屏幕看太久了。 :)
  • 那些“某些人”不应该告诉你如何编写代码,因为他们的方法是错误的。
  • security related!?只需向他们展示此页面:stackoverflow.com/questions/1732348/…

标签: ruby regex html-parsing


【解决方案1】:

正如其他人所说,正则表达式不是要走的路。如果您真的一定要使用正则表达式(不仅仅是懒得重构?),这应该可以解决问题:

response.match(/<title>(.*)<\/title>/mi).captures.first

【讨论】:

  • 感谢您的回答。它确实有效。 :) ...我是noobie,但不是太懒惰。 :) ...正如我之前提到的,我已经将 Nokogiri 用于其他任务,但对于这一任务,我必须只使用正则表达式。能否请您介绍一下 captures.first?
  • 好吧,没有冒犯我只是想找出答案 ;-) 我只是好奇:你为什么不能使用 Nokogiri?
  • captures 为您提供捕获组,即括号中的正则表达式部分 (...) 作为数组。 first 会给你数组的第一个元素。
  • 我见过带有重复和多个 &lt;title&gt; 标记的 HTML,这会导致其表现不佳,尤其是当 &lt;head&gt; 块在正文之后重复时。
  • @theTinMan 我听到了。让我尝试分享有关此正则表达式使用的更多信息。有一个 Web 应用程序在设备上运行。它有一个欢迎页面,用户首先登陆后登录。这个网址的内容非常少,并且具有某些标准关键字。正则表达式是提取和匹配这些关键字。它不是一个经常更新的应用程序,目标页面具有预设的内容和大多数(动态)功能位于单独的页面上。您还发现使用正则表达式有什么问题吗?
【解决方案2】:

处理这个问题的正确方法是使用解析器。 Nokogiri 将处理您提出的所有要求,不会因为大小写差异或日期差异而中断。

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<HTML>
<HEAD> <TITLE>TestExample [Date]</TITLE></HEAD>
</HTML>
EOT
doc.at('title').text
=> "TestExample [Date]"

doc = Nokogiri::HTML(<<EOT)
<HTML>
<HEAD> <TITLE>TestExample [1/1/2000]</TITLE></HEAD>
</HTML>
EOT
doc.at('title').text
=> "TestExample [1/1/2000]"

doc = Nokogiri::HTML(<<EOT)
<HTML>
<HEAD> <TiTlE>TestExample [Jan. 1, 2000]</tItLe></HEAD>
</HTML>
EOT
doc.at('title').text
=> "TestExample [Jan. 1, 2000]"

doc.title
=> "TestExample [Jan. 1, 2000]"

【讨论】:

  • 只是好奇,如果关键字在http响应中anywhere,我能找到吗?
  • 关键字?你是说标签?如果它在解析的 HTML 正文中,是的。更重要的是,如果"&lt;title&gt;" 出现在某个地方的文本中,它就不会被愚弄,不像正则表达式那样很难分辨。
【解决方案3】:

你也可以试试这个模式:

/(?<=<title>)[^<]++/i

[^&lt;] 表示除 [^&lt;]+ 表示该类中的 1 个或多个字符
[^&lt;]++ 表示该类中的 1 个或多个字符,并且是所有格

a possessive quantifier 通知正则表达式引擎它不需要回溯,因此性能更好。

示例:

response.match(/(?<=<title>)[^<]++/i)

我们的想法是不使用点并将其替换为排除 &lt; 的字符类

注意,结果是整个模式,这里不需要使用捕获组,也不需要测试后面的内容。我删除了 m 修饰符 (代表 DOTALL) 因为我不使用点。

我只是向后看,之前有 &lt;title&gt;。

【讨论】:

  • 什么是[^&lt;]++?这不是 Ruby 正则表达式引擎的一部分。
  • >> response.match(/(?)[^)[^
  • @Sunshine: Lookbehind 仅适用于 ruby​​ 1.9
  • @theTinMan:Regexp 引擎支持所有格量​​词。
  • 啊,你是对的。我在文档中搜索了++,但当然,他们没有示例,描述它的文本仅显示一个+:A quantifier followed by + matches possessively: once it has matched it does not backtrack. They behave like greedy quantifiers, but having matched they refuse to “give up” their match even if this jeopardises the overall match.
猜你喜欢
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
  • 2018-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多