在本文里,我们需要稍微修改之前的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或任何软件并发送大量电子邮件。
到目前为止,我们的脚本只能够从一个网页提取电子邮件。要提取大量电子邮件,我们的脚本需要能够抓取整个网站的信息。这将在下一章讨论。