PHP preg_match_all regex для извлечения только числа в строке - PullRequest
1 голос
/ 14 марта 2012

Я не могу понять правильное регулярное выражение для извлечения только определенных чисел из строки.У меня есть HTML-строка с различными тегами img.В HTML есть куча тегов img, из которых я хочу извлечь часть значения.Они следуют следующему формату:

<img src="http://domain.com/images/59.jpg" class="something" />
<img src="http://domain.com/images/549.jpg" class="something" />
<img src="http://domain.com/images/1249.jpg" class="something" />
<img src="http://domain.com/images/6.jpg" class="something" />

Таким образом, переменные длины чисел перед тем, что «обычно» является .jpg (это может быть также .gif, .png или что-то еще).Я хочу только извлечь номер из этой строки.

Во-вторых, я хочу использовать это число, чтобы найти запись в базе данных и получить тег alt / title для этого конкретного идентификатора изображения.Наконец, я хочу добавить это возвращенное значение базы данных в строку и вернуть его обратно в строку HTML.

Любые мысли о том, как это сделать, были бы великолепны ...

До сих пор я пытался:

$pattern = '/img src="http://domain.com/images/[0-9]+\/.jpg';
preg_match_all($pattern, $body, $matches);
var_dump($matches);

Ответы [ 7 ]

2 голосов
/ 14 марта 2012

Я думаю, что это лучший подход:

  1. Использование HTML-парсера для извлечения тегов изображения
  2. Использование регулярного выражения (или, возможно, манипуляции со строками) для извлечения идентификатора
  3. Запрос данных
  4. Используйте HTML-анализатор для вставки возвращаемых данных

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

$html = '<img src="http://domain.com/images/59.jpg" class="something" />
<img src="http://domain.com/images/549.jpg" class="something" />
<img src="http://domain.com/images/1249.jpg" class="something" />
<img src="http://domain.com/images/6.jpg" class="something" />';
$doc = new DOMDocument;
$doc->loadHtml( $html);

foreach( $doc->getElementsByTagName('img') as $img)
{
    $src = $img->getAttribute('src');
    preg_match( '#/images/([0-9]+)\.#i', $src, $matches);
    $id = $matches[1];
    echo 'Fetching info for image ID ' . $id . "\n";

    // Query stuff here
    $result = 'Got this from the DB';

    $img->setAttribute( 'title', $result);
    $img->setAttribute( 'alt', $result);
}

$newHTML = $doc->saveHtml();
1 голос
/ 14 марта 2012

Попробуйте использовать preg_replace_callback.

Используйте это регулярное выражение: (images/([0-9]+)[^"]+")

Затем в качестве аргумента callback используйте анонимную функцию.Результат:

$output = preg_replace_callback(
    "(images/([0-9]+)[^\"]+\")",
    function($m) {
        // $m[1] is the number.
        $t = getTitleFromDatabase($m[1]); // do whatever you have to do to get the title
        return $m[0]." title=\"".$t."\"";
    },
    $input
);
1 голос
/ 14 марта 2012

использование preg_match_all :

preg_match_all('#<img.*?/(\d+)\.#', $str, $m);
print_r($m);

вывод:

Array
(
    [0] => Array
        (
            [0] => <img src="http://domain.com/images/59.
            [1] => <img src="http://domain.com/images/549.
            [2] => <img src="http://domain.com/images/1249.
            [3] => <img src="http://domain.com/images/6.
        )

    [1] => Array
        (
            [0] => 59
            [1] => 549
            [2] => 1249
            [3] => 6
        )

)
1 голос
/ 14 марта 2012

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

preg_match_all('/<img src="http:\/\/domain.com\/images\/(\d+)\.[a-zA-Z]+"/', $html, $matches);
print_r($matches);

Он будет содержать все найденные материалы.

0 голосов
/ 14 марта 2012

Регулярные выражения сами по себе немного растут, когда дело доходит до парсинга дерьмового HTML. Обработка HTML DOMDocument довольно хороша для горячей и свежей подачи тегов, xpath для выбора srcs вашего изображения и простой sscanf для извлечения числа:

$ids = array();
$doc = new DOMDocument();
$doc->loadHTML($html);
foreach(simplexml_import_dom($doc)->xpath('//img/@src[contains(., "/images/")]') as $src) {
    if (sscanf($src, '%*[^0-9]%d', $number)) {
        $ids[] = $number;
    }
}

Поскольку это дает только массив, почему бы не инкапсулировать его?

$html = '<img src="http://domain.com/images/59.jpg" class="something" />
<img src="http://domain.com/images/549.jpg" class="something" />
<img src="http://domain.com/images/1249.jpg" class="something" />
<img src="http://domain.com/images/6.jpg" class="something" />';

$imageNumbers = new ImageNumbers($html);

var_dump((array) $imageNumbers);

Что дает вам:

array(4) {
  [0]=>
  int(59)
  [1]=>
  int(549)
  [2]=>
  int(1249)
  [3]=>
  int(6)
}

Эта функция, описанная выше, красиво обернута в ArrayObject:

class ImageNumbers extends ArrayObject
{
    public function __construct($html) {
        parent::__construct($this->extractFromHTML($html));
    }
    private function extractFromHTML($html) {
        $numbers = array();
        $doc = new DOMDocument();
        $preserve = libxml_use_internal_errors(TRUE);
        $doc->loadHTML($html);
        foreach(simplexml_import_dom($doc)->xpath('//img/@src[contains(., "/images/")]') as $src) {
            if (sscanf($src, '%*[^0-9]%d', $number)) {
                $numbers[] = $number;
            }
        }
        libxml_use_internal_errors($preserve);
        return $numbers;
    }
}

Если ваш HTML должен быть настолько отформатирован, что даже DOMDocument::loadHTML() не сможет его обработать, то вам нужно обрабатывать его только внутри класса ImageNumbers.

0 голосов
/ 14 марта 2012
$matches = array();
preg_match_all('/[:digits:]+/', $htmlString, $matches);

Затем переберите массив matches, чтобы как восстановить HTML, так и посмотреть в базе данных.

0 голосов
/ 14 марта 2012

Это регулярное выражение должно соответствовать числовым частям:

\/images\/(?P<digits>[0-9]+)\.[a-z]+

В вашем $matches['digits'] должны быть все необходимые вам цифры в виде массива.

...