swi prolog 8.0.2: gziped http - PullRequest
       40

swi prolog 8.0.2: gziped http

2 голосов
/ 11 марта 2019

Я попытался заставить работать кусок кода, который открывает http-соединение.Тем не менее, веб-страница может быть передана в виде простого текста или gziped.В результате код с прагматизмом пытается открыть как обычный текст, и если он терпит неудачу и получает исключение, пытается, как если бы он был закодирован gzip.

URL - единственная переменная для заземления.Попробуйте, например, с URL = 'http://releases.llvm.org/6.0.0/tools/clang/docs/ClangCommandLineReference.html'.

                user::catch(
                (
                 user::http_open(URL, DataStream, []),                            
                 user::load_html(stream(DataStream), Terms, []),
                 user::close(DataStream)
                ),
                _
                ,
                (
                 user::open_any(URL, read, GZipDataStream, CloseIt, [encoding(gzip), string(atom)]),
                 /*user::http:encoding_filter(gzip, DataStream, GZipDataStream),*/
                 user::load_html(stream(GZipDataStream), Terms, []),
                 user::close_any(CloseIt)
                )
                )

К сожалению, восстановительная часть catch не работает.

Есть предложения, пожалуйста?

1 Ответ

2 голосов
/ 11 марта 2019

Префиксы user:: в целях указывают на то, что размещенный вами код является фрагментом Logtalk. Если это так, то он неправильно использует исходный код Logtalk и создает зависимость от механизма автозагрузки SWI-Prolog. Код может быть переписан для ясности и устойчивости. Выполнение этого и исправление ошибки в нем (library(zlib) необходимо загрузить, чтобы сделать доступным фильтр http:encoding_filter/3) приводит к следующему решению:

:- use_module(library(http/http_open), []).
:- use_module(library(sgml), []).
:- use_module(library(iostream), []).
:- use_module(library(zlib), []).


:- object(html).

    :- public(get_url/2).

    % override ambiguous meta-predicate template
    :- meta_predicate(sgml:load_html(*,*,*)).

    get_url(URL, Terms) :-
        catch(
                setup_call_cleanup(
                    http:http_open(URL, DataStream, []),
                    sgml:load_html(stream(DataStream), Terms, []),
                    close(DataStream)
                ),
                _,
                setup_call_cleanup(
                    iostream:open_any(URL, read, DataStream, CloseIt, [string(atom)]),
                    sgml:load_html(stream(DataStream), Terms, []),
                    iostream:close_any(CloseIt)
                )
            ).

:- end_object.

Вызовы setup_call_cleanup/3 обеспечивают закрытие открытых потоков в случае ошибки.

Предполагая, что объект выше сохранен в файле html.lgt, следующий пример вызова показывает, что он работает для отправленного вами URL:

?- {html}.
...
% (0 warnings)
true.

?- html::get_url('http://releases.llvm.org/6.0.0/tools/clang/docs/ClangCommandLineReference.html', Terms).
Terms = [element(html, [xmlns='http://www.w3.org/1999/xhtml'], [element(head, [], [element(meta, ['http-equiv'='Content-Type', content='text/html; charset=utf-8'], []), element(title, [], ['Clang command line argument reference — Clang 6 documentation']), element(link, [... = ...|...], []), element(link, [...|...], []), element(..., ..., ...)|...]), element(body, [role=document], ['      ', element(div, [... = ...|...], [element(..., ..., ...)|...]), '\n      ', element(..., ..., ...)|...])])].
...