你得到所有<img>src-attributes的问题基本上是因为你运行
$images = $dom->getElementsByTagName('img');
这表示您想从整个文档中获取所有 <img> 元素。但实际上您只想获取特定表格内的那些图像。至少你现在是这么认为的,但现在让我们直接这样做。您要查找的表格是文档顺序中的第 13 个表格。因此,您现在解决问题的方法是首先获取 <table>,然后从中获取所有 <img> 元素:
$tables = $dom->getElementsByTagName('table');
$table = $tables->item(12); # 13th table in the document
$images = $table->getElementsByTagName('img');
这将已经为您提供了您在问题中要求的图像(src 属性的摘录):
//cdn3.volusion.com/sfvhn.cpdkd/v/vspfiles/photos/SPL12-00BK-1.jpg?1381182668
/v/vspfiles/templates/ammunition/images/clear1x1.gif
/v/vspfiles/templates/ammunition/images/clear1x1.gif
/v/vspfiles/templates/ammunition/images/clear1x1.gif
/v/vspfiles/templates/ammunition/images/clear1x1.gif
/v/vspfiles/templates/ammunition/images/buttons/btn_addtocart_small.gif
/v/vspfiles/templates/ammunition/images/clear1x1.gif
...
显然这会导致一些进一步的问题:
- 图片列表中有大量您不感兴趣的图片。您需要
.jpg 文件,而不是所有那些许多 1 像素 gif 或购物车按钮。
- 表的编号是硬编码的。这不是很稳定,最好是寻找
class="v65-productDisplay" 属性(你甚至已经在你的问题中写了它)。
- 图片 URL 是相对于文档的,所以需要解析。
我现在将首先展示如何解决前两个问题。
似乎getElementsByTagName 即使有用,也不能灵活地满足您的抓取需求。还有一种更好的方法可以从文档中查询元素,那就是xpath (ref)。它是一种查询语言,您可以在其中表达您想要的元素。因此,我们希望特定表中的图像 src 属性是 jpegs。 xpath 查询看起来像这样:
//table[@class="v65-productDisplay"]/tr/td/a/img/@src[contains(., ".jpg")]
这是在DOMXPath 的帮助下运行的,如下所示:
$xpath = new DOMXPath($dom);
$srcQuery = '//table[@class="v65-productDisplay"]/tr/td/a/img/@src[contains(., ".jpg")]';
/** @var DOMAttr $src */
foreach ($xpath->query($srcQuery) as $src) {
echo $src->nodeValue, "\n";
}
现在这已经大大减少了列表的内容,同时也不那么冗长:
//cdn3.volusion.com/sfvhn.cpdkd/v/vspfiles/photos/SPL12-00BK-1.jpg?1381182668
//cdn3.volusion.com/sfvhn.cpdkd/v/vspfiles/photos/GTL1275-1.jpg?1380206953
//cdn3.volusion.com/sfvhn.cpdkd/v/vspfiles/photos/SS12L8-1.jpg?1390326206
//cdn3.volusion.com/sfvhn.cpdkd/v/vspfiles/photos/LEF127RS-1.jpg?1368458526
//cdn3.volusion.com/sfvhn.cpdkd/v/vspfiles/photos/LE13300-1.jpg?1368458467
//cdn3.volusion.com/sfvhn.cpdkd/v/vspfiles/photos/ADLE13300AC-1.jpg?1393516003
...
所以现在只剩下清理 URI 的问题了,即解析文档 URI(因为文档中没有进一步的基本 URI)并且可能清理查询字符串。我是在Net_URL2 的帮助下完成的,这里单独处理 src:
/** @var DOMAttr $src */
foreach ($xpath->query($srcQuery) as $src) {
$href = $uri->resolve($src->nodeValue);
$href->setQuery(false);
echo $href, "\n";
}
这是一个完整的例子:
<?php
/*
* @link http://stackoverflow.com/questions/24344420/scraping-within-a-table-using-php-dom
* @auhtor hakre <http://hakre.wordpress.com>
*/
# uses Net_URL2 -- http://pear.php.net/package/Net_URL2/ -- https://packagist.org/packages/pear/net_url2
require __DIR__ . '/vendor/autoload.php';
$uri = new Net_URL2('http://www.ammunitiondepot.com/12-Gauge-Shotgun-Ammo-s/1922.htm');
$cache = '12-Gauge-Shotgun-Ammo-s-1922.htm';
if (is_readable($cache)) {
$html = file_get_contents($cache);
} else {
$options = [
'http' => [
'user_agent' => "Godzilla/42.4 (Gabba Gandalf Client 7.3; C128; Z80) Lord of the Table Weed Edition (KHTML, like Gold Dust Day Gecko) Chrome/97.0.43043.0 Safari/1337.42",
'max_redirects' => 1, # do not follow redirects
]
];
$context = stream_context_create($options);
$html = file_get_contents($uri, null, $context);
file_put_contents($cache, $html);
}
$dom = new domDocument;
$dom->preserveWhiteSpace = false;
$save = libxml_use_internal_errors(true);
$dom->loadHTML($html);
libxml_use_internal_errors($save);
$dom->documentURI = $uri;
$xpath = new DOMXPath($dom);
$srcQuery = '//table[@class="v65-productDisplay"]/tr/td/a/img/@src[contains(., ".jpg")]';
/** @var DOMAttr $src */
foreach ($xpath->query($srcQuery) as $src) {
$href = $uri->resolve($src->nodeValue);
$href->setQuery(false);
echo $href, "\n";
}
这里是 HTML 供将来参考:http://pastebin.com/HCTTRm9E