一、介绍
Goutte 库非常有用,它可以为您提供有关如何使用 PHP 抓取内容的出色支持。
基于 Symfony 框架,它提供了 API 来抓取网站并从 HTML / XML响应中抓取数据,它是免费开源的。
基于 OOP 的编程思想,非常适合大型项目的爬虫,同时它有着还不错的解析速度。
它需要 php 满足 5.5+。
Goutte:支持 JavaScript,支持 Cookie
二、安装
通过 composer 安装
composer require fabpot/goutte
三、例子
3.1、简单例子
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'http://www.baidu.com/');
$crawler->filter('a')->each(function ($node) {
print $node->attr('href');
});
该实例访问百度首页,获取所有链接的地址并输出。首先我们创建了一个 Client 实例,然后使用 request 方法获取百度首页 HTML 内容,接着使用 filter 方法选择 DOM 节点,并使用 each 方法进行循环处理每个节点。
3.2、获取页面内容
通过 Goutte 可以获取网页的所有内容,如标题、Meta 标签、CSS 样式、JavaScript 脚本等。
下面是一个实例:
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'https://www.sina.com.cn/');
$title = $crawler->filterXPath('//title')->text();
$meta = $crawler->filterXPath('//meta[@name="description"]')->attr('content');
$css = $crawler->filterXPath('//link[@rel="stylesheet"]')->attr('href');
$script = $crawler->filterXPath('//script[@src]')->attr('src');
echo "title: ".$title;
echo "meta_description: ".$meta;
echo "css: ".$css;
echo "script: ".$script;
上述实例获取了新浪网首页的标题、Meta 标签中的 description、CSS 样式文件和 JavaScript 脚本文件,并输出到控制台中。
3.3、表单提交
在某些情况下,我们需要模拟用户登录并提交表单来获取目标数据。
Goutte 可以通过类似用户行为的方式提交表单。
下面是一个实例:
use Symfony\Component\DomCrawler\Form;
$client = new Client();
$crawler = $client->request('GET', 'http://localhost/login.php');
$form = $crawler->selectButton('login')->form();
$form['username'] = 'admin';
$form['password'] = '123456';
$crawler = $client->submit($form);
echo $crawler->filterXPath('//div[@class="alert alert-success"]')->text();
该实例模拟用户通过 POST 方式提交了用户名和密码,登录了本地服务器的一个测试站点,并获取了登录后的页面内容。
3.4、AJAX 请求
现如今,越来越多的网页采用了 AJAX 的技术,动态更新数据。
Goutte 同样也支持模拟 AJAX 请求并抓取返回的结果。
下面是一个实例:
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'https://www.taobao.com/');
$ajax_url = $crawler->filterXPath('//a[@data-ajax]');
$response = $client->request('GET', $ajax_url->attr('href'));
echo $response->filterXPath('//title')->text();
该实例获取了淘宝首页中带 data-ajax 属性的链接地址,并使用 Goutte 进行 AJAX 请求,并输出返回的页面标题。
3.5、登录并抓取数据
在某些情况下,我们需要先登录才能抓取到目标数据。
下面是一个实例:
use Goutte\Client;
$client = new Client();
// login first
$crawler = $client->request('GET', 'http://localhost/login.php');
$form = $crawler->selectButton('login')->form();
$form['username'] = 'admin';
$form['password'] = '123456';
$crawler = $client->submit($form);
// then visit the page you want
$crawler = $client->request('GET', 'http://localhost/data.php');
echo $crawler->filterXPath('//table')->text();
该实例先模拟用户登录操作,然后再访问数据页面,并输出数据表格内容。
3.6、获取表格内容
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'http://www.example.com/table.html');
$tableRows = $crawler->filter('table tr')->each(function ($row) {
return $row->filter('td')->each(function ($cell) {
return $cell->text();
});
});
var_dump($tableRows);
3.7、处理 JavaScript 渲染的内容
use Goutte\Client;
use Symfony\Component\DomCrawler\Crawler;
$client = new Client();
$crawler = $client->request('GET', 'http://www.example.com');
// 等待JavaScript加载完成
$client->wait(5000, "document.readyState === 'complete'");
// 使用Crawler对象解析JavaScript渲染后的HTML内容
$javascriptRenderedHtml = $client->executeScript('return document.documentElement.outerHTML;');
$crawler = new Crawler($javascriptRenderedHtml);
$crawler->filter('h1')->each(function ($node) {
echo $node->text()."\n";
});
3.8、使用代理访问网页
use Goutte\Client;
$client = new Client();
// 设置代理服务器
$client->setProxy('http://proxy.example.com:8080');
// 访问需要使用代理的页面
$crawler = $client->request('GET', 'http://www.example.com');
$crawler->filter('h1')->each(function ($node) {
echo $node->text()."\n";
});
3.9、处理 XML 数据
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'http://www.example.com/xml');
$xml = simplexml_load_string($crawler->html());
foreach ($xml->item as $item) {
echo $item->title."\n";
echo $item->description."\n";
}
3.10、获取多个页面的数据
use Goutte\Client;
$client = new Client();
$urls = [
'http://www.example.com/page1',
'http://www.example.com/page2',
'http://www.example.com/page3',
];
foreach ($urls as $url) {
$crawler = $client->request('GET', $url);
$crawler->filter('h1')->each(function ($node) {
echo $node->text()."\n";
});
}
3.11、使用 cookie 访问网页
use Goutte\Client;
$client = new Client();
// 设置cookie
$client->getCookieJar()->set(new \Symfony\Component\BrowserKit\Cookie('session_id', '123'));
$crawler = $client->request('GET', 'http://www.example.com');
$crawler->filter('h1')->each(function ($node) {
echo $node->text()."\n";
});
3.12、处理AJAX响应
use Goutte\Client;
$client = new Client();
$client->request('GET', 'http://www.example.com');
// 发送异步请求获取数据
$response = $client->getClient()->request('POST', 'http://www.example.com/ajax', [
'headers' => ['X-Requested-With' => 'XMLHttpRequest'],
'json' => ['key' => 'value'],
]);
// 处理响应
$data = json_decode($response->getBody(), true);
echo $data['name']."\n";
echo $data['age']."\n";
3.13、从 JSON 数据中获取内容
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'http://www.example.com/api');
$jsonData = json_decode($crawler->html());
foreach ($jsonData as $item) {
echo $item->name."\n";
echo $item->age."\n";
}
3.14、使用队列爬取网页
use Goutte\Client;
use Symfony\Component\DomCrawler\Link;
$client = new Client();
$queue = new \SplQueue();
$queue->enqueue('http://www.example.com/');
while (!$queue->isEmpty()) {
$url = $queue->dequeue();
$crawler = $client->request('GET', $url);
$crawler->filter('a')->each(function (Link $link) use ($queue) {
$url = $link->getUri();
if (strpos($url, 'http://www.example.com/') === 0) {
$queue->enqueue($url);
}
});
$crawler->filter('h1')->each(function ($node) {
echo $node->text()."\n";
});
}
3.15、处理下载文件
use Goutte\Client;
$client = new Client();
// 访问包含文件下载链接的页面
$crawler = $client->request('GET', 'http://www.example.com/files');
// 获取下载链接并下载文件
$link = $crawler->filter('a')->eq(0)->link();
$fileContent = $client->click($link)->getContent();
// 写入文件
file_put_contents('/path/to/downloaded/file', $fileContent);
3.16、获取图片链接并下载图片
use Goutte\Client;
$client = new Client();
$crawler = $client->request('GET', 'http://www.example.com/images');
// 获取图片链接并下载图片
$crawler->filter('img')->each(function ($image) use ($client) {
$imageUrl = $image->attr('src');
$imageContent = $client->request('GET', $imageUrl)->getContent();
// 写入文件
file_put_contents('/path/to/downloaded/image.jpg', $imageContent);
});
3.17、关闭自动重定向
use Goutte\Client;
$client = new Client(['allow_redirects' => false]);
$crawler = $client->request('GET', 'http://www.example.com');
if ($client->getResponse()->getStatusCode() == 301) {
$redirectUrl = $client->getResponse()->getHeader('location')[0];
$crawler = $client->request('GET', $redirectUrl);
}
$crawler->filter('h1')->each(function ($node) {
echo $node->text()."\n";
});