Как анализировать HTML-теги с помощью REBOL? - PullRequest
3 голосов
/ 17 июня 2011

У меня есть веб-страница, которую я загрузил с загрузкой / разметкой.Мне нужно разобрать кучу вещей из этого, но некоторые данные находятся в тегах.Любые идеи о том, как я могу разобрать это?Вот пример того, что я получил (и попробовал) до сих пор:

REBOL []

mess: {
<td>Bob Sockaway</td>
<td><a href=mailto:bsockaway@example.com>bsockaway@example.com</a></td>
<td>9999</td>
}

rules: [
    some [
        ; The expression below /will/ work, but is useless because of specificity.
        ; <td> <a href=mailto:bsockaway@example.com> s: string! </a> (print s/1) </td> | 

        ; The expression below will not work, because <a> doesn't match <a mailto=...>
        ; <td> <a> s: string! </a> (print s/1) </td> |

        <td> s: string! (print s/1) </td> |

        tag! | string! ; Catch any leftovers.
    ]
]

правила разбора загрузки / разметки

Это дает:

Bob Sockaway
9999

Iхотел бы увидеть что-то еще как:

Bob Sockaway
bsockaway@example.com
9999

Есть мысли?Спасибо!

Примечание!Для чего бы это ни стоило, я придумал хороший простой набор правил, который даст желаемые результаты:

rules: [
    some [
        <td> any [tag!] s: string! (print s/1) any [tag!] </td> |
        tag! | string! ; Catch any leftovers.
    ]
]

Ответы [ 2 ]

2 голосов
/ 17 июня 2011

Когда mess обрабатывается с LOAD/MARKUP, вы получаете это (и я отформатировал + прокомментировал с типами):

[
    ; string!
    "^/" 

    ; tag! string! tag!
    <td> "Bob Sockaway" </td>

    ; string!
    "^/"

    ; tag! tag!
    ;     string!
    ; tag! tag!
    <td> <a href=mailto:bsockaway@example.com>
        "bsockaway@example.com"
    </a> </td>

    ; (Note: you didn't put the anchor's href in quotes above...)

    ; string!
    "^/"

    ; tag! string! tag!
    <td> "9999" </td> 

    ; string!
    "^/"
]

Ваш шаблон вывода соответствует серии вида [<td> string! </td>], но не вещам формы [<td> tag! string! tag! </td>]. Обойдя вопрос, поставленный в вашем заголовке, вы можете решить эту конкретную дилемму несколькими способами. Можно было бы вести подсчет того, находитесь ли вы внутри тега TD, и печатать какие-либо строки, когда число не равно нулю:

rules: [
    (td-count: 0)
    some [
        ; if we see an open TD tag, increment a counter
        <td> (++ td-count)
        |
        ; if we see a close TD tag, decrement a counter
        </td> (-- td-count)
        |
        ; capture parse position in s if we find a string
        ; and if counter is > 0 then print the first element at
        ; the parse position (e.g. the string we just found) 
        s: string! (if td-count > 0 [print s/1])
        |
        ; if we find any non-TD tags, match them so the
        ; parser will continue along but don't run any code
        tag!
    ]
]

В результате вы получите запрос:

Bob Sockaway
bsockaway@example.com
9999

Но вы также хотели знать, по сути, можете ли вы переходить к разбору строк из разбора блоков по тому же набору правил (без перехода в открытый код). Я посмотрел на это «смешанный анализ», похоже, что это может быть функция, рассматриваемая в Rebol 3. Тем не менее, я не мог заставить его работать на практике. Поэтому я задал свой вопрос.

Как смешать разбор строк и разбор блоков в одном правиле?

1 голос
/ 23 января 2016

Я думаю, что нашел довольно хорошее решение.Может потребоваться обобщение, если у вас было много разных тегов, атрибуты которых вам нужны.

Я искал атрибут id тега запроса!:

<query id="5">

В правиле разборадля тега !, я сделал это:

  | set t tag! (
    p: make block! t 
    if p/1 = 'query [_qid: to-integer p/3]
  )

Больше тегов, чтобы посмотреть, я бы использовал случай.И, может быть, это было бы лучше установить _qid

to-integer select p 'id=

Мне пришлось проанализировать другой тег, и это хороший общий шаблон

switch p/1 [
  field [_fid: to-integer p/id= _field_type: p/field_type=]
  query [_qid: to-integer p/id=]
]
...