Извлечение javascript-объекта из html с использованием регулярных выражений и php - PullRequest
0 голосов
/ 08 мая 2018

Я пытаюсь извлечь конкретный объект JavaScript со страницы, содержащей обычную разметку HTML.

Я пытался использовать регулярное выражение, но мне кажется, что я не могу заставить его правильно анализировать HTMLкогда HTML содержит разрыв строки.

Пример можно увидеть здесь: https://regex101.com/r/b8zN8u/2

HTML-код, который я пытаюсь извлечь, выглядит следующим образом:

<script>
  DATA.tracking.user = { 
      age: "19", 
      name: "John doe" 
  }
</script>

Используя следующее регулярное выражение: DATA.tracking.user = (. *?)}

<?php
$re = '/DATA.tracking.user = (.*?)\}/m';
$str = '<script>
           DATA.tracking.user = { age: "19", name: "John doe" }
        </script>';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

Если я анализирую DATA.tracking.user = { age: "19", name: "John doe" } без каких-либо разрывов строк, то это работает нормально, но если я пытаюсь разобрать:

DATA.tracking.user = { 
      age: "19", 
      name: "John doe" 
  }

Не нравится иметь дело с переносами строк.

Любая помощь будет принята с благодарностью.

Спасибо.

Ответы [ 4 ]

0 голосов
/ 08 мая 2018

Простое решение вашей проблемы - использовать модификатор шаблона s, чтобы подать команду . (любой символ), чтобы она также соответствовала символам новой строки, чего по умолчанию нет.

И выследует:

  • экранировать ваши буквальные точки.
  • написать \{ за пределами вашей группы захвата.
  • опустить модификатор шаблона m, потому что вы не 't с помощью якорей.

... НО ...

Если бы это было моей задачей, и я собирался обрабатывать данные из извлеченной строки, я бы, вероятно, начал ломатьдо компонентов во время извлечения с силой \G.

Код: ( Демо ) ( Pattern Demo )

$htmls[] = <<<HTML
DATA.tracking.user = { age: "19", name: "John doe", int: 55 } // This works
HTML;

$htmls[] = <<<HTML
DATA.tracking.user = { 
    age: "20", 
    name: "Jane Doe",
    int: 49
} // This does not works
HTML;

foreach ($htmls as $html) {
    var_export(preg_match_all('~(?:\G(?!^),|DATA\.tracking\.user = \{)\s+([^:]+): (\d+|"[^"]*")~', $html, $out, PREG_SET_ORDER) ? $out : []);
    echo "\n --- \n";
}

Вывод:

array (
  0 => 
  array (
    0 => 'DATA.tracking.user = { age: "19"',
    1 => 'age',
    2 => '"19"',
  ),
  1 => 
  array (
    0 => ', name: "John doe"',
    1 => 'name',
    2 => '"John doe"',
  ),
  2 => 
  array (
    0 => ', int: 55',
    1 => 'int',
    2 => '55',
  ),
)
 --- 
array (
  0 => 
  array (
    0 => 'DATA.tracking.user = { 
    age: "20"',
    1 => 'age',
    2 => '"20"',
  ),
  1 => 
  array (
    0 => ', 
    name: "Jane Doe"',
    1 => 'name',
    2 => '"Jane Doe"',
  ),
  2 => 
  array (
    0 => ',
    int: 49',
    1 => 'int',
    2 => '49',
  ),
)
 --- 

Теперь вы можете просто повторять совпадения и работать с [1] (ключи) и [2] (значения).Это базовое решение, которое может быть дополнительно адаптировано к данным вашего проекта.Следует признать, что это не учитывает значения, которые содержат экранированные двойные кавычки.Добавление этой функции не составит труда.Учет более сложных типов значений может быть более сложной задачей.

0 голосов
/ 08 мая 2018

Вам нужно будет указать пробелы (\s) в вашем шаблоне, чтобы проанализировать код javascript, содержащий разрывы строк.

Например, если вы используете следующий код:

<?php
$re = '/DATA.tracking.user = \{\s*.*\s*.*\s*\}/';
$str = '<script>
  DATA.tracking.user = {
      age: "19",
      name: "John doe"
  }
</script>';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
print_r($matches[0]);
?>

Вы получите следующий вывод:

Array
(
    [0] => DATA.tracking.user = {
      age: "19",
      name: "John doe"
  }
)
0 голосов
/ 08 мая 2018

Вам нужно добавить модификатор 's' в конец вашего регулярного выражения - в противном случае, "." не включает переводы строк. См это :

с (PCRE_DOTALL)

Если этот модификатор установлен, метасимвол точки в шаблоне соответствует всем символам, включая символы новой строки. Без этого новые строки исключаются. Этот модификатор эквивалентен модификатору Perl's / s. Отрицательный класс, такой как [^ a], всегда соответствует символу новой строки, независимо от настройки этого модификатора.

Так что в основном измените свое регулярное выражение на:

'/DATA.tracking.user = (.*?)\}/ms'

Кроме того, вы должны указать другие точки (в противном случае вы будете соответствовать "DATAYtrackingzZuser". Итак ...

'/DATA\.tracking\.user = (.*?)\}/ms'

Я бы также добавил открытую фигурную скобку и не вводил один пробел вокруг знака равенства, поэтому:

'/DATA\.tracking\.user\s*=\s*\{(.*?)\}/ms'
0 голосов
/ 08 мая 2018

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

Обратитесь к этому для значений ascii:
https://www.techonthenet.com/ascii/chart.php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...