Как извлечь данные href, title и text из тега <a>с определенным значением класса из очищенного HTML? - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть это регулярное выражение для preg_match_all(), которое корректно совпадает на regex101.com, но не в моем коде.

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

<a class="profile-link" href="CompanyProfile.aspx?PID=4813&amp;country=211&amp;practicearea=0&amp;pagenum=" title="1-844-Iran-Law">Amin Alemohammad</a>

Который найден во всем результате html скручивания. Каждый блок имеет следующее, например ::10000

<li style="opacity: 1;">
   <a class="profile-link" href="CompanyProfile.aspx?PID=4813&amp;country=211&amp;practicearea=0&amp;pagenum=" title="1-844-Iran-Law">Amin Alemohammad</a>
   <!--<a class="profile-link" href="javascript:void(0)" title="1-844-Iran-Law">Amin Alemohammad</a>-->
   <img src="/Images/Uploaded/Photos/4813_1844IranLaw.png" style="max-width:140px; max-height:140px">
   <div class="results-profile">
      <h2>Amin Alemohammad</h2>
      <p><strong>Firm:</strong> 1-844-Iran-Law <br> <strong>Country:</strong> USA</p>
   <p class="blue"><strong>Practice Area:</strong> Iranian Desk</p>
   <ul>
      <li class="tel-icon" style="opacity: 1;">Tel: +1-202-465-8692</li>
      <li class="fax-icon" style="opacity: 1;">Fax: +1-202-776-0136</li>
      <li class="email-icon">Email: <a style="position:relative; z-index:9999;" href="mailto:amin@1844iranlaw.com">amin@1844iranlaw.com</a></li>
   </ul>
   </div><!-- results profile -->
      <img class="practice-logo" src="/Images/Uploaded/Logos/4813_1844IranLaw.png" style="max-width:185px; max-height:70px;">
      <a class="results-btn contact-btn" href="CompanyProfile.aspx?PID=4813&amp;country=211&amp;practicearea=0&amp;pagenum=" title="View Full Profile">VIEW FULL PROFILE</a>
      <!--<a class="results-btn contact-btn" href="CompanyProfile.aspx?PID=4813&country=211&practicearea=0&pagenum=" title="1-844-Iran-Law">CONTACT</a>-->
      <a class="results-btn website-btn" href="http://www.1844iranlaw.com" title="www.1844iranlaw.com">VIEW WEBSITE</a>
   </li>
</li>

Результат регулярного выражения

Group 1.    54-58   `4813` // company profile
Group 2.    71-74   `211` // country id
Group 3.    92-93   `0` // practice area
Group 5.    115-129 `1-844-Iran-Law` // company name
Group 6.    131-147 `Amin Alemohammad` // Person's name

Что у меня есть:

preg_match_all('/<a class="profile-link" href="CompanyProfile\.aspx\?PID=(.*?)&amp;country=([0-9]{1,}?)&amp;practicearea=([0-9]{1,10}?)&amp;pagenum=\?" title="(.*?)">(.*?)<\/a>/', $result, $match, PREG_PATTERN_ORDER);
dd($match);

, который возвращает

array:6 [▼
   0 => []
   1 => []
   2 => []
   3 => []
   4 => []
   5 => []
]

Количество совпадений правильное -> 5 совпадений в строковом шаблоне, но я не могу понять, почему он возвращает пустые значения.

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

Ответы [ 3 ]

0 голосов
/ 26 апреля 2018

Ну, после некоторого времени, углубляясь в проблему, анализируя весь html-файл, который нужно проанализировать с помощью preg_match_all(), я просто включаю его, добавив пару строк для замены \t \r \n из html с момента добавления его в регулярное выражение не работает.

Таким образом, решение было бы добавить следующие две строки перед preg_match_all():

(...)
$result = curl_exec($curl); // already there

$result = str_replace(["&amp;"], "&", $result); // new
$result = str_replace(["\t", "\r", "\n"], "", $result); // new
$regex = '/<a class="profile-link" href="CompanyProfile\.aspx\?PID=(.*?)&country=([0-9]{1,}?)&practicearea=([0-9]{1,}?)&pagenum=" title="(.*?)">(.*?)<\/a>/s';

preg_match_all($regex, $result, $match, PREG_SET_ORDER);

Затем вместо ссылки &amp; я ввел символ & в регулярном выражении. Это работает как шарм!

Чем вы все, кто там помогал!

0 голосов
/ 29 апреля 2018

Код: ( Демо )

$dom = new DOMDocument; 
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$output = [];
foreach ($xpath->evaluate("//a[@class='profile-link']") as $node) {
    parse_str(parse_url($node->getAttribute('href'), PHP_URL_QUERY), $output);
    $output['title'] = $node->getAttribute('title');
    $output['text'] = $node->nodeValue;
}
var_export($output);

Выход:

array (
  'PID' => '4813',
  'country' => '211',
  'practicearea' => '0',
  'pagenum' => '',
  'title' => '1-844-Iran-Law',
  'text' => 'Amin Alemohammad',
)

Я полагаю, что это использует всю красоту языка php с DomDocument с Xpath, чтобы надежно / напрямую нацелить на соответствующий тег / узел, затем parse_url() с parse_str(), чтобы красноречиво преобразовать данные строки запроса в желаемый пары ключ-значение.

Теперь у вас будет что-то стабильное без хакерских str_replace() вызовов или шаблонов регулярных выражений.

0 голосов
/ 26 апреля 2018

Вместо использования регулярного выражения вы можете использовать DOMDocument .

Чтобы получить значения из атрибута href, вы можете использовать explode и parse_str .

$html = <<<HTML
<a class="profile-link" href="CompanyProfile.aspx?PID=4813&amp;country=211&amp;practicearea=0&amp;pagenum=" title="1-844-Iran-Law">Amin Alemohammad</a>
HTML;

$doc = new DOMDocument();
$doc->loadHTML($html);
foreach($doc->getElementsByTagName('a') as $a) {
    if ($a->getAttribute('class') === 'profile-link') {
        $parts = explode('?', $a->getAttribute('href'), 2);
        parse_str($parts[1], $output);

        echo 'Title: ' . $a->getAttribute('title') . '<br>';
        echo 'Text: ' . $a->nodeValue . '<br>';
        echo 'PID: ' . $output['PID'];
        // etc..
    }
}

Демо

...