【问题标题】:Using regex to get title使用正则表达式获取标题
【发布时间】:2017-02-01 15:54:26
【问题描述】:

我不确定如何使用正则表达式选择标题。我试过了

match(/<title>(.*) .*<\/title>/)[1]

但这不匹配任何东西。

This 是我要从中选择的响应正文。

尝试选择"title I need to select."

【问题讨论】:

  • 用正则表达式解析 HTML 只会给开发者带来不幸的后果:stackoverflow.com/a/1732454/67392
  • “如果你有一小部分 HTML 页面,你想从其中抓取数据然后填充到数据库中,那么正则表达式可能工作得很好。”这似乎是我想要做的。所以可能没问题?
  • 另外你会推荐做什么?
  • @user3579614 你对 JavaScript 有什么了解吗?它的语法相似,更适合抓取 HTML 页面。
  • 是的,有点。我找到了 nokogiri,这似乎可以正确完成工作?

标签: ruby-on-rails ruby regex match


【解决方案1】:

它不起作用的原因是itemprop=\"name\" 属性。要解决此问题,您也可以匹配它:

# copy-paste from the page you provided
html = '<!doctype html>\n<html lang=\"en\" itemscope itemtype=\"https://schema.org/WebPage\">\n<head>\n<meta charset=\"utf-8\"><meta name=\"referrer\" content=\"always\" />\n<title itemprop=\"name\">title I need to select.</title>\n<meta itemprop=\"description\" name=\"description\" content=\\'

html.match(/<title.*?>(.*)<\/title>/)[1] # => "title I need to select."

.*? 基本上意味着“匹配所需的字符数,但不要更多”


然而,正如其他人指出的那样,正则表达式并不适合 html 解析。相反,您可以为此使用流行的 ruby​​ gem - Nokogiri:

require 'nokogiri'

page = Nokogiri.parse(html)
page.css('title').text # => "title I need to select."

请注意,它甚至可以处理格式错误的 html,就像这里的情况一样。

【讨论】:

    【解决方案2】:

    如果您正在寻找更强大的 XML/HTML 解析器,请尝试使用支持 XPath 的 Nokogiri。

    这篇文章解释了原因 Use xPath or Regex?

    require "nokogiri"
    string = "<title itemprop=\"name\">title I need to select.</title>"
    html_doc = Nokogiri::HTML(string)
    html_doc.xpath("//title").first.text
    

    【讨论】:

    • 最好使用 CSS 而不是 Xpath,CSS 更不容易出错。
    • 我对“容易出错”的示例感兴趣? XPath 的语法主要是为 XML 设计的,但也适用于 XHTML。 CSS 选择器可以通过 CSS 类/id 更改轻松破坏,XPath 可以通过 HTML 破坏的结构轻松破坏。在这方面选择你的立场。除了“语法更简单”之外,还有什么让 CSS 更好?
    • node.xpath("//foo") 不会选择node 的所有foo 后代。关于其他所有 nokogiri 问题都是有人绊倒的。我强烈推荐 CSS 的可预测行为。
    【解决方案3】:

    这里的正则表达式会给你你想要的: &lt;title.*&gt;(.*)&lt;\/title&gt;

    如前所述,有更好的方法来解析 HTML。您可能想查看Nokogiri 之类的内容。

    【讨论】:

    • 如果该页面上有两个 title 标签,这将选择更多。
    【解决方案4】:

    当我必须从 XML 中获取元素时,我喜欢将其转换为哈希

    from_xml(xml, disallowed_types = nil) 公开

    当键是 节点名称,值为它的内容

    #http://apidock.com/rails/Hash/from_xml/class

    现在你可以做类似的事情

    hash = Hash.from_xml('XML')
    hash.title # my favorite book
    

    【讨论】:

    • 不适用于 OP 的 html,您还需要使用 rails 或至少需要 'active_support/all'
    【解决方案5】:

    一种解决方案是使用以下模式:

    <title.*?>(.*?)<\/title>
    

    https://regex101.com/r/piwm5H/1

    【讨论】:

      【解决方案6】:

      在处理 XML 或 HTML 数据时使用 HTML/XML 解析器,极其简单的情况除外。 HTML 和 XML 对于普通的正则表达式来说太复杂了。

      使用 Nokogiri 我会这样做:

      require 'nokogiri'
      
      some_html = '
      <html>
        <head>
          <title>the title</title>
        </head>
      </html>
      '
      
      doc = Nokogiri::HTML(some_html)
      doc.title # => "the title"
      

      Nokogiri 已经有了返回标题的方法,因此您可以利用它。或者,您可以按照正常方式进行操作:

      doc.at('title').text  # => "the title"
      

      正则表达式的问题在于 HTML 可以用多种方式编写:

      <title>foo</title>
      

      或:

      <title>
        foo
      </title>
      

      甚至:

      <title>foo
      </head>
      

      虽然不正确,但会被浏览器接受并由 Nokogiri 修复,然后仍然可以工作。编写一个模式来处理这些变体是一件痛苦且容易出错的事情。随着 HTML 变得越来越复杂,情况只会变得更糟,尤其是当您不控制内容的生成时。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多