Я пытаюсь извлечь данные с веб-страницы, чтобы вставить ее в базу данных. Данные, которые меня интересуют, находятся в div, которые имеют класс = «компания». На одной веб-странице есть 15 или менее div, и есть много страниц, с которых я пытаюсь извлечь эти данные. По этой причине я пытаюсь найти автоматическое решение для извлечения данных.
Деб с классом = «компания» выглядит следующим образом (на одной странице с разными данными есть 15 или менее divs):
<div class="company" id="company-6666"> <!-- EXTRACT 'company-6666' from id="company-6666" --> <div class="top clearfix"> <div class="name clearfix"> <h2> <a href="/company-name">Company Name</a> <!-- EXTRACT 'Company Name' from contents of A element and EXTRACT '/company-name' from href attribute --> <a href="/branches-list-link?parent_id=6666" class="branches">Branches <span>(5)</span></a> <!-- EXTRACT '/branches-list-link?parent_id=6666' from href attribute --> </h2> </div> </div> <div class="inner clearfix has-logo"> <div class="clearfix"> <div class="logo"> <a href="/company-name"> <img src="/graphics/company/logo/listing/123456.jpg?_ts=1365390237" border="0" alt="" /> <!-- EXTRACT '/graphics/company/logo/listing/123456.jpg?_ts=1365390237' from src attribute --> </a> </div> <div class="info"> <div class="address">StreetName 500, 7777 City, County</div> <!-- EXTRACT 'StreetName 500, 7777 City, County' from contents of class="address" div --> <div class="clearfix"> <div class="slogan">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ac condimentum mi.</div> <!-- EXTRACT 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi ac condimentum mi.' from contents of class="slogan" div --> </div> </div> </div> <div class="actions-bar clearfix"> <ul> <li><span class="phone-number">6666666</span></li> <!-- EXTRACT '6666666' from contents of class="phone-number" div --> <li><a href="mailto:mail@mail.com" target="_blank" title="mail@mail.com" class="email">mail@mail.com</a></li> <!-- EXTRACT 'mail@mail.com' from contents of class="email" div --> <li><a href="http://www.webpage.com" target="_blank" title="www.webpage.com" class="redirect url">www.webpage.com</a></li> <!-- EXTRACT 'www.webpage.com' from contents of class="redirect url" div --> </ul> </div> </div> </div>
До сих пор у меня есть следующий PHP-код (в $ output есть HTML-код веб-страницы):
<?php $doc = new DomDocument(); @$doc->loadHTML($output); $doc->preserveWhiteSpace = false; $xpath = new DomXPath($doc); $elements = $xpath->query("//*[@class='company']"); if (!is_null($elements)) { foreach ($elements as $element) { echo $element->nodeValue; } } ?>
Кажется, что он получает все 15 div с классом = «компания», но я понятия не имею, как извлечь ранее упомянутые (в комментариях HTML-кода) отдельные значения.
Каждый div (я говорю о div с class = "company") не имеет всех значений, записанных в блоке HTML. Так почему-то я должен сделать запрос, если конкретный div внутри div компании, где интересуются данные, существует, и если он существует, я должен проверить, не является ли он пустым (содержит текст между тегами или нет). Если он существует и не является пустым, я добавляю его к переменной.
Как только значения извлекаются, я хотел бы назначить их переменным PHP, которые позволят мне работать с ними впоследствии. Было бы еще лучше, если бы извлеченные значения были помещены в массив следующим образом:
$result = array( // 1'st div's data [0] => 'company name' => 'company name', 'company link' => 'company link', 'company id' => 'company id', 'company branches' => 'branches link', 'company logo' => 'logo', 'company address' => 'address', 'company slogan' => 'slogan', 'company webpage' => 'webpage', 'company email' => 'email', 'company phone' => 'phone' // 2'nd div's data [1] => 'company name' => 'company name', 'company link' => 'company link', 'company id' => 'company id', 'company branches' => 'branches link', 'company logo' => 'logo', 'company address' => 'address', 'company slogan' => 'slogan', 'company webpage' => 'webpage', 'company email' => 'email', 'company phone' => 'phone' ... )
Каждая компания может быть представлена контекстным узлом, имея при этом каждое свойство, представленное выражением xpath относительно него:
Company company-6666: ->id ....... = "company-6666" -- string(@id) ->name ..... = "Company Name" -- .//a[1]/text() ->href ..... = "/company-name" -- .//a[1]/@href ->img ...... = "/graphics/company/logo/listing/123456.jpg?_ts=1365390237" -- .//img[1]/@src ->address .. = "StreetName 500, 7777 City, County" -- .//*[@class="address"]/text() ...
Если вы обернете это в объекты, это довольно изящно использовать:
$doc = new DOMDocument(); $doc->loadHTML($html); /* @var $companies DOMValueObject[] */ $companies = new Companies($doc); foreach ($companies as $company) { printf("Company %s:\n", $company->id); foreach ($company->getObjectProperties() as $name => $value) { $expression = $company->getPropertyExpression($name); printf(" ->%'.-10s = \"%s\" -- %s\n", $name.' ', $value, $expression); } }
Это работает с DOMObjectCollection и DOMValueObject , определяя ваш собственный тип:
class Companies extends DOMValueCollection { public function __construct(DOMDocument $doc) { parent::__construct($doc, '//*[@class="company"]'); } /** * @return DOMValueObject */ public function current() { $object = parent::current(); $object->defineProperty('id', 'string(@id)'); $object->defineProperty('name', './/a[1]/text()'); $object->defineProperty('href', './/a[1]/@href'); $object->defineProperty('img', './/img[1]/@src'); $object->defineProperty('address', './/*[@class="address"]/text()'); # ... add your definitions return $object; } }
И для ваших требований к массиву существует метод getArrayCopy()
:
echo "\nGet Array Copy:\n\n"; print_r($companies->getArrayCopy());
Вывод:
Get Array Copy: Array ( [0] => Array ( [id] => company-6666 [name] => Company Name [href] => /company-name [img] => /graphics/company/logo/listing/123456.jpg?_ts=1365390237 [address] => StreetName 500, 7777 City, County ) )
Чтобы проверить, существует ли узел, убедитесь, что свойство length равно 1 в возвращаемом запросе:
if ($company_name->length == 1) { $object->company_name = trim($company_name->item(0)->nodeValue); }