Форум » [x]Harbour » Работа с HTML(Сайты в Интернет) » Ответить

Работа с HTML(Сайты в Интернет)

Softlog86: Друзья , подскажите в каком направлении рыть ... Есть сайт в интернете . Там поле для ввода строки поиска . .... Вводим строку . Сайт выдаёт (если найдёт у себя в базе) какую-то информацию в виде HTML-странички .... Задача такая : Программа на Harbour должна делать запрос на сайт и полученную информацию отображать в своём окне . При этом нужно кой-чего из этой информации убрать или заменить некоторые слова ( сайт буржуйский ) . Хочу прилепить как-бы On-Line поиск .... но чтоб данные брать с чужого сайта .... Какие будут мысли ? Или не связываться с такой задачей ?

Ответов - 47, стр: 1 2 3 All

Andrey: Смотри тему http://clipper.borda.ru/?1-3-0-00000218-000-0-0-1342804573 AlexMyr пишет: Посмотри на harbour\examples\guestbk , может на что и натолкнет, сам не пробовал.

AlexMyr: Для Harbour вот (как раз поисковик задействован) harbour\contrib\hbtip\tests\loadhtml.prg

Andrey: AlexMyr пишет: harbour\contrib\hbtip\tests\loadhtml.prg Как хоть собрать этот пример ? Опять забыл как это делать....


PSP: Может так: hbmk2 loadhtml.prg ?

Andrey: PSP пишет: Может так: hbmk2 loadhtml.prg ? А что за файлы в папке лежат ? hbtip.hbc hbtipssl.hbc hbmk.hbm Я через них пытался собрать...

Andrey: PSP пишет: Может так: hbmk2 loadhtml.prg ? Выдает ошибку при выполнении:

AlexMyr: Проверил у себя, работает. Version: Harbour 3.2.0dev (Rev. 18385) Compiler: MinGW GNU C 4.7 (32-bit) Platform: Windows XP 5.1.2600 Service Pack 3 [pre2]C:\dev\_svn\harbour\contrib\hbtip\tests\>loadhtml.exe 56024 bytes received Search http://www.google.de/webhp?hl=en&tab=ww Translate http://translate.google.de/?hl=en&q=Harbour&um=1&ie=UTF-8&sa=N&tab=wT Books http://www.google.de/search?hl=en&q=Harbour&um=1&ie=UTF-8&tbo=u&tbm=bks&so urce=og&sa=N&tab=wp Shopping http://www.google.de/products?hl=en&q=Harbour&um=1&ie=UTF-8&sa=N&tab=wf Blogger http://www.blogger.com/?tab=wj Reader http://www.google.de/reader/view/?hl=en&tab=wy Photos http://picasaweb.google.de/lh/view?hl=en&q=Harbour&um=1&ie=UTF-8&sa=N&tab =wq Videos http://www.google.de/search?hl=en&q=Harbour&um=1&ie=UTF-8&tbo=u&tbm=vid&s ource=og&sa=N&tab=wv Even more » http://www.google.de/intl/en/options/[/pre2]

AlexMyr: да, вот результат, к-й в файле Google.html

Softlog86: Спасибо за подсказку ! Теперь осталось дело за малым - разобраться как сформировать строку запроса к "их" базе .... Полученный HTML-код разобрать тоже сложно ....но можно :)

Pasha: Можно ли подобными запросами выбирать курсы валют ЦБ/НБУ, учетные ставки, индекс инфляции и тому подобную информацию ? Если можно, то с каких сайтов ?

AlexMyr: Pasha пишет: Можно ли подобными запросами выбирать курсы валют ЦБ/НБУ, учетные ставки, индекс инфляции и тому подобную информацию ? Если можно, то с каких сайтов ? Я думаю можно. Вот код выдергивает страницу с курсами с нбу, потом только разобрать таблицу с курсами и вывести в удобной форме: [pre2]/* * $Id: loadhtml.prg 18289 2012-10-11 16:16:32Z vszakats $ */ /* * Sends a query to Google and displays the Links from the response HTML page */ #require "hbtip" PROCEDURE Main LOCAL oHttp, cHtml, aLink, oNode, oDoc oHttp := TIpClientHttp():new( "http://www.bank.gov.ua/control/uk/curmetal/detail/currency?period=daily" ) /* Connect to the HTTP server */ IF ! oHttp:open() ? "Connection error:", oHttp:lastErrorMessage() QUIT ENDIF /* download the Google response */ cHtml := oHttp:readAll() oHttp:close() ? Len( cHtml ), "bytes received " oDoc := THtmlDocument():new( cHtml ) oDoc:writeFile( "Google.html" ) /* ":a" retrieves the first <a href="url"> text </a> tag */ oNode := oDoc:body:a ? oNode:getText( "" ), oNode:href /* ":divs(5)" returns the 5th <div> tag */ oNode := oDoc:body:divs( 5 ) /* "aS" is the plural of "a" and returns all <a href="url"> tags */ aLink := oNode:aS FOR EACH oNode IN aLink ? HtmlToOem( oNode:getText( "" ) ), oNode:href NEXT RETURN [/pre2]

Pasha: Спасибо. Заодно я обратил внимание на незнакомую мне директиву hbmk2 #require.

petr707: Для получения курсов валют есть веб-сервисы (например http://www.cbr.ru/scripts/Root.asp?Prtid=DWS) и поддержка SOAP , пример в \contrib\hbwin\testole.prg Придется, правда, на комп дополнительно установить пакет SOAP ToolKit 3.0 от MS

AlexMyr: Pasha пишет: Заодно я обратил внимание на незнакомую мне директиву hbmk2 #require. Директива позволяет запускать prg как скрипт, но для этого как я понял нужно собрать hbrun c -shared.

santy: AlexMyr пишет: /* * $Id: loadhtml.prg 18289 2012-10-11 16:16:32Z vszakats $ */ /* * Sends a query to Google and displays the Links from the response HTML page */ #require "hbtip" PROCEDURE Main LOCAL oHttp, cHtml, aLink, oNode, oDoc oHttp := TIpClientHttp():new( "http://www.bank.gov.ua/control/uk/curmetal/detail/currency?period=daily" ) /* Connect to the HTTP server */ IF ! oHttp:open() ? "Connection error:", oHttp:lastErrorMessage() QUIT ENDIF /* download the Google response */ cHtml := oHttp:readAll() oHttp:close() ? Len( cHtml ), "bytes received " oDoc := THtmlDocument():new( cHtml ) oDoc:writeFile( "Google.html" ) /* ":a" retrieves the first <a href="url"> text </a> tag */ oNode := oDoc:body:a ? oNode:getText( "" ), oNode:href /* ":divs(5)" returns the 5th <div> tag */ oNode := oDoc:body:divs( 5 ) /* "aS" is the plural of "a" and returns all <a href="url"> tags */ aLink := oNode:aS FOR EACH oNode IN aLink ? HtmlToOem( oNode:getText( "" ) ), oNode:href NEXT RETURN Этот код работает только тогда когда нет ошибки 302 (перенаправление). Если ошибка 302 можно скачать другим способом: [pre2] Пример: IF oHttp:open(cUrl) cHtml := oHttp:readAll() if oHttp:nReplyCode == 302 _resGetFile := GETINETFILE(cFileURL,сFileName) else ...... endif endif ...... #PRAGMA BEGINDUMP #include <windows.h> #include <wininet.h> #include "hrbdll.h" #include "hbapi.h" #include "hbapiitm.h" #include "hbapierr.h" HB_FUNC( GETINETFILE ) { HINTERNET hSession; HINTERNET hURL; HANDLE hFile; char * sAppName= "GetPublicIpAddress"; char * FileURL; char * _FileName ; char Buffer[1024]; DWORD dwRead =0; DWORD dwWrite = 0; BOOL bFound = FALSE; FileURL = hb_parc(1); _FileName = (char *) hb_parc(2); hSession = InternetOpen(sAppName, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); if (hSession) { hURL = InternetOpenUrl(hSession, FileURL, NULL, 0, 0, 0); if (hURL) { hFile = CreateFile(_FileName, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); while (InternetReadFile(hURL, Buffer, 1024, &dwRead) == TRUE) { if ( dwRead == 0) break; WriteFile(hFile, Buffer, dwRead, &dwWrite, NULL); bFound = TRUE; } CloseHandle(hFile); InternetCloseHandle(hURL); } InternetCloseHandle(hSession); } hb_retl(bFound); } #PRAGMA ENDDUMP [/pre2]

a_sidorov: Класс TIPClientHTTP() в Наrbour 3.2 и xHarbour 1.2.1 содержит одну недоработку – указана длина буфера при чтении строки 500, а это неправильно, поскольку размер заголовка (hHeaders) часто превышает эту величину. Отсюда и все проблемы. Кроме того класс TIPClientHTTP() в Наrbour 3.0 и 3.1 содержит ошибку, которая исправлена в Наrbour 3.2, она может возникнуть при сложных запросах (например массив ХЭШ с login и password). Мои действия и как я это обошел: Работаю на xHarbour 1.2.1 (CRM и 2 сервера leto с программой синхронизации между ними) и xHarbour 1.0.0 (бухгалтерия). Решаю следующую задачу – передачу и прием данных (синхронизация ) таблиц DBF и данных на WEB по протоколу HTTP: 1. Обращение к странице авторизации программы для получения Cookie и Token из данных страницы. 2. Автоизация в WEB программе - Передача (POST) Login и Password , Cookie и Token на страницу авторизации и получения кода ответа nReplyCode : =302,cReplyDescr : "Found" и нового Cookie . 3. Обращение GET по адресу таблица.json и получение json Мои действия: 1. Беру xHarbour 1.2.1, класс TIPClientHTTP(). Получаю – что класс нерабочий, а именно – для чтения данных в классе используется метод ::InetRecvLine из класса tIPClientHTTP (соответственно INETRECVLINE в inet.c), а он работает некорректно. Вставляет пустую строку в середине заголовка (:hHeaders), теряя часть заголовка (в моем случае Cookie) и кидая остаток заголовка в данные. Беру копию метода POST и меняю ::InetRecvLine на ::InetRecvALL – вытягиваю Cookie. После этого ставлю :hFields["X-Requested-With"]:="XMLHttpRequest" :setCookie(sess_Cookies) Даю GET() и получаю json 2. Беру Наrbour 3.0 и Наrbour 3.1 , класс TIPClientHTTP() – получаю ошибку Error BASE/1123 Argument error: HB_HKEYAT Смотрю ChangeLog – ошибка исправлена 2012-07-30 (то есть в 3.2) 3. Беру Наrbour 3.2 последней сборки – ошибка Наrbour 3.1 действительно исправлена, но json получить не могу. Оказалось, что работающий код в xHarbour 1.2.1 oxml:=THtmlDocument():new(Cdata) oNode := oxml:findFirst( 'input', 'name','authenticity_token') a_token :=onode:getattribute('value') в Наrbour 3.2 почему-то не работает. Достаю 'authenticity_token' руками и получаю ту же проблему что и Наrbour 3.1 - ::InetRecvLine режет заголовок пополам и теряет Cookie. После разбора текстов все-таки догадался изменить везде при вызове - ::InetRecvLine в классе TIPClientHTTP() размер буфера с 500 на 1000 cLine := ::inetRecvLine( ::SocketCon, @nPos, 1000 ) После этого получил json. Заголовки (:hHeaders) тоже нормально разбираются. Необходимо исправить размер буфера при вызове :inetRecvLine в дистрибутиве Наrbour с 500 на 1000.

Softlog86: Возвращаясь к старой теме , в примере LoadHTML.PRG есть код по поиску и доступу к тегам .... там расписано как брать ссылки ... Подскажите синтаксис и аогоритм по выуживанию данных из таблицы внутри HTML-страницы : <table и соответственно строк с данными из жтой таблицы . Вот такой примерно кусок текста из такой страницы : ...... <table class="list"> <tr class="alternating"> <td>0001124005 <---- Эти данные нужно считывать </td> </tr> <tr class="alternating"> <td>0001124006 <---- Эти данные нужно считывать </td> </tr> <tr class="alternating"> <td>02B911023D <---- Эти данные нужно считывать </td> </tr> ........ <---- и так далее по таблице </table> ......... То есть вопрос в том , как добратьться до объекта <table ? , и соответственно считать в массив все строки с нужными данными ? Буду благодарен за хоть какую-то информацию . Таблиц <tablе в тексте несколько , но добраться нужно к определенной (она по порядку всегда на одном и том-же месте ) число строк может быть разным ...

santy: Приблизительно будет так: oHtmlDoc:readFile( "HTML\\test.html") aTableNodes := oHtmlDoc:body:tableS // Возвращает все ноди для tags table FOR EACH oNodeTable IN aTableNodes // пробегаем по всем таблицам IF 'class="list"' IN ALLTRIM(oNodeTable:attrToString()) // наша таблица FOR EACH otdNode1 IN oNodeTable:tdS // считываем tags td cAllData:=ALLTRIM(HtmlToAnsi(otdNode1:getText(""))) // считываем наш текст ........ // что-то с ними делаем NEXT ENDIF NEXT можна вместо attrToString() использовать :getAttribute( "class" ) если есть tr c разными классами тогда нужно считать сначала tr, найти ссответсвующий класс (атрибут) а потом уже считывать td и соответсвенно данные.

Softlog86: Есть ошибки и недостаточность кода : oHtmlDoc:readFile( "HTML\\test.html") aTableNodes := oHtmlDoc:body:tableS // Возвращает все ноди для tags table // oNodeTable - откуда взялось ? FOR EACH oNodeTable IN aTableNodes // пробегаем по всем таблицам IF 'class="list"' IN ALLTRIM(oNodeTable:attrToString()) // наша таблица // otdNode1 -откуда взялось ? FOR EACH otdNode1 IN oNodeTable:tdS // считываем tags td cAllData:=ALLTRIM(HtmlToAnsi(otdNode1:getText(""))) // считываем наш текст ........ // что-то с ними делаем NEXT ENDIF NEXT

santy: Ошибок думаю нету так как приблизительный код работает. Код для xHarbour. Для Harbour IN -> $. Всё остальное работало в Harbour. в начале объявите LOCAL aTableNodes:={}, oNodeTable, otdNode1 Посмотрите описание класса THtmlNode() в доке по xHarbour. Он должен быть аналогичный Harbour.

santy: Softlog86 пишет: Есть ошибки и недостаточность кода : Разобрались? Или объяснить более детально?

Softlog86: В принципе разобрался . Но есть ещё вопросы .Пока синтаксис не ложится в голову :) Не знаю как из таблицы <table вытащить данные по конкретным столбцам (3 и 4 колонка ) <h3>Vэsledek hledбnн pro шetмzec - CA1035IR </h3> <table style='margin-top:2px;'> <--------- НАША ТАБЛИЦА <tbody> <th>Nalezenй инslo <th>Firma <th>Nalezenб polo_ka <th>Dodavatel <th>Nбzev polo_ky <th>MC <th>MC + Dph <tr> <td>CA1035IR <td>HC-PARTS <td style='background:PaleGreen;'><a href='polozka.php?id_polozky=693443'>CA1035IR</a> <---- Это нам нужно то есть 3 и 4 колонка <td style='background:PaleGreen;'>HC-PARTS <---- И это нам нужно <td style='background:PaleGreen;'>alternбtor <td style='background:PaleGreen;' align=right>6 622,00 <td style='background:PaleGreen;' align=right>8 013,00 <tr> <td>CA1035IR <td>HELLA <td style='background:PaleGreen;'><a href='polozka.php?id_polozky=2418964'>860559</a> <---- Это нам нужно то есть 3 и 4 колонка <td style='background:PaleGreen;'>PRESTOLITE ELECTRIC <---- И это нам нужно <td style='background:PaleGreen;'>alternбtor <td style='background:PaleGreen;' align=right>0,00 <td style='background:PaleGreen;' align=right>0,00 <tr> <td>CA1035IR <td>HELLA <td style='background:PaleGreen;'><a href='polozka.php?id_polozky=1393149'>437442</a> <---- Это нам нужно то есть 3 и 4 колонка <td style='background:PaleGreen;'>VALEO <---- И это нам нужно <td style='background:PaleGreen;'>alternбtor <td style='background:PaleGreen;' align=right>20 445,00 <td style='background:PaleGreen;' align=right>24 738,00 .....................................

santy: Softlog86 пишет: В принципе разобрался . Но есть ещё вопросы .Пока синтаксис не ложится в голову :) Не знаю как из таблицы <table вытащить данные по конкретным столбцам (3 и 4 колонка ) Да там нет ничего сложного. Заполняем масивы объектов и проходим по массиву, берём объект и используя его методы достаём данные. Если Вы сами формируете html файл то лучше его наполнить, например добавить атрибуты : <td class="" id=""></td> чтобы можна их было как-то отличить. Если такое невозможно, ну тогда : 1. Мы нашли свою таблицую 2. Считываем все <tr> в масив, проходим по каждому <tr> : FOR EACH otrNode IN oNodeTable:trS 3. Считываем все <td> для конкретной <tr> в масив FOR EACH otdNode IN otrNode:tdS 4. проходим по массиву <td> . Если не можем отличить столбцы по уникальным атрибутам , тогда проще счётчик сделать. Когда счётчик будет 3 и 4 данные выбираем. В случае 3 столбца нужно опять считать масив тегов <a> и вытянуть атрибут href. NEXT NEXT

Softlog86: Тяжко пока писать .... ошибаюсь часто , особо не зная свойств объектов :(

Softlog86: как добыть строку что указана в img src= ??? Вот эта часть в тексте HTML страницы : 1 <td align=center><img src='foto/123.jpg'> 2 <td align=left><a href='polozka.php?id_polozky=3045032'><nobr>132216</nobr></a> :href - (строка 2 ) то есть ссылки получать умею Как добраться к <img src= , то есть получить его значение (foto/123.jpg) ?? onode:src или onode:img (по аналогии с :href) - не проодит - пустые значения выдаёт

fil: Если сайт идет на IE, то можно 1. открыть IE как ActiveX и встроить в свое окно 2. средствами DOM открываем этот сайт и мониторим его(по таймеру например) Ежели под IE не идет делаем тоже самое напр. на JS Или чего-то другое надо ?

Softlog86: Это нужно средствами Harbour + MiniGui cделать . Разобрать полученную страницу .... Loadhtml.prg как пример .

petr707: <img src='foto/123.jpg'> 1) Может быть так ? oDataset := oDoc1:findfirst( "img","src",@cValue,@cData) 2) В исходнике документа сделать замену 'foto/' на 'foto-' после определения значений - обратную замену ( м.б. проблема в символе / )

santy: подключаем hbtip. код: LOCAL otdNode1, oNode, oImg_1 LOCAL cImage_path .... FOR EACH otdNode1 IN oNode:tdS FOR EACH oImg_1 IN otdNode1:imgS ...... cImage_path := oImg_1:getAttribute( "src" ) ...... NEXT NEXT

MIKHAIL: Соединяюсь по 443(https) порту, использую синтаксис запроса HTTP, сервер возвращает ответ: HTTP/1.1 400 Bad Request Server: nginx Date: Sat, 05 Oct 2019 19:34:42 GMT Content-Type: text/html Content-Length: 150 Connection: close <html> <head><title>400 Bad Request</title></head> .... Вероятно требуется как то подключать сертификат ? Какой формат запроса https ?

MIKHAIL: Неужели никто с https не работает ? Сейчас большинство сайтов переведены на этот протокол... может есть где примеры глянуть ?

Dima: MIKHAIL пишет: Неужели никто с https не работает ? Погугли Harbour + Https

Andrey: MIKHAIL пишет: Неужели никто с https не работает ? Попробуй поиск в инете - harbour + https Вот здесь смотри - http://www.kresin.ru/hrbfaq_3.html#Doc13_15 [pre2]// Это 2-й поток Function GetData( lEnd ) Local nCount := 0, hSocket, cUrl, cServer, cBuf, aRes cServer := "clipper.borda.ru" cURL := "GET http://" + cServer + "/ HTTP/1.1" +Chr(13)+Chr(10) cURL += "Host: " + cServer + Chr(13)+Chr(10) cURL += "User-Agent: test_util"+Chr(13)+Chr(10) cUrl += Chr(13)+Chr(10)[/pre2] А по моему вообще очень трудно работать с https через Harbour. Судя по реакции на форуме - здесь таких умельцев нет.

MIKHAIL: Andrey я так и работаю с http, а вот https не пашет, выше ответ сервера приводил. Я полагаю требуется подключить ssl сертификат к запросу. А вот примеров не найти что то...

Andrey: MIKHAIL пишет: Я полагаю требуется подключить ssl сертификат к запросу. У себя в проге обновление качаю с сайта через внешнюю программу на C#, соединяюсь по https ! Прогу писал не я. Подключить сертификат в Харборе даже и не знаю как. Наверное очень трудоёмко это...

MIKHAIL: Andrey пишет: У себя в проге обновление качаю с сайта через внешнюю программу на C#, соединяюсь по https ! Ну вот я так же извратился, только через промежуточный сервер, который принимает http запрос, далее скипт на php получает данные с нужного https ресурса... Но все же хочется без костылей...

PSP: В сырцах харбора посмотрите contrib\hbssl. Там в папке tests есть примеры.

Dima: PSP пишет: В сырцах харбора посмотрите contrib\hbssl. Там в папке tests есть примеры. с языка снял PS Hbcurl умеет по Https

MIKHAIL: PSP пишет: В сырцах харбора посмотрите contrib\hbssl. Там в папке tests есть примеры. Спасибо, как раз уже посмотрел, все заработало, в сокращенном виде выглядит так #require "hbssl" #define CRLF Chr( 13 ) + Chr( 10 ) PROCEDURE Main() LOCAL ssl_ctx LOCAL ssl LOCAL socket LOCAL buffer LOCAL tmp hb_inetInit() socket := hb_inetCreate() ? hb_inetTimeout( socket, 2500 ) ? hb_inetConnect( "www.fortify.net", 443, socket ) ? hb_inetErrorCode( socket ) SSL_init() ? "SSL_CTX_NEW", ssl_ctx := SSL_CTX_new() ? "SSL_NEW", ssl := SSL_new( ssl_ctx ) ? "INET FD", hb_inetFD( socket ) ? "SSL_SET_FD", SSL_set_fd( ssl, hb_inetFD( socket ) ) ? "SSL_CONNECT", tmp := SSL_connect( ssl ) ? "SSL_GET_ERROR", SSL_get_error( ssl, tmp ) ? "SSL_WRITE", tmp := SSL_write( ssl, "GET / http/1.1" + CRLF + "Host: " + "www.fortify.net" + CRLF + CRLF ) ? "SSL_GET_ERROR", SSL_get_error( ssl, tmp ) buffer := Space( 1024 ) ? "SSL_READ", tmp := SSL_read( ssl, @buffer ) ? "SSL_GET_ERROR", SSL_get_error( ssl, tmp ) ? buffer ? hb_inetClose( socket ) RETURN

PSP: Dima пишет: с языка снял Ну, прости)) MIKHAIL пишет: Спасибо Не за что)

MIKHAIL: А доку под данным функциям реально найти ? У Кресина упоминается fd := hb_inetFD( hSocket, [l] ) , но без описания...

Dima: MIKHAIL пишет: Кресина упоминается fd := hb_inetFD( hSocket, [l] ) , но без описания... тут например

MIKHAIL: Dima там тоже не густо, хотелось бы понимать сущность функции. PS Раньше была хорошая дока на http://www.creasolgroup.com/ потом видимо контора закрылась, очень жалею что не скачал сайт...

PSP: MIKHAIL пишет: PS Раньше была хорошая дока на http://www.creasolgroup.com/ потом видимо контора закрылась, очень жалею что не скачал сайт... В такой ситуации могут помочь (к примеру): http://web.archive.org/ http://web-arhive.ru/

Dima: MIKHAIL пишет: Dima там тоже не густо, хотелось бы понимать сущность функции. Попробуй посмотреть сырец (я в си не очень) ....src\rtl\hbinet.c Функции HB_INETFD и HB_INETSTATUS К HB_INETSTATUS описание есть и есть некоторое сходство в этих функциях , возможно наведет на какие то мысли... PS Завтра попробую узнать у человека который шарит в Си , правда от Harbour он далек , может чего и подскажет.

Петр: MIKHAIL пишет: хотелось бы понимать сущность функции Посмотрев исходники, вы найдете, что функция возвращает socket->sd. sd - это socket descriptor. Подробнее найдете здесь https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.cbcpx01/ovsock.htm или что-то другое сможете нагуглить ;) P.S. FD - это file descriptor

MIKHAIL: *PRIVAT*



полная версия страницы