C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Поиск текста в файле, Найти ссылки в html документе
Dimas216
  Отправлено: 21.06.2006, 01:13


Ученик-кочегар

Группа: Участник
Сообщений: 11



Появилась проблема с реализацией программы, которая находит ссылки в html документе и копирует их в отдельный текстовый документ.
BreakPointMAN
Отправлено: 21.06.2006, 02:12


Станционный диспетчер

Группа: Участник
Сообщений: 86



В чем конкретно проблема?
Aptem
Отправлено: 21.06.2006, 05:36


Мастер участка

Группа: Участник
Сообщений: 349



Попробуйте функции Pos и SubStr класса AnsiString.
Valdemar
Отправлено: 21.06.2006, 07:41


Мастер участка

Группа: Участник
Сообщений: 433



А еще можно воспользоваться регулярными выражениями.
Dimas216
  Отправлено: 21.06.2006, 12:59


Ученик-кочегар

Группа: Участник
Сообщений: 11



Всем привет!Проблема в том что я никак нимогу догадаться как это реализовать.Т.е. чтобы она находила в тексте ссылку.
Guest
Отправлено: 21.06.2006, 13:38


Не зарегистрирован







Поручить анализ броузеру и пробежаться по коллекции Anchors'ов. Было на форуме.
Dimas216
Отправлено: 21.06.2006, 13:51


Ученик-кочегар

Группа: Участник
Сообщений: 11



Что то я непонял.У меня программа открывает html файл в html коде и внем должна находить ссылки и сохранять их в текстовом файле.Вот.
__Cheat3r
Отправлено: 21.06.2006, 15:11


Станционный диспетчер

Группа: Участник
Сообщений: 110



CODE

//--------------------
String SubStringEx(String mStr, int Start,int End)
{
return mStr.SubString(Start,End-Start+1);
}
//--------------------
//--------------------
TStringList *lst = new TStringList,*links = new TStringList;
lst->LoadFromFile("html.html");

String txt=lst->Text;

while(int pos=txt.Pos("http://"))
{
txt = SubStringEx(txt, pos, txt.Length());
links->Add(SubStringEx(txt,1,txt.Pos("\""));
}
//в links — ссылки.

//--------------------

код на работоспособность не проверял.

Отредактировано __Cheat3r — 22/06/2006, 01:15
Dimas216
Отправлено: 21.06.2006, 15:23


Ученик-кочегар

Группа: Участник
Сообщений: 11



Не работает.Куча ошибок.
__Cheat3r
Отправлено: 21.06.2006, 15:35


Станционный диспетчер

Группа: Участник
Сообщений: 110



Где ошибки!?
Dimas216
Отправлено: 21.06.2006, 15:39


Ученик-кочегар

Группа: Участник
Сообщений: 11



Undefined symbol 'mStr'
'_fastcall TForm1::FindBtnClick(TObject *)' cannot return a value
'lst' is assigned a value that is never used
Dimas216
Отправлено: 21.06.2006, 15:44


Ученик-кочегар

Группа: Участник
Сообщений: 11



CODE
[AnsiString text = RichEdit1->Lines->Text;
AnsiString subString = text.SubString( LastFind+1, text.Length() );]
Вот у меня тут написано начало а как дальше немогу понять.

__Cheat3r
Отправлено: 21.06.2006, 15:48


Станционный диспетчер

Группа: Участник
Сообщений: 110



Ты вообще знаком с программированием?

Это вставь гденить в начале юнита
//--------------------
String SubStringEx(String mStr, int Start,int End)
{
return mStr.SubString(Start,End-Start+1);
}
//--------------------

а это повесь на какуюнибудь кнопку.
TStringList *lst = new TStringList,*links = new TStringList;
lst->LoadFromFile("html.html");

String txt=lst->Text;
delete lst;
while(int pos=txt.Pos("http://"))
{
txt = SubStringEx(txt, pos, txt.Length());
links->Add(SubStringEx(txt,1,txt.Pos("\""));
}

links->SaveToFile("Links.htm");
//в links — ссылки.
Dimas216
Отправлено: 21.06.2006, 16:07


Ученик-кочегар

Группа: Участник
Сообщений: 11



программа не находит в файле ссылки.В html коде начало ссылки начинается с href= а заканчивается .
Guest
Отправлено: 21.06.2006, 16:17


Не зарегистрирован







Бросьте заниматся самодельным анализом текста. WebBrowser зделает это за вас значительно лучше. А вам останется только собирать плоды.

Парсинг HTML в древовидную структуру
Извлечение из Интернет-страницы..., ...всех ссылок на другие сайты.
Dimas216
Отправлено: 21.06.2006, 17:48


Ученик-кочегар

Группа: Участник
Сообщений: 11



Нет, такое мне не нужно.Мне нужно чтобы это было с помощью вытаскивания из html кода.
Valdemar
Отправлено: 22.06.2006, 07:26


Мастер участка

Группа: Участник
Сообщений: 433



Ну если вам ничего не подошло, то еще раз советую воспользоваться регулярными выражениями. Здесь http://regexpstudio.com есть библиотека для работы с регулярными выражениями с описанием на русском языке.
AVC
Отправлено: 22.06.2006, 09:03


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (Dimas216 @ 21/06/2006, 16:48)
Нет, такое мне не нужно.Мне нужно чтобы это было с помощью вытаскивания из html кода.

Ну тогда, для начала, определите что такое ссылка. После этого станет понятно что искать.
Можно попробовать так:
ссылка это текст принадлежажий link'у не стоящему внутри закомментированного участка и расположенному после символов href (в любом сочетании регистров) за которыми может следовать любое число (в том числе и 0) и в любой комбинации символов пробел, табуляция и новая строка, затем знак равенства, затем снова sp,tab \n,
затем символ начала строкового литерала (которого может и не быть)
затем, наконец, сама ссылка либо до парного с началом открывающего символа либо при отсутствии оного до первого пробела. И все это при условии, что мы не выходим за пределы одного тэга.
После этого придется отсеивать ссылки переходов внутри документа (ну это, кажется, легко) и разбирать ссылки, представляющие собой код на js или bas (как это сделать мне пока не ясно).

Ну вот, в первом приближении, то что предстоит сделать.

Отредактировано AVC — 22/06/2006, 08:05
** Sl@Sh
Отправлено: 23.06.2006, 06:23


Не зарегистрирован







Хотелось бы добавить, что в html допускается отступы между href, = и адресом. А еще нет гарантии что после href будет именно " или '. В html можно сразу адрес.

Так что вам наверное придется искать сперва href, потом =, а дальше запоминать для анализа строку от первого символа после = и до символа>.
В этой строке сперва поищите другие параметры тега (target например). Причем очевидно, что все эти варианты будут после href, значит действуйте так : нашли например target и удаляйте часть строки от начала target и до конца строки.
Конечно если у вас есть гарантия, что ссылка не содержит пробелов (а пробелы могут быть,смотря где вы html-файл применяете), то достаточно вырезать только текст от символа после = и до первого пробела.

P.S.: Я тут что-то намудрил. Извините если что неясно, сонный я biggrin.gif
AVC
Отправлено: 23.06.2006, 08:42


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (** Sl@Sh @ 23/06/2006, 05:23)
Хотелось бы добавить, что в html допускается отступы между href, = и адресом. А еще нет гарантии что после href будет именно " или '. В html можно сразу адрес.

Так что вам наверное придется искать сперва href, потом =, а дальше запоминать для анализа строку от первого символа после = и до символа>.
В этой строке сперва поищите другие параметры тега (target например). Причем очевидно, что все эти варианты будут после href, значит действуйте так : нашли например target и удаляйте часть строки от начала target и до конца строки.
Конечно если у вас есть гарантия, что ссылка не содержит пробелов (а пробелы могут быть,смотря где вы html-файл применяете), то достаточно вырезать только текст от символа после = и до первого пробела.

P.S.: Я тут что-то намудрил. Извините если что неясно, сонный я  biggrin.gif

Действительно сонный smile.gif , прочтите внимательно мой пост.
Кроме того полагаться на порядок параметров в тэге ни в коем случае нельзя.
Кстати, кроме
a
base
area
link
form.action
где еще могут стоять явные ссылки ?
Aptem
Отправлено: 23.06.2006, 10:07


Мастер участка

Группа: Участник
Сообщений: 349



Я вообще не понимаю чо вы тут паритесь. Ну вот есть у вас html-код в строке. С помощью функции Pos находим первое вхождение . Вот вам и все, теперь уже в этой строке находим href и выдергиваем ссылку. Пробелы на концах строки можно обработать Trim'ом.

Тут конечно упоминалось обо всяких регулярных выражениях и т.д., это конечно же быстрее и удобнее, но я люблю сам во всем разобраться и понять как это работает. По-моему все тут прозрачно.

Писать кому то за вас совсем не интересно, попробуйте разобраться сами!

Про функции Pos и SubStr можно почитать в обычной помощи C++ Builder.

Удачи!

Отредактировано Aptem — 23/06/2006, 10:09
AVC
Отправлено: 23.06.2006, 13:43


Ветеран

Группа: Модератор
Сообщений: 1583



Вот набросал примерчик, правда для его функционирования требуется мой PageProduser (прилагается, офомлен как визуальный компонент, но можно использовать и просто как lib)
Собственно сам пример
CODE

//---------------------------------------------------------------------------

void __fastcall TF_SeekLinks::Bt_SeekClick(TObject *Sender)
{
Memo1->Lines->LoadFromFile("F:\Temp\b.htm");
AnsiString text = Memo1->Text;

// Оказалось, что мой Producer плохо анализирует текст с разрывами между именем, = и значением
// в теге они должны стоять без разрывов (типа href=значение)
// ну и попутно выкину комментарии, так как Producer писался не для этого
char *buf = new char[text.Length()+1];
char *bp  = buf;
bool  incmnt = false;
int   i = 0;
for (char *cp=text.c_str(); *cp; cp++, i++)
{ if (*cp < ' ') continue;
if (i > 3)
 { if  (*(cp-0) == '-' && *(cp-1) == '-' && (*cp-2) == '<') { incmnt = true;  bp-=2; } // <--
 else if (*(cp-0) == '>' && *(cp-1) == '-' && (*cp-2) == '-') { incmnt = false; bp-=2; } // -->
  }
if (incmnt) break;
*bp++ = *cp;
}
*bp = 0x00;
AnsiString htmltext(buf);
delete [] buf;

Memo1->Text = htmltext;

TAxPageProducer *pgprod = new TAxPageProducer(this);
try {
Aborted = false;
pgprod->AxTagBeg    = "<";
pgprod->AxTagEnd    = ">";
pgprod->OnAxTag     = PgProd_Tag;
Memo1->Lines->Add(AnsiString::StringOfChar('=', 40));
pgprod->Execute(htmltext);
Memo1->Lines->Add(AnsiString::StringOfChar('=', 40));
}
__finally { delete pgprod; pgprod = NULL; }

}

//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

void __fastcall TF_SeekLinks::PgProd_Tag (TObject *Sender
          ,const AnsiString &TagName
          ,TStrings   *TagParams
          ,AnsiString   &RetText
          ,int    &RetState
          )
{
if (Aborted)
{ RetText  = "";
RetState = trsABORT;
return;
}

AnsiString text = "";
AnsiString tagname = TagName.UpperCase();

RetState = trsNONE;
try { // проанализировать только нужные тэги

if  (tagname == "ABORT" ) { RetState = trsABORT; Aborted = true; }
else if (tagname == "A"  ) Memo1->Lines->Add(tagname + ": [" + GetLink(TagParams) + "]");
else if (tagname == "LINK" ) Memo1->Lines->Add(tagname + ": [" + GetLink(TagParams) + "]");
else if (tagname == "AREA" ) Memo1->Lines->Add(tagname + ": [" + GetLink(TagParams) + "]");
else if (tagname == "BASE" ) Memo1->Lines->Add(tagname + ": [" + GetLink(TagParams) + "]");
else if (tagname == "FORM" ) Memo1->Lines->Add(tagname + ": [" + GetLink(TagParams, "action") + "]");
else if (tagname == "FRAME" ) Memo1->Lines->Add(tagname + ": [" + GetLink(TagParams, "src" ) + "]");

} // try
catch (Exception &xcp)
{ text = "Exception: " + xcp.Message;
RetState = trsNONE;
}

RetText = text;
}

//---------------------------------------------------------------------------
// Найти href в параметрах тэга
//---------------------------------------------------------------------------

AnsiString __fastcall TF_SeekLinks::GetLink (TStrings *params
          ,const AnsiString& pPName
          )
{
AnsiString pname = pPName.UpperCase();
AnsiString name;
AnsiString value = "";
int   idx;
char  c1, c2;

for (int i=0; i < params->Count; i++)
{ name  = params->Names[i].UpperCase();
if (name != pname) continue;
value = params->Strings[i];
idx = value.Pos("=");
if (idx > 0) value = value.SubString(idx+1,100);
else   value = "";
}
return value;
}
//---------------------------------------------------------------------------


Пример работы
CODE

Вход
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=windows-1251'>
<link rel='stylesheet' href='file:///E:/Aster/php/afish/style1.css' type='text/css'>
</head>
<body>
<form name='frm_afish' method='post' action='http://localhost/afish/afish.php?cmd=main1'>
<map name="aaa">
<--<area alt="asdfg" shape="poly" coords="1,45,120,118,158,161,1,165" href="qwer">
--><area alt="123" shape="circle" coords="119,57,51" href="zxcv">
</map>
<img src="E:\HHC\Images\Troll3.gif" width="211" height="166" border="0" usemap="#aaa">
<select name='afish_city'
onChange='javascript: afish_mall.value = 1; submit(); return false;'
>
<option value='12' >Актау</option>
<option value='278' >Актюбинск</option>
</select>
<a href='#' onClick='javascript: afish_mall.value = 1; submit(); return false;'>Все</a>
<input type=hidden name='afish_mall' id='afish_mall' value='0'>
</form>
<hr>
<a class='odtmnu' href='?cmd=main1'>Афиша, 1-й вариант</a>
<a class='odtmnu' href=?cmd=debugshow name=iii>Массивы</a>
<a class='odtmnu'
href

=

'?cmd=anysql'
>SQL</a>
</body></html>

Выход
LINK: [file:///E:/Aster/php/afish/style1.css]
FORM: [http://localhost/afish/afish.php?cmd=main1]
AREA: [zxcv]
A: [#]
A: [?cmd=main1]
A: [?cmd=debugshow]
A: [?cmd=anysql]


User Attached Image Скачать файл
axpgprod.rar


Dimas216
Отправлено: 23.06.2006, 15:26


Ученик-кочегар

Группа: Участник
Сообщений: 11



А как подключить AxPgProd к программе?
Guest
Отправлено: 23.06.2006, 17:19


Не зарегистрирован







добавить строку #include "AxPgProd.h"

Установить как пакет: Component->Install Pakages
или
подключить как lib: #pragma link AxPgProd.lib

PS. Это для 5-й стройки. Если вас не 5-я в понедельник вышлю исходники (куда ?).
Dimas216
Отправлено: 23.06.2006, 18:09


Ученик-кочегар

Группа: Участник
Сообщений: 11



Dimas216@mail.ru
** Sl@Sh
Отправлено: 25.06.2006, 06:45


Не зарегистрирован







QUOTE (AVC @ 23/06/2006, 08:42)
Кроме того полагаться на порядок параметров в тэге ни в коем случае нельзя.

Я и не полагаюсь. Ведь я предложил только находить например href, а после него (содержимого) ожидать либо еще тег, либо>
Dimas216
  Отправлено: 26.06.2006, 19:56


Ученик-кочегар

Группа: Участник
Сообщений: 11



Есть кто — нибудь кто может выслать исходники этой программы?
AVC
Отправлено: 27.06.2006, 11:46


Ветеран

Группа: Модератор
Сообщений: 1583



Высылаю.

Вернуться в Вопросы программирования в C++Builder