Как мне добраться до этого узла с помощью Nokogiri? - PullRequest
1 голос
/ 24 января 2012

Вот начало моего 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.

Ответы [ 3 ]

2 голосов
/ 24 января 2012

Интересует ваш источник (я удалил атрибуты для ясности):

<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>

Обратите внимание, что теги br в HTML являются самозакрывающимися, поэтому искать их бессмысленноих дочерние элементы.

Цель может быть описана с помощью css div div p span, но обратите внимание, что есть два узла, которые соответствуют этому, и at_css возвращает first .Вы можете использовать div div p>span для указания только span s, которые являются непосредственными дочерними элементами в 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 голос
/ 24 января 2012

Я бы начал с этого:

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 - беспорядок, поэтому вы не можете легко увидеть конкретные деревья, которые вы хотите в этом лесу. Уберите все, что не нужно для навигации, а затем постройте поиск.

И, хотя синтаксический анализатор - отличный инструмент, иногда его проще использовать для перехода к нужному тексту, а затем захватить конкретную вещь с помощью поиска строки.

1 голос
/ 24 января 2012

В этом документе не так много места для навигации.Используйте селектор, который надежно приведет вас к ближайшей точке, а затем возьмите текст с помощью регулярного выражения:

> doc.css("div.WordSection1 p.MsoNormal span").text[/Sent:\n(.*)/, 1]
=> "          !! DATE I NEED TO GRAB HERE !! To:"
...