PHP网络蜘蛛爬行网页提取Email地址脚本(3)

网站分页爬行

在这文章里,我将展示如何进一步修改我们的电子邮址提取脚本,注入爬行能力,并收集尽可能最多的电子邮址。

诀窍很简单 - 我们不要爬行整个网站并检查每个网页。这样做会消耗大量的带宽和时间。我们只需要抓取网页有针对性的电子邮件列表,因此,只要我们知道总页数,然后循环从第一页到最后一页就可完成任务了!

首先,检查目标网站的分页。在这个例子中,它有页面1,2,3,...和“Last”页面按钮。按下此钮将带我们到最后一页,第169页。每个页面有10个电子邮件地址,所以从这个网站可以得到将近1690电子邮址。页面总数(目前为169)将来是可以改变的。如果我们想重用我们的电子邮件提取脚本,它必须能够自动检测总页数。

目标网站的分页

现在我们来看看这个分页的源文件。

分页的源文件

 我们提取电子邮址之前,我们需要解析最后一页的页码。这是 httpcurl.php代码。

<?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>~');
define('LASTPAGE', '~<li class="pager-last last"><a href="/negotiators\?page=(.*?)"~');
define('PARSE_CONTENT', TRUE);
 
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, $status = FALSE) {
		$this->request($url);	
		if ($status === TRUE) {
			return $this->runParser($this->_body, $this->getStatus()); 
		}		
    }
  
    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);      
    }
  
    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);
        }
    } 
}
  
?>

 

首先,我添加了两个定义:

define('LASTPAGE', '~<li class="pager-last last"><a href="/negotiators\?page=(.*?)"~');
define('PARSE_CONTENT', TRUE);

 LASTPAGE从URL解析最后一页数。请注意,有一个"?"在URL中,所以我们需要"\?"对其进行转义。

PARSE_CONTENT告诉函数 get()是否要执行runParser()。 $status默认设置为“FALSE”,只执行函数request()。如果把PARSE_CONTENT传递给$status,那么函数get()将另外执行runParser(),在网页中提取电子邮址,姓名及联络电话号码列表。

    public function get($url, $status = FALSE) {
		$this->request($url);	
		if ($status === TRUE) {
			return $this->runParser($this->_body, $this->getStatus()); 
		}		
    }

 

test.php也有修改。

<?php
include 'httpcurl.php';
   
$target = "http://《网站域名》/negotiators?page=";
$startPage = $target . "1";
$scrapeContent = new Scraper;
$firstPage = new HttpCurl();
$firstPage->get($startPage);
if ($firstPage->getStatus() === 200) {
	$lastPage = $scrapeContent->matchPattern(LASTPAGE, $firstPage->getBody(), 1);
}
$pages = new HttpCurl($scrapeContent);
for($i=1; $i <= $lastPage; $i++) { 
	$targetPage = $target . $i;
	$pages->get($targetPage, PARSE_CONTENT);
}
  
?>

 首先,共有169页的房地产代理信息。每个页面的结构

<domain的目标website>/negotiators?page= 1,2,3,4, 至页169。因此,我们可以创建一个循环$target.$i。为了得到第一个页面,$startPage = $target . 1, 就是

<domain的目标website>/negotiators?page= 1。

我们实例化两个对象

$scrapeContent = new Scraper;
$firstPage = new HttpCurl();

 当我们读取第一页配合模式“LASTPAGE”,我们得到169号返回$lastpage。有了这个信息,我们可以创建循环.

for($i=1; $i <= $lastPage; $i++)

 现在,我们实例化另一个对象$pages,循环每一个页面直到最后一页。我提取到1687个电子邮件地址及相关信息。现在是时候管理大量数据。

接下来,我们需要将这些信息存储到MySQL。我们可以从众多的网站收集高达几十万电子邮件地址,并将它们存储到MySQL。我们也可以存储CSV格式文件及导入电子邮件管理软件。然后发出海量邮件至我们的目标。这将在第4部分讨论。

最后修改于 星期四, 03 11月 2016 06:30
给本项目评分
(0 得票数)
返回顶部