当前位置: 代码迷 >> PHP >> php爬虫抓取信息及反爬虫相干
  详细解决方案

php爬虫抓取信息及反爬虫相干

热度:102   发布时间:2016-04-28 17:21:26.0
php爬虫抓取信息及反爬虫相关
58爬虫了百姓,赶集和58互爬,最后各种信息相同,都是爬虫后的数据库调用,潜规则啊,几家独大还暗中各种攻击,赶驴网的幽默事例我不想多评价。这个时代是砸.钱*养.钱的时代,各种姚晨杨幂葛优,各种地铁公车广告,各种卫视广告,铺天盖地~~~
来谈php爬虫抓取信息~~
php爬虫首推Curl函数了,先来认识下它。
0x01.curl扩展的安装:
1.确保php子文件夹ext里面有php_curl.dll(一般都有的,一般配置时候会设置环境变量的)
2.将php.ini里面的;extension=php_curl.dll反注释为extension=php_curl.dll
3.重启apache完了。
4.如果还不行,把php5/libeay32.dll,ssleay32.dll复制到系统目录windows/下,这2个dll的描述是OpenSSL Shared Library。

否则会出现
Fatal error: Call to undefined function curl_init() in XX:\XX\XX\XX.php on line 3?
这样未定义,找不到库的错误,大家懂的。

0x02.先来熟悉下curl再去采集抓取,信息时代,大爆炸,爬虫个信息不是难事。顺便测试登陆,COOKIE。

PHP中的CURL函数库(Client URL Library Function)是个强大的库。

curl_close — 关闭一个curl会话
curl_copy_handle — 拷贝一个curl连接资源的所有内容和参数
curl_errno — 返回一个包含当前会话错误信息的数字编号
curl_error — 返回一个包含当前会话错误信息的字符串
curl_exec — 执行一个curl会话
curl_getinfo — 获取一个curl连接资源句柄的信息
curl_init — 初始化一个curl会话
curl_multi_add_handle — 向curl批处理会话中添加单独的curl句柄资源
curl_multi_close — 关闭一个批处理句柄资源
curl_multi_exec — 解析一个curl批处理句柄
curl_multi_getcontent — 返回获取的输出的文本流
curl_multi_info_read — 获取当前解析的curl的相关传输信息
curl_multi_init — 初始化一个curl批处理句柄资源
curl_multi_remove_handle — 移除curl批处理句柄资源中的某个句柄资源
curl_multi_select — Get all the sockets associated with the cURL extension, which can then be "selected"
curl_setopt_array — 以数组的形式为一个curl设置会话参数
curl_setopt — 为一个curl设置会话参数
curl_version — 获取curl相关的版本信息

curl_init()函数的作用初始化一个curl会话,curl_init()函数唯一的一个参数是可选的,表示一个url地址。
curl_exec()函数的作用是执行一个curl会话,唯一的参数是curl_init()函数返回的句柄。
curl_close()函数的作用是关闭一个curl会话,唯一的参数是curl_init()函数返回的句柄。

简单实例:
<?php
$url = "http://yxmhero1989.blog.163.com/";//不建议爬大型网站,一般都有反爬虫机制,被封了IP别怪我~~
$ch = curl_init($url);//初始curl会话
$fp = fopen("homepage.txt", "w");//这里是把抓取的网页内容写入一个txt文件,下面会告诉你操作数据库。
curl_setopt($ch, CURLOPT_FILE, $fp);//为一个curl设置会话参数
curl_setopt($ch, CURLOPT_HEADER, 0);//设置header
curl_exec($ch);//执行curl会话
curl_close($ch);//关闭curl会话
fclose($fp);
?> 

0x03.关于CURL_SETOPT()函数的设置

bool curl_setopt (int ch, string option, mixed value)

curl_setopt()函数将为一个CURL会话设置选项。option参数是你想要的设置,value是这个选项给定的值。

下列选项的值将被作为长整形使用(在option参数中指定):

* CURLOPT_INFILESIZE: 当你上传一个文件到远程站点,这个选项告诉PHP你上传文件的大小。
* CURLOPT_VERBOSE: 如果你想CURL报告每一件意外的事情,设置这个选项为一个非零值。
* CURLOPT_HEADER: 如果你想把一个头包含在输出中,设置这个选项为一个非零值。
* CURLOPT_NOPROGRESS: 如果你不会PHP为CURL传输显示一个进程条,设置这个选项为一个非零值。注意:PHP自动设置这个选项为非零值,你应该仅仅为了调试的目的来改变这个选项。
* CURLOPT_NOBODY: 如果你不想在输出中包含body部分,设置这个选项为一个非零值。
* CURLOPT_FAILONERROR: 如果你想让PHP在发生错误(HTTP代码返回大于等于300)时,不显示,设置这个选项为一人非零值。默认行为是返回一个正常页,忽略代码。
* CURLOPT_UPLOAD: 如果你想让PHP为上传做准备,设置这个选项为一个非零值。
* CURLOPT_POST: 如果你想PHP去做一个正规的HTTP POST,设置这个选项为一个非零值。这个POST是普通的 application/x-www-from-urlencoded 类型,多数被HTML表单使用。
* CURLOPT_FTPLISTONLY: 设置这个选项为非零值,PHP将列出FTP的目录名列表。
* CURLOPT_FTPAPPEND: 设置这个选项为一个非零值,PHP将应用远程文件代替覆盖它。
* CURLOPT_NETRC: 设置这个选项为一个非零值,PHP将在你的 ~./netrc 文件中查找你要建立连接的远程站点的用户名及密码。
* CURLOPT_FOLLOWLOCATION: 设置这个选项为一个非零值(象 “Location: “)的头,服务器会把它当做HTTP头的一部分发送(注意这是递归的,PHP将发送形如 “Location: “的头)。
* CURLOPT_PUT: 设置这个选项为一个非零值去用HTTP上传一个文件。要上传这个文件必须设置CURLOPT_INFILE和CURLOPT_INFILESIZE选项.
* CURLOPT_MUTE: 设置这个选项为一个非零值,PHP对于CURL函数将完全沉默。
* CURLOPT_TIMEOUT: 设置一个长整形数,作为最大延续多少秒。
* CURLOPT_LOW_SPEED_LIMIT: 设置一个长整形数,控制传送多少字节。
* CURLOPT_LOW_SPEED_TIME: 设置一个长整形数,控制多少秒传送CURLOPT_LOW_SPEED_LIMIT规定的字节数。
* CURLOPT_RESUME_FROM: 传递一个包含字节偏移地址的长整形参数,(你想转移到的开始表单)。
* CURLOPT_SSLVERSION: 传递一个包含SSL版本的长参数。默认PHP将被它自己努力的确定,在更多的安全中你必须手工设置。
* CURLOPT_TIMECONDITION: 传递一个长参数,指定怎么处理CURLOPT_TIMEVALUE参数。你可以设置这个参数为TIMECOND_IFMODSINCE 或 TIMECOND_ISUNMODSINCE。这仅用于HTTP。
* CURLOPT_TIMEVALUE: 传递一个从1970-1-1开始到现在的秒数。这个时间将被CURLOPT_TIMEVALUE选项作为指定值使用,或被默认TIMECOND_IFMODSINCE使用。

下列选项的值将被作为字符串:

* CURLOPT_URL: 这是你想用PHP取回的URL地址。你也可以在用curl_init()函数初始化时设置这个选项。
* CURLOPT_USERPWD: 传递一个形如[username]:[password]风格的字符串,作用PHP去连接。
* CURLOPT_PROXYUSERPWD: 传递一个形如[username]:[password] 格式的字符串去连接HTTP代理。
* CURLOPT_RANGE: 传递一个你想指定的范围。它应该是”X-Y”格式,X或Y是被除外的。HTTP传送同样支持几个间隔,用逗句来分隔(X-Y,N-M)。
* CURLOPT_POSTFIELDS: 传递一个作为HTTP “POST”操作的所有数据的字符串。
* CURLOPT_REFERER: 在HTTP请求中包含一个”referer”头的字符串。
* CURLOPT_USERAGENT: 在HTTP请求中包含一个”user-agent”头的字符串。
* CURLOPT_FTPPORT: 传递一个包含被ftp “POST”指令使用的IP地址。这个POST指令告诉远程服务器去连接我们指定的IP地址。这个字符串可以是一个IP地址,一个主机名,一个网络界面名 (在UNIX下),或是‘-’(使用系统默认IP地址)。
* CURLOPT_COOKIE: 传递一个包含HTTP cookie的头连接。
* CURLOPT_SSLCERT: 传递一个包含PEM格式证书的字符串。
* CURLOPT_SSLCERTPASSWD: 传递一个包含使用CURLOPT_SSLCERT证书必需的密码。
* CURLOPT_COOKIEFILE: 传递一个包含cookie数据的文件的名字的字符串。这个cookie文件可以是Netscape格式,或是堆存在文件中的HTTP风格的头。
* CURLOPT_CUSTOMREQUEST: 当进行HTTP请求时,传递一个字符被GET或HEAD使用。为进行DELETE或其它操作是有益的,更Pass a string to be used instead of GET or HEAD when doing an HTTP request. This is useful for doing or another, more obscure, HTTP request. 注意: 在确认你的服务器支持命令先不要去这样做。下列的选项要求一个文件描述(通过使用fopen()函数获得):
* CURLOPT_FILE: 这个文件将是你放置传送的输出文件,默认是STDOUT.
* CURLOPT_INFILE: 这个文件是你传送过来的输入文件。
* CURLOPT_WRITEHEADER: 这个文件写有你输出的头部分。
* CURLOPT_STDERR: 这个文件写有错误而不是stderr。用来获取需要登录的页面的例子,当前做法是每次或许都登录一次,有需要的人再做改进了.

 

PHP实现最简单爬虫原型(话说原作者的正则注释反了,出现错误哈哈)


代码如下
<?php


function _getUrlContent($url){
    $handle = fopen($url, "r");
    if($handle){
        $content = stream_get_contents($handle,1024*1024);
        return $content;
    }else{
        return false;
    }    
}

function _filterUrl($web_content){
    $reg_tag_a = "/<[a|A].*?href=[\'\"]{0,1}([^>\'\"\ ]*).*?>/";
    //$result = preg_match_all($reg_tag_a,$web_content,$match_result);
    $result = preg_match_all("/<meta[^>]*?name=[\'\"]?description[\'\"]?[^>]*?>/is",$web_content,$match_result);
    if($result){
        return $match_result[1];
    }
}


function _reviseUrl($base_url,$url_list){
    $url_info = parse_url($base_url);
    $base_url = $url_info["scheme"].'://';
    if($url_info["user"]&&$url_info["pass"]){
        $base_url .= $url_info["user"].":".$url_info["pass"]."@";
    }
    $base_url .= $url_info["host"];
    if($url_info["port"]){
        $base_url .= ":".$url_info["port"];
    }
    $base_url .= $url_info["path"];
    print_r($base_url);
    if(is_array($url_list)){
        foreach ($url_list as $url_item) {
            if(preg_match('/^http/',$url_item)){
                //已经是完整的url
                $result[] = $url_item;
            }else {
                //不完整的url
                $real_url = $base_url.'/'.$url_item;
                $result[] = $real_url;
            }
        }
        return $result;
    }else {
        return;
    }
}

function crawler($url){
    $content = _getUrlContent($url);
    if($content){
        $url_list = _reviseUrl($url,_filterUrl($content));
        if($url_list){
            return $url_list;
        }else {
            return ;
        }
    }else{
        return ;
    }
}

function main(){
    $current_url = "http://hao123.com/";//初始url
    $fp_puts = fopen("url.txt","ab");//记录url列表
    $fp_gets = fopen("url.txt","r");//保存url列表
    do{
        $result_url_arr = crawler($current_url);
        if($result_url_arr){
            foreach ($result_url_arr as $url) {
                fputs($fp_puts,$url."/r/n");
            }
        }
    }while ($current_url = fgets($fp_gets,1024));//不断获得url
    
}
main();
?>
<input type="text" value="关键字" />
<input type="submit" value="搜索"/>



代码如下
  1. <?php
  2. class CurlComponent{
  3.    var $headers;
  4.    var $user_agent;
  5.    var $compression;
  6.    var $cookie_file;
  7.    var $proxy;
  8.  
  9.    functionset_value($cookies=TRUE,$cookie='cookies.txt',$compression='gzip',$proxy='') {
  10.        $this->headers[] = "Accept: image/gif, image/x-bitmap, image/jpeg, image/pjpeg";
  11.        $this->headers[] = "Connection: Keep-Alive";
  12.        $this->headers[] = "Content-type: application/x-www-form-urlencoded";
  13.        $this->user_agent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0)";
  14.        $this->compression=$compression;
  15.        $this->proxy=$proxy;
  16.        $this->cookies=$cookies;
  17.        if ($this->cookies == TRUE) $this->cookie($cookie);
  18.    }
  19.  
  20.    function cookie($cookie_file) {
  21.        if (file_exists($cookie_file)) {
  22.            $this->cookie_file=$cookie_file;
  23.        } else {
  24.            @fopen($cookie_file,'w')or$this->error("The cookie file could not be opened. Make sure this directory has the correct permissions");
  25.            $this->cookie_file=$cookie_file;
  26.            @fclose($cookie_file);
  27.        }
  28.    }
  29.  
  30.    function get($url,$refer='') {
  31.        $process =curl_init($url);
  32.         curl_setopt($process,CURLOPT_REFERER, $refer);
  33.         curl_setopt($process,CURLOPT_HTTPHEADER, $this->headers);
  34.         curl_setopt($process,CURLOPT_USERAGENT, $this->user_agent);
  35.        if ($this->cookies == TRUE)curl_setopt($process,CURLOPT_COOKIEFILE, $this->cookie_file);
  36.        if ($this->cookies == TRUE)curl_setopt($process,CURLOPT_COOKIEJAR, $this->cookie_file);
  37.         curl_setopt($process,CURLOPT_ENCODING, $this->compression);
  38.         curl_setopt($process,CURLOPT_TIMEOUT, 30000);
  39.        if ($this->proxy)curl_setopt($cUrl,CURLOPT_PROXY, 'proxy_ip:proxy_port');
  40.         curl_setopt($process,CURLOPT_RETURNTRANSFER, 1);
  41.        $return =curl_exec($process);
  42.         curl_close($process);
  43.        return $return;
  44.    }
  45.  
  46.    function post($url,$data,$refer) {
  47.        $process =curl_init($url);
  48.         curl_setopt($process,CURLOPT_REFERER, $refer);
  49.         curl_setopt($process,CURLOPT_HTTPHEADER, $this->headers);
  50.         curl_setopt($process,CURLOPT_USERAGENT, $this->user_agent);
  51.        if ($this->cookies == TRUE)curl_setopt($process,CURLOPT_COOKIEFILE, $this->cookie_file);
  52.        if ($this->cookies == TRUE)curl_setopt($process,CURLOPT_COOKIEJAR, $this->cookie_file);
  53.         curl_setopt($process,CURLOPT_ENCODING, $this->compression);
  54.         curl_setopt($process,CURLOPT_TIMEOUT, 30000);
  55.        if ($this->proxy)curl_setopt($cUrl,CURLOPT_PROXY, 'proxy_ip:proxy_port');
  56.         curl_setopt($process,CURLOPT_POSTFIELDS, $data);
  57.         curl_setopt($process,CURLOPT_RETURNTRANSFER, 1);
  58.         curl_setopt($process,CURLOPT_FOLLOWLOCATION, 1);
  59.         curl_setopt($process,CURLOPT_POST, 1);
  60.        $return =curl_exec($process);
  61.         curl_close($process);
  62.        return $return;
  63.    }
  64.  
  65.    function error($error) {
  66.        echo "<center><div style='width:500px;border: 3px solid #FFEEFF; padding: 3px; background-color: #FFDDFF;font-family: verdana; font-size: 10px'><b>cURL Error</b><br>$error</div></center>";
  67.        die;
  68.    }
  69.  
  70. }
  71.  
  72. ?>


0x04.POST数据
代码如下
  1. ﹤?php
  2. $phoneNumber = '13812345678';
  3. $message = 'This message was generated by curl and php';
  4. $curlPost = 'pNUMBER=' . urlencode($phoneNumber) . '&MESSAGE=' . urlencode($message) . '&SUBMIT=Send';
  5. $ch = curl_init();
  6. curl_setopt($ch, CURLOPT_URL, 'http://www.lxvoip.com/sendSMS.php');
  7. curl_setopt($ch, CURLOPT_HEADER, 1);
  8. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  9. curl_setopt($ch, CURLOPT_POST, 1);
  10. curl_setopt($ch, CURLOPT_POSTFIELDS, $curlPost);
  11. $data = curl_exec();
  12. curl_close($ch);
  13. ?﹥



0x05.
模拟登录

Curl 模拟登录 discuz 程序,适合DZ7.0,将username改成你的用户名,userpass改成你的密码就可以了. 
代码如下
    1. <?php  
    2.   
    3.  
    4. !extension_loaded('curl') && die('The curl extension is not loaded.');  
    5.  
    6. $discuz_url = 'http://www.lxvoip.com';//论坛地址  
    7. $login_url = $discuz_url .'/logging.php?action=login';//登录页地址  
    8. $get_url = $discuz_url .'/my.php?item=threads'; //我的帖子  
    9.  
    10. $post_fields = array();  
    11. //以下两项不需要修改  
    12. $post_fields['loginfield'] = 'username';  
    13. $post_fields['loginsubmit'] = 'true';  
    14. //用户名和密码,必须填写  
    15. $post_fields['username'] = 'lxvoip';  
    16. $post_fields['password'] = '88888888';  
    17. //安全提问  
    18. $post_fields['questionid'] = 0;  
    19. $post_fields['answer'] = '';  
    20. [email protected]  
    21. $post_fields['seccodeverify'] = '';  
    22.  
    23. //获取表单FORMHASH  
    24. $ch = curl_init($login_url);  
    25. curl_setopt($ch, CURLOPT_HEADER, 0);  
    26. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  
    27. $contents = curl_exec($ch);  
    28. curl_close($ch);  
    29. preg_match('/<inputs*type="hidden"s*name="formhash"s*value="(.*?)"s*/>/i', $contents,$matches);  
    30. if(!empty($matches)) {  
    31.     $formhash = $matches[1];  
    32. } else {  
    33.     die('Not found the forumhash.');  
    34. }  
    35.  
    36. //POST数据,获取COOKIE  
    37. $cookie_file = dirname(__FILE__) . '/cookie.txt';  
    38. //$cookie_file = tempnam('/tmp');  
    39. $ch = curl_init($login_url);  
    40. curl_setopt($ch, CURLOPT_HEADER, 0);  
    41. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  
    42. curl_setopt($ch, CURLOPT_POST, 1);  
    43. curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);  
    44. curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);  
    45. curl_exec($ch);  
    46. curl_close($ch);  
    47.  
    48. //带着上面得到的COOKIE获取需要登录后才能查看的页面内容  
    49. $ch = curl_init($get_url);  
    50. curl_setopt($ch, CURLOPT_HEADER, 0);  
    51. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);  
    52. curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);  
    53. $contents = curl_exec($ch);  
    54. curl_close($ch);  
    55.  
    56. var_dump($contents);  
    57. ?>
再看几个模拟登录的例子:

代码如下
<?php

error_reporting(E_ALL);

$login_url = '192.168.18.25/test/php-curl-login.php';//模拟登录地址

$cookie_url='192.168.18.25/test/php-curl-cookie.php'; //模拟发帖

$post_fields = array();
$post_fields['user_name'] = 'phpcto';
$post_fields['pass_word'] = 'phpcto123';
$cookie_file =tempnam('./temp','cookie');
ob_start();
echo '<pre>';

$ch = curl_init($login_url);
curl_setopt($ch, CURLOPT_HEADER, 0);// 返回页面内容  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);  //获取的信息以文件流的形式返回  
curl_setopt($ch, CURLOPT_POST, 1);// 提交post数据 
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);// 保存cookie 
curl_exec($ch);  // 执行 
curl_close($ch);// 关闭
echo '<hr/>';

$ch2=curl_init($cookie_url);
curl_setopt($ch2, CURLOPT_COOKIEFILE, $cookie_file); // 使用cookie
curl_exec($ch2);
curl_close($ch2);
echo '<hr/>';

echo '</pre>';
ob_end_flush();



代码如下
php 使用curl模拟登录discuz以及模拟发帖 
<?php
$discuz_url = 'http://127.0.0.1/discuz/';//论坛地址
$login_url = $discuz_url .'logging.php?action=login';//登录页地址
$post_fields = array();
//以下两项不需要修改
$post_fields['loginfield'] = 'username';
$post_fields['loginsubmit'] = 'true';
//用户名和密码,必须填写
$post_fields['username'] = 'tianxin';
$post_fields['password'] = '111111';
//安全提问
$post_fields['questionid'] = 0;
$post_fields['answer'] = '';
[email protected]
$post_fields['seccodeverify'] = '';

//获取表单FORMHASH
$ch = curl_init($login_url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$contents = curl_exec($ch);
curl_close($ch);
preg_match('/<input\s*type="hidden"\s*name="formhash"\s*value="(.*?)"\s*\/>/i', $contents, $matches);
if(!empty($matches)) {
    $formhash = $matches[1];
} else {
    die('Not found the forumhash.');
}

//POST数据,获取COOKIE,cookie文件放在网站的temp目录下
$cookie_file = tempnam('./temp','cookie');

$ch = curl_init($login_url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
curl_exec($ch);
curl_close($ch);

//取到了关键的cookie文件就可以带着cookie文件去模拟发帖,fid为论坛的栏目ID
$send_url = $discuz_url."post.php?action=newthread&fid=2";

$ch = curl_init($send_url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
$contents = curl_exec($ch);
curl_close($ch);

//这里的hash码和登陆窗口的hash码的正则不太一样,这里的hidden多了一个id属性
preg_match('/<input\s*type="hidden"\s*name="formhash"\s*id="formhash"\s*value="(.*?)"\s*\/>/i', $contents, $matches);
if(!empty($matches)) {
    $formhash = $matches[1];
} else {
    die('Not found the forumhash.');
}

$post_data = array();
//帖子标题
$post_data['subject'] = 'test2';
//帖子内容
$post_data['message'] = 'test2';
$post_data['topicsubmit'] = "yes";
$post_data['extra'] = '';
//帖子标签
$post_data['tags'] = 'test';
//帖子的hash码,这个非常关键!假如缺少这个hash码,discuz会警告你来路的页面不正确
$post_data['formhash']=$formhash;

$ch = curl_init($send_url);
curl_setopt($ch, CURLOPT_REFERER, $send_url);       //伪装REFERER
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$contents = curl_exec($ch);
curl_close($ch);

//清理cookie文件
unlink($cookie_file);

?>




代码如下
<?php   
$cookie_file = dirname(__FILE__)."/cookie_".md5(basename(__FILE__)).".txt"; // 设置Cookie文件保存路径及文件名   
  
function vlogin($url,$data){ // 模拟登录获取Cookie函数   
     $curl = curl_init(); // 启动一个CURL会话   
     curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址               
     curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查   
   curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在   
    curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器   
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转   
     curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer   
     curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求   
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post 提交的数据包   
    curl_setopt($curl, CURLOPT_COOKIEJAR, $GLOBALS['cookie_file']); // 存放 Cookie信息的文件名称   
     curl_setopt($curl, CURLOPT_COOKIEFILE, $GLOBALS['cookie_file']); // 读取上面所储存的Cookie信息   
     curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环   
     curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容   
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回   
     $tmpInfo = curl_exec($curl); // 执行操作   
    if (curl_errno($curl)) {   
         echo 'Errno'.curl_error($curl);   
        
       curl_close($curl); // 关闭 CURL会话   
       return $tmpInfo; // 返回数据   
   }   
     
  function vget($url){ // 模拟获取内容函数   
      $curl = curl_init(); // 启动一个CURL会话   
      curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址               
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查   
     curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在   
    curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器   
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转   
    curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer   
    curl_setopt($curl, CURLOPT_HTTPGET, 1); // 发送一个常规的Post请求   
    curl_setopt($curl, CURLOPT_COOKIEFILE, $GLOBALS['cookie_file']); // 读取上面所储存的Cookie信息   
     curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环   
     curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容   
     curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回   
     $tmpInfo = curl_exec($curl); // 执行操作   
   if (curl_errno($curl)) {   
       echo 'Errno'.curl_error($curl);   
     }   
      curl_close($curl); // 关闭 CURL会话   
     return $tmpInfo; // 返回数据   
  
   
function vpost($url,$data){ // 模拟提交数据函数   
     $curl = curl_init(); // 启动一个CURL会话   
    curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址               
     curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查   
     curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在   
    curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器   
     curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转   
    curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer   
    curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求   
     curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post 提交的数据包   
    curl_setopt($curl, CURLOPT_COOKIEFILE, $GLOBALS['cookie_file']); // 读取上面所储存的Cookie信息   
     curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环   
       curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容   
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回   
     $tmpInfo = curl_exec($curl); // 执行操作   
    if (curl_errno($curl)) {   
       echo 'Errno'.curl_error($curl);   
      
      curl_close($curl); // 关键 CURL会话   
     return $tmpInfo; // 返回数据   
  
   
function delcookie($cookie_file){ // 删除 Cookie函数   
  @unlink($cookie_file); // 执行删除   
  
   
// 使用实例   
// vlogin('192.168.18.25/test/login.php','user_name=yang&pass_word=yangjs123'); // 登录获取 Cookie   
//echo vget('192.168.18.25/test/login.php');   
echo vpost('192.168.18.25/test/login.php','user_name=yang&pass_word=yangjs123');   
?> 


0x06.PHP多线程抓取网页实现代码

代码如下
<?php
$ch1 = curl_init();
$ch2 = curl_init();
curl_setopt($ch1, CURLOPT_URL, "http://www.XX.com/");
curl_setopt($ch1, CURLOPT_HEADER, 0);
curl_setopt($ch2, CURLOPT_URL, "http://www.00.com/");
curl_setopt($ch2, CURLOPT_HEADER, 0);
$mh = curl_multi_init();
curl_multi_add_handle($mh,$ch1);
curl_multi_add_handle($mh,$ch2);
do{
 curl_multi_exec($mh,$flag);
}while($flag > 0);
curl_multi_remove_handle($mh,$ch1);
curl_multi_remove_handle($mh,$ch2);
curl_multi_close($mh);
?>



0x07.抓取和分析一个文件是非常简单的事。

file函数也可以,不同的网站要写不同的正则表达式来匹配抓取想要的内容。
以下实现php抓取网页title,keywords,description,content,注释掉的数据库操作(即把抓取的内容存到数据库)

代码如下
<?php

header('Content-Type: text/html; charset=gbk');
$url ="http://www.jj59.com/qingganwenzhang/093750.html";
$lines_array=file($url);//read entire web file into array
//var_dump($lines_array);
$lines_string = implode('', $lines_array);//maybe not in a row,so join the array elements with a string
$count=count($lines_string);
for($i=0;$i<$count;$i++){
 if(preg_match("/<title>(.*)<\/title>/is",$lines_string,$title)){//标题
  $title=$title[0];
  }
 if(preg_match("/<meta[^>]*?name=[\'\"]?keywords[\'\"]?[^>]*?>/is",$lines_string,$keywords)){//关键字
  $title2=$keywords[0];
  }
 if(preg_match("/<meta[^>]*?name=[\'\"]?description[\'\"]?[^>]*?>/is",$lines_string,$description)){//描述
  $title3=$description[0];
  }
  if(preg_match("/<div class=\"content\"><div id=zt><div id=\"twgg\" class=\"gg\"><\/div>(.*)<p>(.*)<\/p>(.*)<p class=\"bianji\">/is",$lines_string,$content)){//描述
  $title4=$content[0];
  //var_dump($title4);
  } 
}
$title=substr($title,7,-19);
$title2=substr($title2,31,-4);
$title3=substr($title3,34,-4);
//$title4=substr($title4,34,-40);
echo "Title:".$title."<br>";
echo "KeyWords:".$title2."<br>";
echo "Description:".$title3."<br>";
echo "Content:".$title4."<br>";
//$query="insert into insun4 values('$i','$title','$title2','$title3','$title4')";
//$result=mysql_query($query) or die("查询数据失败");//执行查询
?>


代码如下
<?php

header('Content-Type: text/html; charset=gbk');
error_reporting(E_CORE_ERROR);
$url ="http://yxmhero1989.blog.163.com";
$lines_array=file($url);//read entire web file into array
//var_dump($lines_array);
$lines_string = implode('', $lines_array);//maybe not in a row,so join the array elements with a string
$count=count($lines_string);
for($i=0;$i<$count;$i++){
 //if(preg_match("/<title>(.*)<\/title>/is",$lines_string,$title)){//标题
 if(eregi("<title>(.*)</title>",$lines_string,$title)){
  $title=$title[0];
  }
 if(preg_match("/<meta[^>]*?name=[\'\"]?keywords[\'\"]?[^>]*?>/is",$lines_string,$keywords)){//关键字
  $title2=$keywords[0];
  }
 if(preg_match("/<meta[^>]*?name=[\'\"]?description[\'\"]?[^>]*?>/is",$lines_string,$description)){//描述
  $title3=$description[0];
  }
}
$title=substr($title,7,-19);
$title2=substr($title2,31,-3);
$title3=substr($title3,34,-5);

echo "Title:".$title."<br>";
echo "KeyWords:".$title2."<br>";
echo "Description:".$title3."<br>";

//$query="insert into insun4 values('$i','$title','$title2','$title3')";
//$result=mysql_query($query) or die("查询数据失败");//执行查询
?>



结果:
Title:Minghacker is Insun - InSun
KeyWords:InSun,Minghacker is Insun,网易博客,网易,blog
Description:百度(baidu)分词算法分析,对网易博客日志标签功能的期盼,CDbConnection failed to open the DB connection: could not find driver,Warning: date() [function.date]: It is not safe to rely on the system's timezone settings.,浅谈Python web框架,谷歌是如何做代码审查的(Things Everyone Should Do: Code Review),Failed to connect to mailserver at localhost port 25,PHP flock文件锁,针对$_SERVER[’PHP_SELF’]的跨站脚本攻击,安全跑路指南与安全跑路指南升级版,InSun的网易博客,凡你醉处 你说过 皆非他乡,爱好写词摄影和美女。专注编程和安全。应该可以发好人卡,可能时机没到

0x08.找到了的数据存到数据库,然后CSS+DIV架个前台,在前台用分页调用,代码就不贴了,直接上图片:
 
你看多简单,前面的几个大站互爬数据添加到数据库,然后前台调用,充实了自己的信息库,减少了手动的工作量,何其乐啊,可是不知道算不算违反?大概恶意竞争才算,所以反爬虫机制必须的~~~
 
0x09.浅谈反爬虫机制:
①。现在各大搜索网站和行业化以及特别商业化的网站应该都有反爬虫机制,爬虫需要伪造Agent信息,而且每次爬信息都要有一定的时间间隔(即加上随机sleep )。
②。robots.txt是一存放于网站根目录中的文本文件,用来定义网站上哪些内容可以或不能供网络爬虫存取,Yahoo也在网站上说明如何利用robots.txt以避免网站或特定网页数据不被搜索引擎搜集及索引。
③。如果是爬虫程序来访,则user-agent会显示Googlebot或MSNBot等搜索引擎爬虫程序名称,每个搜索引擎都有自己的user-agent,以下分别列出国内主要的爬虫程序。

百度baidu.com—-Baiduspider   谷歌google.com—-Googlebot

雅虎yahoo.com—-Yahoo  有道yodao.com—-YodaoBot

搜搜soso.com—-Sosospider/Sosoimagespider  搜狗sogou.com—-sogou  微软msn.com—-msnbot

自写程序,if不是上面就access deny,这样不失流量,也遏制了对手的肆意爬取信息,减少了对公司的损失。
④。重要的2篇文章  分析了反爬虫策略。
web性能优化(三)反爬虫策略
http://dynamiclu.iteye.com/blog/1044645
互联网网站的反爬虫策略浅析
http://robbin.iteye.com/blog/451014
  相关解决方案