合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
[PHP: DOMXPath - Manual](https://www.php.net/manual/zh/class.domxpath.php) ``` <?php // 1. 获取页面HTML内容 $url = 'https://example.com'; // 目标页面地址 $html = file_get_contents($url); // 简单获取方式(适用于不需要鉴权的页面) // 或使用cURL获取(推荐): /* $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0'); $html = curl_exec($ch); curl_close($ch); */ // 2. 创建DOM解析对象 $dom = new DOMDocument(); libxml_use_internal_errors(true); // 禁用错误报告(处理不规范的HTML) $dom->loadHTML($html); libxml_clear_errors(); // 3. 创建XPath解析器 $xpath = new DOMXPath($dom); // 4. 定义XPath表达式(示例) $targetXpath = '//h1[@class="title"]'; // 提取class为title的h1标签 // 5. 执行XPath查询 $nodes = $xpath->query($targetXpath); // 6. 处理查询结果 $result = []; if ($nodes->length > 0) { foreach ($nodes as $node) { // 提取文本内容 $result[] = trim($node->nodeValue); // 如果需要提取属性(示例): // $class = $node->getAttribute('class'); // $result[] = ['text' => trim($node->nodeValue), 'class' => $class]; } } else { // 没有匹配内容时的处理 $result = ['error' => '未找到匹配内容']; } // 7. 输出结果 print_r($result); // 8. 清理内存 unset($dom, $xpath); ?> ``` **获取HTML的三种方式**: * `file_get_contents()`:简单快速,适合静态页面 * cURL扩展:推荐方式,支持: ``` curl_setopt($ch, CURLOPT_PROXY, 'IP:PORT'); // 设置代理 curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt'); // 保持会话 curl_setopt($ch, CURLOPT_TIMEOUT, 15); // 超时设置 ``` * GuzzleHTTP客户端(需要安装):适合复杂需求 ``` composer require guzzlehttp/guzzle ``` **XPath编写技巧** ``` //div[@id="main"]/ul/li/a # 多层结构定位 //meta[@property="og:title"]/@content # 获取属性值 //a[contains(@class, "btn")] # 模糊匹配class //*[starts-with(text(), "Hello")] # 文本前缀匹配 ``` **常见问题处理** **XPath匹配不到内容** 1. 验证XPath有效性: ~~~ // 调试输出整个DOM结构 echo $dom->saveHTML(); ~~~ 2. 处理动态加载内容: ~~~ // 使用浏览器自动化工具 composer require facebook/webdriver ~~~ 3. 处理iframe嵌套: ~~~ // 需要单独处理iframe内容 $iframeNodes = $xpath->query('//iframe'); foreach ($iframeNodes as $iframe) { $iframeUrl = $iframe->getAttribute('src'); // 单独处理iframe内容 } ~~~ **中文乱码** * 解决方案: ~~~ // 转换编码(处理GBK页面) $html = mb_convert_encoding($html, 'HTML-ENTITIES', 'GB2312'); ~~~ **需要处理JavaScript渲染** 解决方案: 使用无头浏览器方案: ``` composer require chrome-php/chrome use HeadlessChromium\BrowserFactory; $browserFactory = new BrowserFactory(); $browser = $browserFactory->createBrowser(); $page = $browser->createPage(); $page->navigate($url)->waitForNavigation(); $html = $page->evaluate('document.documentElement.outerHTML')->getReturnValue(); ``` ### 高级功能扩展 1. **结果缓存机制**: ~~~ $cacheFile = md5($url).'.cache'; if (file_exists($cacheFile) && time()-filemtime($cacheFile) < 3600) { return json_decode(file_get_contents($cacheFile), true); } // ...执行采集... file_put_contents($cacheFile, json_encode($result)); ~~~ 2. **自动重试机制**: ~~~ $retry = 3; while ($retry > 0) { try { // 执行采集代码 break; } catch (Exception $e) { $retry--; sleep(5); } } ~~~ 3. **分布式采集**: ~~~ // 使用Redis队列 $redis = new Redis(); $redis->connect('127.0.0.1', 6379); while ($url = $redis->rpop('url_queue')) { // 执行采集任务 // 存储结果到数据库 } ~~~ ### 性能优化建议 1. **启用缓存**: * 使用Memcached缓存DOM解析结果 ~~~ $memcached = new Memcached(); $memcached->addServer('localhost', 11211); $cacheKey = 'page_'.md5($url); if ($cached = $memcached->get($cacheKey)) { $dom->loadHTML($cached); } else { // 解析并存储 $memcached->set($cacheKey, $html, 3600); } ~~~ 2. **并行处理**: ~~~ // 使用多进程 $urls = ['url1', 'url2', 'url3']; $pool = new Pool(3); // 3个线程 foreach ($urls as $url) { $pool->submit(new class($url) extends Thread { public function __construct($url) { $this->url = $url; } public function run() { // 执行采集逻辑 } }); } $pool->shutdown(); ~~~ 3. **DNS预解析**: ~~~ // 在采集前解析所有域名 dns_get_record('example.com', DNS_A); ~~~ 通过以上方法,您可以构建一个健壮的网页内容采集系统,能够应对各种复杂的网页结构和采集需求。