awanesia /
PHP 的一个网页抓取器,用于轻松从网页中提取数据 -> laurentvw 的一部分
Requires
- php: >=5.3.0
This package is not auto-updated.
Last update: 2024-09-29 09:44:09 UTC
README
Scrapher 是一个 PHP 库,用于轻松从网页中抓取数据。
入门
安装
将包添加到您的 composer.json
中并运行 composer update
。
{
"require": {
"laurentvw/scrapher": "2.*"
}
}
对于仍在使用 v1.0 ("LavaCrawler") 的人,您可以在以下位置找到文档: https://github.com/Laurentvw/scrapher/tree/v1.0.2
基本用法
为了开始抓取,您需要设置要抓取的 URL(s) 或 HTML,以及要使用的选择器类型(例如正则表达式选择器,以及您希望匹配的数据)。
use \Laurentvw\Scrapher\Scrapher; use \Laurentvw\Scrapher\Selectors\RegexSelector; $url = 'https://www.google.com/'; $scrapher = new Scrapher($url); // Match all links on a page $regex = '/<a.*?href=(?:"(.*?)").*?>(.*?)<\/a>/ms'; $matchConfig = array( array( 'name' => 'url', 'id' => 1, // the first match (.*?) from the regex ), array( 'name' => 'title', 'id' => 2, // the second match (.*?) from the regex ), ); $matches = $scrapher->with(new RegexSelector($regex, $matchConfig)); $results = $matches->get();
这将返回一个基于设置的匹配配置的数组列表。
array(29) {
[0] =>
array(2) {
'url' =>
string(34) "https://www.google.com/webhp?tab=ww"
'title' =>
string(6) "Search"
}
...
}
文档
实例化
当创建 Scrapher 实例时,您可以可选地传递一个或多个 URL。
传递多个 URL 在您想要在不同页面上抓取相同数据时很有用。例如,当内容通过分页分开时。
$scrapher = new Scrapher($url); $scrapher = new Scrapher(array($url, $url2));
如果您更喜欢使用专门的客户端/库自行抓取页面,您也可以简单地传递页面的实际内容。如果您想抓取除网页之外的其他内容(例如本地文件),这也很方便。
$scrapher = new Scrapher($content); $scrapher = new Scrapher(array($content, $content2));
在某些情况下,您可能需要在运行时动态添加(即附加)URL 或内容。
$scrapher->addUrl($url); $scrapher->addUrls(array($url, $url2)); $scrapher->addContent($content); $scrapher->addContents(array($content, $content2));
使用选择器匹配数据
在检索或排序匹配的数据之前,您需要选择一个选择器来匹配您想要的数据。
目前,Scrapher 提供了一个内置选择器 RegexSelector,它允许您使用正则表达式选择数据。
选择器接受一个表达式和一个匹配配置作为其参数。
例如,要匹配所有链接及其链接名称,您可以这样做
$regExpression = '/<a.*?href=(?:"(.*?)").*?>(.*?)<\/a>/ms'; $matchConfig = array( array( // The "name" key let's you name the data you're looking for, // and will be used when retrieving the matched data 'name' => 'url', // The "id" key is an identifier used during the regular expression search. // The id 1 corresponds to the first match in the regular expression, matching the URL. 'id' => 1, ), array( 'name' => 'title', 'id' => 2, ), ); $matches = $scrapher->with(new RegexSelector($regExpression, $matchConfig));
请注意,传递给 "id" 键的值可能因您使用的选择器而异,实际上可以是任何东西。您可以将 "id" 键视为给定表达式与其选择器之间的粘合剂。
RegexSelector 在内部使用 https://php.ac.cn/manual/en/function.preg-match-all.php。
为了方便起见,当使用正则表达式时,带有 'id' => 0
的匹配将返回被爬取页面的 URL。
检索 & 排序
一旦您使用 with 方法指定了选择器,您就可以开始检索和/或排序数据。
检索
// Return all matches $results = $matches->get(); // Return all matches with a subset of the data (either use multiple arguments or an array for more than one column) $results = $matches->get('title'); // Return the first match $result = $matches->first(); // Return the last match $result = $matches->last(); // Count the number of matches $numberOfMatches = $matches->count();
偏移量 & 限制
// Take the first N matches $results = $matches->take(5)->get(); // Skip the first N matches $results = $matches->skip(1)->get(); // Take 5 matches starting from the second one. $results = $matches->skip(1)->take(5)->get();
排序
// Order by title $results = $matches->orderBy('title')->get(); // Order by title, then by URL $results = $matches->orderBy('title')->orderBy('url', 'desc')->get(); // Custom sorting: For values that do not lend well with sorting, e.g. dates*. $results = $matches->orderBy('date', 'desc', 'date_create')->get(); // Simply reverse the order of the results $results = $matches->reverse()->get();
过滤
您可以对匹配的数据进行过滤,以细化您的结果集。返回 true
以保留匹配项,返回 false
以过滤它。
$matches->filter(function($match) { // Return only matches that contain 'Google' in the link title. return stristr($match['title'], 'Google') ? true : false; });
变异
为了处理不一致性或格式问题,您可以将匹配的值更改为更理想的值。变异发生在过滤和排序结果集之前。您可以通过在匹配配置数组中使用带有 2 个参数的闭包的 apply
索引来完成此操作:匹配的值和被爬取页面的 URL。
$matchConfig = array( array( 'name' => 'url', 'id' => 1, // Add domain to relative URLs 'apply' => function($match, $sourceUrl) { if (!stristr($match, 'http')) { return $sourceUrl . trim($match, '/'); } return $match; }, ), array( 'name' => 'title', 'id' => 2, // Remove all html tags inside the link title 'apply' => function($match) { return strip_tags($match); }, ), ... );
验证
您可以通过验证匹配的数据来确保结果集始终包含所需的结果。验证发生在可选地使用 apply
修改数据集之后。要添加应用于数据的验证规则,请使用匹配配置数组中的 validate
索引,并传递一个接受两个参数的闭包:匹配的值和爬取的网页的URL。如果验证成功,闭包应返回 true
;如果验证失败,返回 false
。验证失败的匹配将从中移除。
$matchConfig = array( array( 'name' => 'url', 'id' => 1, // Make sure it is a valid url 'validate' => function($match) { return filter_var($match, FILTER_VALIDATE_URL); }, ), array( 'name' => 'title', 'id' => 2, // We only want titles that are between 1 and 50 characters long. 'validate' => function($match) { return strlen($match) >= 1 && strlen($match) <= 50; }, ), ... );
- 为了简化验证,我们建议在您的项目中使用 https://github.com/Respect/Validation。
日志记录
如果您想查看被过滤掉的匹配项或由于验证失败而被移除的匹配项,可以使用 getLogs
方法,该方法返回一个包含消息日志的数组。
$logs = $matches->getLogs();
你知道吗?
所有方法都是可链式的
$scrapher = new Scrapher(); $scrapher->addUrl($url)->with($regexSelector)->filter(...)->orderBy('title')->skip(1)->take(5)->get();
只有 get
、first
、last
、count
和 getLogs
方法会导致链式调用结束,因为它们都返回一个特定的结果。
您可以从一个页面抓取不同的数据
假设您正在抓取一个页面,并想获取所有H2标题以及页面上的所有链接。您可以通过不重新实例化Scrapher来实现这一点。
$scrapher = new Scrapher($url); $h2Titles = $scrapher->with($h2RegexSelector)->get(); $links = $scrapher->with($linksRegexSelector)->get();
关于
作者
Laurent Van Winckel - http://www.laurentvw.com - http://twitter.com/Laurentvw
许可协议
Scrapher遵循MIT许可协议 - 详细信息请参阅LICENSE
文件。
贡献
我们欢迎对Laurentvw\Scrapher的贡献。通过通过 GitHub pull requests 发送您的贡献,您会使我们的工作变得更轻松。
您还可以 创建一个issue 来报告错误或请求新功能。