如何使用Nokogiri到达此节点?

时间:2012-01-24 14:47:22

标签: ruby nokogiri

这是我的html的开头:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="Generator" content="Microsoft Word 12 (filtered medium)">
<!--[if !mso]><style>v\\:* {behavior:url(#default#VML);}\no\\:*  {behavior:url(#default#VML);}\nw\\:* {behavior:url(#default#VML);}\n.shape {behavior:url(#default#VML);}\n</style><![endif]--><style><!--\n/* Font Definitions */\n@font-face\n\t{font-family:"Cambria Math";\n\tpanose-1:2 4 5 3 5 4 6 3 2 4;}\n@font-face\n\t{font-family:Calibri;\n\tpanose-1:2 15 5 2 2 2 4 3 2 4;}\n@font-face\n\t{font-family:Tahoma;\n\tpanose-1:2 11 6 4 3 5 4 4 2 4;}\n/* Style Definitions */\np.MsoNormal, li.MsoNormal, div.MsoNormal\n\t{margin:0in;\n\tmargin-bottom:.0001pt;\n\tfont-size:12.0pt;\n\tfont-family:"Times New Roman","serif";}\na:link, span.MsoHyperlink\n\t{mso-style-priority:99;\n\tcolor:blue;\n\ttext-decoration:underline;}\na:visited, span.MsoHyperlinkFollowed\n\t{mso-style-priority:99;\n\tcolor:purple;\n\ttext-decoration:underline;}\np\n\t{mso-style-priority:99;\n\tmso-margin-top-alt:auto;\n\tmargin-right:0in;\n\tmso-margin-bottom-alt:auto;\n\tmargin-left:0in;\n\tfont-size:12.0pt;\n\tfont-family:"Times New Roman","serif";}\nspan.EmailStyle18\n\t{mso-style-type:personal-reply;\n\tfont-family:"Calibri","sans-serif";\n\tcolor:#1F497D;}\n.MsoChpDefault\n\t{mso-style-type:export-only;\n\tfont-size:10.0pt;}\n@page WordSection1\n\t{size:8.5in 11.0in;\n\tmargin:1.0in 1.0in 1.0in 1.0in;}\ndiv.WordSection1\n\t{page:WordSection1;}\n--> </style>
<!--[if gte mso 9]><xml>\n<o:shapedefaults v:ext="edit" spidmax="1026" />\n</xml><![endif]--> <!--[if gte mso 9]>    <xml>\n<o:shapelayoutv:ext="edit">\n<o:idmapv:ext="edit"data="1"/>\n</o:shapelayout></xml><![endif]-->

</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><p>&nbsp;</p></span></p>
<p class="MsoNormal"><a name="_MailEndCompose"><span style='font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D'><p>&nbsp;</p></span></a></p>
<div><div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in"><p class="MsoNormal"><b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>From:</span></b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'> EMAIL SENDER NAME [mailto:EMAILADDRESS@FAKE.COM] <br><b>Sent:</b>!! DATE I NEED TO GRAB HERE !! <br><b>To:</b> EMAIL ADDRESS HERE <br><b>Subject:</b> SUBJECT LINE HERE <p></p></span></p></div></div>

我需要抓住发送电子邮件的日期。这是我尝试过的:

label_tag_name = 'div div p span br b'
if label_tag = @doc.at_css(%Q{#{label_tag_name}:contains("#{label}:")})
  @attributes[field] = label_tag.text.gsub("#{label}:",'').gsub("\\n", "").strip
end

我还尝试了label_tag_name中的一些较短路径,基本上在开头添加了另一个HTML标记。

每次发送日期都会回来nil

2 个答案:

答案 0 :(得分:2)

您感兴趣的源代码是(为清晰起见,我删除了属性):

<div>
  <div>
    <p>
      <b>
        <span>From:</span>
      </b>
      <span> EMAIL SENDER NAME [mailto:EMAILADDRESS@FAKE.COM] <br>
        <b>Sent:</b>!! DATE I NEED TO GRAB HERE !! <br>
        <b>To:</b> EMAIL ADDRESS HERE <br>
        <b>Subject:</b> SUBJECT LINE HERE <p></p>
      </span></p></div></div>

请注意,HTML中的br标记是自动关闭的,因此查找它们的子元素毫无意义。

可以使用css div div p span来描述目标,但请注意,有两个节点与之匹配,at_css会返回第一个。您可以使用div div p>span仅指定span上的直接子项p。实际目标是此元素内的文本节点(现在文档中只有一个匹配的范围)。特别是,它是第一个b标记之后的下一个元素。因此,如果我们将css选择器扩展为div div p>span b,我们可以使用Nokogiri next方法来获取目标字符串:

date_string = @doc.at_css('div div p>span b').next

如果您想要其他字段,可以使用css代替at_css

date_string = @doc.css('div div p>span b')[0].next
to_string = @doc.css('div div p>span b')[1].next
subject_string = @doc.css('div div p>span b')[2].next

我将留下收件人的姓名以供你做!

答案 1 :(得分:1)

我从这开始:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>
<head>
    <title></title>
</head>

<body>
    <div class="WordSection1">

        <div>
            <div>
                <b>Sent:</b>!! DATE I NEED TO GRAB HERE !!<br>
                <b>To:</b> EMAIL ADDRESS HERE<br>
                <b>Subject:</b> SUBJECT LINE HERE</span></p>
            </div>
        </div>
    </div>
</body>
</html>
EOT

text = doc.at('div.WordSection1').text
sent_date = text[/Sent:(.+)To:/, 1].strip
puts sent_date

哪个输出:

!! DATE I NEED TO GRAB HERE !!

示例HTML非常混乱,因此您无法在该林中轻松查看所需的特定树。删除对导航不重要的所有内容,然后构建搜索。

而且,虽然解析器是一个很棒的工具,但有时候使用它来获取所需的文本会更容易,然后通过字符串搜索来抓取特定的东西。