Wyciągnięcie fragmentu HTML z większego fragmentu

0

Witam,

Mam taki kod strony (fragment)


    			  <div class="produkt_opcje" id="produkt_opcje" title="2278"></div>
    			</div> <!-- meta info -->
    		</div> <!-- row -->
    		<div class="description-wrapper clearfix">
    			<div class="desc-col">
    				<h3><a href="informacja">Opis podstawowy</a></h3>
    <div class="text">
      <h3>Cechy</h3>
              produkt kontrolowany na nieobecność GMO
            <br></div>
    <h3><a href="informacja">Nazwa produktu uregulowana prawnie</a></h3>
    <div class="text">Konserwa warzywna z ryżem sterylizowana.<br></div>
    <h3><a href="informacja">Składniki</a></h3>
    <div class="text">ryż gotowany 23%, woda, teksturat <span style='font-weight: bold;'>sojowy</span> 15%, olej rzepakowy, warzywa 14% (cebula, marchewka, papryka, pietruszka), koncentrat pomidorowy 5%, kasza manna (<span style='font-weight: bold;'>pszenica</span>), mąka ryżowa, białko <span style='font-weight: bold;'>sojowe</span>, sól morska, hydrolizat białka roślinnego (<span style='font-weight: bold;'>soja</span>, kukurydza), przyprawy, ekstrakty i olejki eteryczne przypraw, ekstrakt drożdżowy, cukier trzcinowy, aromaty (<span style='font-weight: bold;'>seler</span>)</div>
    <h3><a href="informacja">Informacja o wartości odżywczej</a></h3>
    <div class="text">
      <table border="1">
        <tr>
          <th></th>
          <th>w 100 g produktu:</th>
        </tr>

I chciałbym pobrać następujący fragment

<div class="text">ryż gotowany 23%, woda, teksturat <span style='font-weight: bold;'>sojowy</span> 15%, olej rzepakowy, warzywa 14% (cebula, marchewka, papryka, pietruszka), koncentrat pomidorowy 5%, kasza manna (<span style='font-weight: bold;'>pszenica</span>), mąka ryżowa, białko <span style='font-weight: bold;'>sojowe</span>, sól morska, hydrolizat białka roślinnego (<span style='font-weight: bold;'>soja</span>, kukurydza), przyprawy, ekstrakty i olejki eteryczne przypraw, ekstrakt drożdżowy, cukier trzcinowy, aromaty (<span style='font-weight: bold;'>seler</span>)</div>

Coś takiego mam :

preg_match('/Składniki<\/a><\/h3>(.*)<\/div>/i', $strona, $wynik);

Niestety to mi nie zwraca wyniku, proszę o pomoc w tym temacie.

3

Po pierwsze wyrażenia regularne do tego to niezbyt mądry pomysł od tego jest DOMDocument ale jak koniecznie musisz to

/Składniki.+\r?\n?(.+)\r?\n?<h3>/
0

Bardzo dziękuje za pomoc

2
Busyboy napisał(a):

Coś takiego mam :

preg_match('/Składniki<\/a><\/h3>(.*)<\/div>/i', $strona, $wynik);

Niestety to mi nie zwraca wyniku, proszę o pomoc w tym temacie.

Parsowanie HTML'a przy użyciu wyrażeń regularnych to na prawdę jest bardzo zły pomysł. Nie wiem dlatego nie chcesz skorzystać z rady @kAzek, bo użycie DOMDocument na prawdę byłoby dużo lepszym pomysłem. Wydaje mi się że nie chcesz go użyć, bo nie do końca rozumiesz jak działa, więc pozwól że Ci pomogę.

Co tu się dzieje konkretnie:

  1. Mamy funkcję parseHtml() która przyjmuje string w którym jest HTML, i ma za zadanie wyciągnąć tablicę stringów, która zwiera wewnętrzne wartości pewnych dzieci, w tym wypadku div z klasą text - bo użyłem xpath //div[@class='text']. Łatwo jest też napisać xPath pod id, kolejność, etc.
  2. Ładujemy html'a do DOMDocument, użyłem też mb_convert_encoding() żeby zachować Twoje znaki specjalne jak ż w słowie ryż.
  3. Używając DOMDocument możemy odpowiednio iterować po elementach trzewa albo ręcznie (np przy użyciu foreach), albo poprzez DOMXPath - ja użyłem DOMXPath
  4. Dostajemy listę znalezionych dzieci, czyli <div> z klasą 'text'
  5. Iteruję po liście, i wołam na nich saveHtml(), żeby z pojedyńczego elementu zwrócić tylko jego wewnętrzną treść
  6. Zwracamy listę.
<?php

function parseHtml(string $html): array
{
    $document = new \DOMDocument();
    $unicodeHtml  = mb_convert_encoding($html , 'HTML-ENTITIES', 'UTF-8');
    @$document->loadHTML($unicodeHtml);
    $xpath = new DOMXpath($document);
    $nodes = $xpath->query("//div[@class='text']"); // xpath
    if ($nodes === false) {
        throw new Exception("xPath is malformed"); 
    }
    $strings = [];
    foreach ($nodes as $node) {
        $strings[] = $node->ownerDocument->saveHtml($node);
    }
    return $strings;
}

$html = <<<HTML
    			  <div class="produkt_opcje" id="produkt_opcje" title="2278"></div>
    			</div> <!-- meta info -->
    		</div> <!-- row -->
    		<div class="description-wrapper clearfix">
    			<div class="desc-col">
    				<h3><a href="informacja">Opis podstawowy</a></h3>
    <div class="text">
      <h3>Cechy</h3>
              produkt kontrolowany na nieobecność GMO
            <br></div>
    <h3><a href="informacja">Nazwa produktu uregulowana prawnie</a></h3>
    <div class="text">Konserwa warzywna z ryżem sterylizowana.<br></div>
    <h3><a href="informacja">Składniki</a></h3>
    <div class="text">ryż gotowany 23%, woda, teksturat <span style='font-weight: bold;'>sojowy</span> 15%, olej rzepakowy, warzywa 14% (cebula, marchewka, papryka, pietruszka), koncentrat pomidorowy 5%, kasza manna (<span style='font-weight: bold;'>pszenica</span>), mąka ryżowa, białko <span style='font-weight: bold;'>sojowe</span>, sól morska, hydrolizat białka roślinnego (<span style='font-weight: bold;'>soja</span>, kukurydza), przyprawy, ekstrakty i olejki eteryczne przypraw, ekstrakt drożdżowy, cukier trzcinowy, aromaty (<span style='font-weight: bold;'>seler</span>)</div>
    <h3><a href="informacja">Informacja o wartości odżywczej</a></h3>
    <div class="text">
      <table border="1">
        <tr>
          <th></th>
          <th>w 100 g produktu:</th>
        </tr>
HTML;

$subElements = parseHtml($html);
var_dump($subElements);

Czemu skorzystanie z DOMDocument jest dużo lepszym pomysłem, niż preg_match(). Ano z takiego powodu, że bardzo trudno (niemal niemożliwe) jest napisanie odpowiedniego wyrażenia regularnego które mogłoby złapać HTML. Weź pod uwagę, że musisz operować nie tylko na znakach < oraz ", ale również na wszystkich pozostałych symbolach, rozróżnić np komentarze html <!-- oraz -->, encje, np &lt;/&gt;, i masę innych rzeczy. preg_match() może wydawać się dobrym pomysłem na początek, ale im dłużej będziesz z nim pracował tym gorsze rezultaty dostaniesz. Ostatecznym problemem z parsowaniem HTML'a regexpami jest problem znalezienia odpowiednich domknięć, jak masz kod <div><div>some</div></div> to 99% parserów HTML'a napisanych przy regexpach złapie <div><div>some</div> jako pierwszy node.

Poświęć te kilka dodatkowych minut na ogarnięcie DOMDocument, i staraj się wszystkie manipulacje na drzewie robić właśnie DOMDocument, i zapomnij o parsowaniu HTML'a regexpami.

Na zachęte: wpis na StackOverflow o parsowaniu HTML'a wyrażeniami regularnymi, coś dla Ciebie: https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags

1 użytkowników online, w tym zalogowanych: 0, gości: 1