JustH Ответов: 5

Извлечение HTML-данных на языке C++


Всем Привет,

У меня есть проект для чтения электронной почты (формат HTML) и извлечения из нее определенной информации, такой как номера ссылок, суммы и т. д..
Как только я получу электронное письмо, я сохраню его в буфер символов.
Письмо содержит все HTML-теги и т. д. см. ниже.

Я хотел бы знать, как я могу извлечь HTML-данные, а не HTML-теги.
НАПР.:
в <html-код&ГТ;Привет Мир&ЛТ;/HTML и ГТ;
Я хочу извлечь часть "Привет, Мир".

Я подумал о сравнении каждого символа, и если символ находится в угловых скобках "< " или " >", я отброшу этот символ, таким образом, у меня будут все остальные данные.

Является ли это наиболее эффективным методом, так как мы ожидаем больших объемов электронных писем.

Заранее спасибо.
_____

<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head>
<body lang=EN-US link=blue vlink=purple>
<div class=WordSection1><p class=MsoNormal>
<o:p>&nbsp;</o:p></p>
<div align=center>
<table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0 width=720 style='width:540.0pt'>
<tr style='height:129.75pt'>
<td style='padding:0cm 0cm 0cm 0cm;height:129.75pt'>
<p class=MsoNormal>
<img width=720 height=173 id="_x0000_i1026" src="cid:image001.jpg@01CB8683.F336E550" alt="Standard Bank"><o:p></o:p></p></td>
</tr><tr><td width=718 style='width:538.5pt;background:#2E77BA;padding:0cm .75pt 0cm .75pt'>
<div align=center><table class=MsoNormalTable border=0 cellspacing=0 cellpadding=0 width=705 style='width:528.75pt'><tr>
<td style='background:white;padding:7.5pt 7.5pt 7.5pt 7.5pt'><p><b>
<span style='font-size:13.5pt;font-family:"Arial","sans-serif";color:navy'><br></span></b>
<strong>
<span style='font-size:18.0pt;font-family:"Arial","sans-serif";color:navy'>Business Online deposit received</span>
</strong><o:p></o:p></p><p class=MsoNormal>
<span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'>Dear </span>
<span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:#4F81BD'>&lt;&lt;preferredName&gt;&gt;</span>
<span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'><br>
<br>A deposit has been received for your Standard Bank account number </span>
<span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:#4F81BD'>&lt;&lt;ACC NO&gt;&gt;</span>
<span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'>.<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'>
<o:p>&nbsp;</o:p></span></p><p class=MsoNormal>
<span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'>The details are as follows:<o:p></o:p></span></p>
<p class=MsoNormal><span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'><o:p>&nbsp;</o:p></span></p>
<table class=MsoNormalTable border=0 cellspacing=1 cellpadding=0 width="95%" style='width:95.42%;background:#3D5378'>
<tr><td width="10%" valign=top style='width:10.46%;background:white;padding:1.5pt 1.5pt 1.5pt 1.5pt'>
<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'>Currency<o:p></o:p></span>
</b></p></td><td width="21%" valign=top style='width:21.84%;background:white;padding:1.5pt 1.5pt 1.5pt 1.5pt'>
<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'>Amount<o:p></o:p>
</span></b></p></td><td style='background:white;padding:1.5pt 1.5pt 1.5pt 1.5pt'><p class=MsoNormal><b>
<span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'>Value Date</span></b><o:p></o:p></p>
</td><td width="26%" valign=top style='width:26.52%;background:white;padding:1.5pt 1.5pt 1.5pt 1.5pt'><p class=MsoNormal>
<b><span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'>Reference<o:p></o:p></span></b></p></td>
<td width="24%" style='width:24.56%;background:white;padding:1.5pt 1.5pt 1.5pt 1.5pt'><p class=MsoNormal><b>
<span style='font-size:10.0pt;font-family:"Arial","sans-serif";color:black'>Message ID</span></b><o:p></o:p></p></td>
</tr><tr style='height:12.1pt'>
<td width="10%" valign=top style='width:10.46%;background:white;padding:1.5pt 1.5pt 1.5pt 1.5pt;height:12.1pt'>
<p class=MsoNormal align=right style='text-align:right'><span style='font-family:"Arial","sans-serif"'>R<o:p>
</o:p></span></p></td>
<td width="21%" valign=top style='width:21.84%;background:white;padding:1.5pt 1.5pt 1.5pt 1.5pt;height:12.1pt'>
<p class=MsoNormal><span style='font-family:"Arial","sans-serif"'>2860.00<o:p></o:p></span></p></td>
<td style='background:white;padding:1.5pt 1.5pt 1.5pt 1.5pt;height:12.1pt'><p class=MsoNormal>


[edit]попытался исправить форматирование, но что-то кажется неправильным[/edit]
[edit2] исправлено форматирование [/edit2]

5 Ответов

Рейтинг:
37

Alain Rist

Это действительно так именно то, что вы предлагаете, но посмотрите на проблему пространства с вашими образцовыми данными :(

bool InTag(char c)
{
    static int bracket = 0;
    switch (c)
    {
    case '<':
        ++bracket;
        break;
    case '>':
        --bracket;
        return true;
    }
    return bracket > 0;
}

#include <fstream>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <iostream>
int main()
{
    std::ifstream in("Test.htm");
    std::ostringstream oss;
    std::remove_copy_if(std::istream_iterator<char>(in), std::istream_iterator<char>(), std::ostream_iterator<char>(oss), InTag);
    std::cout << oss.str() << std::endl;
    return 0;
}

овации,
АР


Рейтинг:
29

E.F. Nijboer

Один из самых быстрых и простых-это просто реализовать его очень прямолинейно, если вам нужно то, что вы предлагаете. Правила, которые вы определили, должны останавливаться, когда встречается " <", и начинать, когда встречается " >", Так что это то, что вы должны делать :)

просто просмотрите строку, и когда вы столкнетесь с " <", вы прекратите копирование, а когда вы столкнетесь с " >", пришло время начать копирование снова.

The pseudo code would be something like this:
while not end of string {
   while not curchar == '<' and not end of string {
      copy character
      move to next character
    }
   move to next character /* skip '<' character */
   while not curchar == '>' and not end of string {
     move to next character
   }
   move to next character /* skip '>' character */
}


Удачи вам!


Рейтинг:
1

basementman

Я использую эти функции для синтаксического анализа XML в течение нескольких лет с очень впечатляющей производительностью. Возможно, они помогут и вам:

BOOL XMLGetNodeValue(LPCTSTR cpXML, LPCTSTR cpTagName, LPTSTR cpBuf)
{
  BOOL bRetval = FALSE;
  LPTSTR cpTagStartB = NULL;
  LPTSTR cpTagStartE = NULL;
  LPTSTR cpTagEndB = NULL;
  *cpBuf = 0;
  if (XMLFindNode(cpXML,cpTagName,&cpTagStartB,&cpTagStartE,&cpTagEndB))
    {
      if (cpTagStartE != cpTagEndB && cpTagEndB)
        {
          int iLen = (cpTagEndB-cpTagStartE)-1;
          memcpy(cpBuf,cpTagStartE+1,iLen*sizeof(TCHAR));
          *(cpBuf+iLen) = 0;
        }
      bRetval = TRUE;
    }
  return bRetval;
}

BOOL XMLFindNode(LPCTSTR cpXML, LPCTSTR cpTagName, TCHAR **cpTagStartB, TCHAR **cpTagStartE, TCHAR **cpTagEndB)
{
  BOOL bRetval = FALSE;
  TCHAR caTag[512];
  _stprintf(caTag,_T("<%s"),cpTagName);
  int iLen = _tcslen(caTag);
  LPTSTR cpStart = _tcsstr(cpXML,caTag);
  if (cpStart)
    {
      if (*(cpStart+iLen) == ' ' || *(cpStart+iLen) == '>')
        {
          if (cpTagStartB)
            *cpTagStartB = cpStart;
          LPTSTR cpEnd = _tcschr(cpStart, '>');
          if (cpTagStartE)
            *cpTagStartE = cpEnd;
          if (cpEnd && *(cpEnd-1) == '/' && cpTagEndB)
            *cpTagEndB = cpEnd;  // single tag, inline closing mark
          else
            {
              if (cpEnd && cpTagEndB)
                {
                  _stprintf(caTag,_T("</%s>"),cpTagName);
                  *cpTagEndB = _tcsstr(cpEnd,caTag);
                }
            }
          bRetval = TRUE;
        }
      else
        return XMLFindNode(cpStart+iLen,cpTagName,cpTagStartB,cpTagStartE,cpTagEndB);
    }
  return bRetval;
}

BOOL XMLFindNodeAttribute(LPCTSTR cpXML, LPCTSTR cpTagName, LPCTSTR cpAttribName, LPTSTR cpAttribValue, TCHAR **cpTagStart /*=NULL*/)
{
  BOOL bRetval = FALSE;
  LPTSTR cpTagStartB = NULL;
  LPTSTR cpTagStartE = NULL;
  bRetval = XMLFindNode(cpXML,cpTagName, &cpTagStartB,&cpTagStartE);
  if (bRetval)
    {
      TCHAR caBuf[512];
      _stprintf(caBuf,_T("%s="),cpAttribName);
      LPTSTR p = _tcsstr(cpTagStartB+_tcslen(cpTagName),caBuf);
      if (p && p < cpTagStartE)
        {
          p += _tcslen(caBuf);
          if (*p == '\"')
            p++;
          int iCount = 0;
          LPTSTR cpAttribEnd = p;
          while (*cpAttribEnd != '\"' && cpAttribEnd < cpTagStartE)
            {
              *(cpAttribValue+iCount) = *cpAttribEnd;
              cpAttribEnd++;
              iCount++;
            }
          *(cpAttribValue+iCount) = 0;
        }
      if (cpTagStart)
        *cpTagStart = cpTagStartB;
    }
  return bRetval;
}


Рейтинг:
1

Uwe Keim

Воспользуйся регулярное выражение[^] для поиска и извлечения.

Существуют реализации для C++[^].

Овации
Уве


Рейтинг:
0

JustH

Спасибо за предложения, я реализовал следующее.


&ЛТ;заранее Ланг="КС"и GT;недействительным Банк::экстракт(CString в формате HTML)
{
char *буфер;
int BufferSize = 0;
char *Temp;
int StartPos = 0;
int EndPos = 0;
int TempSize = 0;
Параметр bufferSize = HTML-код.Метода getlength может служить метод();
Buffer = новый символ[BufferSize + 1];
memset(Buffer,0,BufferSize + 1);
memcpy(буфер,HTML.GetBuffer(),BufferSize);
for (int i=0;i&lt;BufferSize;i++)
{
if (Buffer[i] == &#39;&lt;&#39;)
{
я++;
для (тип int к = Я; л &амп;ЛТ; параметр bufferSize; к++)
{
if(Buffer[k] == &#39;&gt;&#39;)
{
i = k;
перерыв;
}
}
}
if ((Buffer[i] == &#39;&gt;&#39;) &amp; (Buffer[i+1] != &#39;&lt;&#39;) &amp; & amp; (Buffer[i+1] != 0x0d))//возврат каретки
{
StartPos = 0;
EndPos = 0;
я++; //буфер[я] == &амп;#39;&амп;ГТ;&амп;#39; так буфер[я++] != &ампер;#39;&амп;ГТ;&амп;#39;
StartPos = i;
для (Int J В = я; к &амп;ЛТ; параметр bufferSize; J++в)
{
if (Buffer[j] == &#39;&lt;&#39;)//найдено начало тега
{
i = j;
EndPos = j;
TempSize = EndPos - StartPos;
Temp = новый символ[TempSize + 1];
memset(Temp,0,TempSize + 1);
memcpy(Temp,&amp;Buffer[StartPos],TempSize);
удалить []Temp;
перерыв;
}
}
}
}
if (буфер)
{
удалить буфер [];
Буфер = NULL;
}
}</pre>