
在本文里,我们需要稍微修改之前的PHP Email地址提取脚本。
首先,我们看回该网页的源文件,可以看到有重复块代理联系人的姓名,电子邮件和电话号码。每页有10块。
我们的策略是使用脚本“切出”每一块资料,然后存储到数组,再提取每块资料里的姓名,电子邮件和电话号码。
正如您看到的,每块以标签<div class="negotiators-wrapper">开头及以</ div></ div>结束。请注意,在这个例子中的回车和新换行分隔</ div>标记。

这个例子的代码:
<?php
define('TARGET_BLOCK','~<div class="negotiators-wrapper">(.*?)</div>(\r\n)</div>~s');
define('NAME', '~<div class="negotiators-name"><a href="/negotiator/(.*?)">(.*?)</a></div>~');
define('EMAIL', '~<div class="negotiators-email">(.*?)</div>~');
define('PHONE', '~<div class="negotiators-phone">(.*?)</div>~');
interface HttpScraper
{
public function parse($body, $head);
}
class Scraper implements HttpScraper
{
public function parse($body, $head) {
if ($head == 200) {
$p = preg_match_all(TARGET_BLOCK, $body, $blocks);
if ($p) {
foreach($blocks[0] as $block) {
$agent[name] = $this->matchPattern(NAME, $block, 2);
$agent[email] = $this->matchPattern(EMAIL, $block, 1);
$agent[phone] = $this->matchPattern(PHONE, $block, 1);
echo "<pre>"; print_r($agent); echo "</pre>";
}
}
}
}
public function matchPattern($pattern, $content, $pos) {
if (preg_match($pattern, $content, $match)) {
return $match[$pos];
}
}
}
class HttpCurl {
protected $_cookie, $_parser, $_timeout;
private $_ch, $_info, $_body, $_error;
public function __construct($p = null) {
if (!function_exists('curl_init')) {
throw new Exception('cURL not enabled!');
}
$this->setParser($p);
}
public function get($url) {
return $this->request($url);
}
protected function request($url) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_URL, $url);
$this->_body = curl_exec($ch);
$this->_info = curl_getinfo($ch);
$this->_error = curl_error($ch);
curl_close($ch);
$this->runParser($this->_body, $this->getStatus());
}
public function getStatus() {
return $this->_info[http_code];
}
public function getHeader() {
return $this->_info;
}
public function getBody() {
return $this->_body;
}
public function __destruct() {
}
public function setParser($p) {
if ($p === null || $p instanceof HttpScraper || is_callable($p))
$this->_parser = $p;
}
public function runParser($content, $header) {
if ($this->_parser !== null)
{
if ($this->_parser instanceof HttpScraper)
$this->_parser->parse($content, $header);
else
call_user_func($this->_parser, $content, $header);
}
}
}
?>
如何操作:
首先,我定义TARGET_BLOCK为前面所讨论重复块。
define('TARGET_BLOCK','~<div class="negotiators-wrapper">(.*?)</div>(\r\n)</div>~s');
当运行在Window7的XAMPP,回车和新行\ r \ n顺利匹配。此外,正则表达式“S”修饰符用于模式匹配多线代码。
要提取姓名,我定义 NAME为
define('NAME', '~<div class="negotiators-name"><a href="/negotiator/(.*?)">(.*?)</a></div>~');
需要注意的是前面有个一个URL“>(姓名)</ a></ div>。网址在每块是不同的。preg_match()函数将匹配两个组数据,首先是URL部分的信息,和第二组的目标姓名。在这种情况下,我们将忽略的URL信息。
获得电子邮件和电话号码会比较直接。
define('EMAIL', '~<div class="negotiators-email">(.*?)</div>~');
define('PHONE', '~<div class="negotiators-phone">(.*?)</div>~');
Scraper类只是有一些小改变:
class Scraper implements HttpScraper
{
public function parse($body, $head) {
if ($head == 200) {
$p = preg_match_all(TARGET_BLOCK, $body, $blocks);
if ($p) {
foreach($blocks[0] as $block) {
$agent[name] = $this->matchPattern(NAME, $block, 2);
$agent[email] = $this->matchPattern(EMAIL, $block, 1);
$agent[phone] = $this->matchPattern(PHONE, $block, 1);
echo "<pre>"; print_r($agent); echo "</pre>";
}
}
}
}
public function matchPattern($pattern, $content, $pos) {
if (preg_match($pattern, $content, $match)) {
return $match[$pos];
}
}
}
首先,函数parse()匹配及把资料块复制到阵列,然后我们从中提取姓名,电子邮件和电话号码。其余的代码保持不变。
在本文中,我们运行test.php,并打印出结果:

行了!
现在可以写给您的目标一个更加个性化的电子邮件。您可以使用电子邮件管理软件等ListMailPro或任何软件并发送大量电子邮件。
到目前为止,我们的脚本只能够从一个网页提取电子邮件。要提取大量电子邮件,我们的脚本需要能够抓取整个网站的信息。这将在下一章讨论。

