<?php
/**
* 可以灵活配置使用的采集器
* 作者:Rain
* 创建时间:2015-02-03 15:17:30
* 版本信息:V1.0
*/ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//数据库的相关配置信息,请根据您的数据库信息进行配置
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PWD', 'test123456');
define('DB_NAME', 'test_dbname');
define('DB_CHARSET', 'utf8');
define('TABLE_NAME', 'tb_book');
//end //网站信息相关的配置,请根据具体需要采集的网站内容信息进行配置
define('WEB_CHARSET', 'gbk');
//变动的参数,使用%d进行替换,只支持数值形式的变动
define('WEB_LIST_URL', 'http://www.pcbookcn.com/book/1_%d.htm');
//分页的条数
define('PAGE_COUNT', 14);
//从哪个页面开始抓取
define('PAGE_START', 1);
//内容页的URL,使用正则模式,必须包含/,例如:/\/xuefu2008\/article\/details\/(\d)+/i
define('WEB_CONTENT_URL_REG', '/\/book\/(\d)+\.htm/i');
//网站域名HOST信息,不包含末尾的/,例如:http://blog.csdn.net
define('WEB_HOST', 'http://www.pcbookcn.com');
//列表页内容的精准定位,用来大致抓取一个列表页的内容显示模块位置,使用正则进行定位
define('WEB_LIST_POSTION', '/book_name\.gif(.*?)<td\swidth="15\%"\snowrap>/i');
//end //微调参数,通常不修改也不会影响您的正常使用
define('SLEEP_TIME', 1);
define('IS_DEBUG', false);
define('INSERT_DB', true);
//内容的输出速度,单位:秒
define('OUTPUT_SPEED', 1);
//end //需要过滤删除的文字,根据采集的网站类型进行设置,不区分大小写
$text_filter = array(
'- 中华电脑书库' => '',
'_电脑电子书' => '',
'_电脑书籍' => '',
'下载' => '',
); //表结构映射的配置
$table_mapping = array(
//表字段名称 => 获取该字段的正则表达式,非空字段都必须在此设置映射关系,常量值请直接填写具体对应的值,无需使用正则
'size' => '/软件大小.*?000000>(.*?)<\/font>/i',
'logo' => 'http://www.94cto.com/index/uploads/images/20150105/0b8461910de101cc51a07684cdab797e.jpg',
'field1' => '/<title>(.*?)<\/title>/i',
'field2' => '/软件简介.*?000000>(.*?)<\/font>/i',
'field3' => '1',
'field4' => '1',
'field5' => '1',
'field6' => '电子书,计算机,图像,图形',
'platform' => 'window/Linux',
'ishot' => '1',
'agreement' => '免费',
'downurl' => '/(\/down\.asp\?id=.*?)"/i',
'istop' => '1',
);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// $ga = new Gather();
$ga->run(); class Gather
{
public function __construct()
{
$this->init_check();
} public function run()
{
global $table_mapping, $text_filter; for ($page = PAGE_START; $page <= PAGE_COUNT; $page++)
{ $this->write('开始采集列表第'.$page.'页的内容...');
$list_content = $this->get(sprintf(WEB_LIST_URL, $page));
if (empty($list_content))
{
$this->write('抓取的列表页的内容为空,所以过滤掉');
continue;
} $list_content = str_replace("\r", '', $list_content);
$list_content = str_replace("\n", '', $list_content); //精准定位要抓取的模块内容
if (!preg_match(WEB_LIST_POSTION, $list_content, $list_search))
{
$this->write('精准匹配列表页的内容失败,所以过滤掉');
continue;
}
if (isset($list_search[1]))
$list_content = $list_search[1];
else
$list_content = $list_search[0];
//end preg_match_all(WEB_CONTENT_URL_REG, $list_content, $match);
if (is_array($match[0]) && !empty($match[0]))
{
$this->write('当前的列表页面,总共匹配到:'.count($match[0]).'个内容页');
foreach ($match[0] as $val)
{
if (strpos($val, 'http:') === false)
{
if (substr($val, 0, 1) == '/')
$val = WEB_HOST.$val;
else
$val = WEB_HOST.'/'.$val;
}
$web_content = $this->get($val);
if (empty($web_content))
{
$this->write('抓取的内容页为空,所以过滤掉');
continue;
} $web_content = str_replace("\r", '', $web_content);
$web_content = str_replace("\n", '【】', $web_content); $sql = "INSERT INTO ".TABLE_NAME."(".implode(', ', array_keys($table_mapping)).")VALUES(";
foreach ($table_mapping as $field => $reg)
$sql .= ':'.$field.',';
$sql = substr($sql ,0, -1);
$sql .= ')'; if (IS_DEBUG)
$this->write('执行SQL '.$sql); $dsn = 'mysql:dbname='.DB_NAME.';host='.DB_HOST;
try {
$dbh = new PDO($dsn, DB_USER, DB_PWD);
} catch (PDOException $e) {
$this->write( 'Connection failed: ' . $e->getMessage(), true);
}
$dbh->query("set names 'utf8'");
$sth = $dbh->prepare($sql); foreach ($table_mapping as $field => $reg)
{
if (substr($reg, 0, 1) != '/')
{
$$field = $reg;
}
else
{
if (!preg_match($reg, $web_content, $tmp_match))
{
$this->write('对不起,匹配字段:'.$field.'失败,过滤此记录');
continue 2;
} $$field = $tmp_match[1];
$$field = $this->closetags($$field); //删除javascript脚本
$$field = preg_replace('/<script(.*?)>(.*?)<\/script>/i', '', $$field); //将链接删除
$$field = preg_replace('/<a(.*?)>(.*?)<\/a>/i', '${2}', $$field); //图片链接地址绝对地址化
preg_match_all('/<img.*?src=("|\')+(.*?)("|\')+.*?>/i', $$field, $img_match);
if (isset($img_match[2]) && is_array($img_match[2]) && !empty($img_match[2]))
{
foreach ($img_match[2] as $img_val)
{
if (strpos($img_val, 'http:') === false)
{
$new_val = $img_val;
if (substr($new_val, 0, 1) != '/')
$new_val = '/'.$img_val;
$new_val = WEB_HOST.$new_val;
$$field = str_replace($img_val, $new_val, $$field);
}
}
}
//end //针对HTML里面的pre的换行先做一个特殊处理
$$field = preg_replace('/<pre.*?>(.*?)<\/pre>/i', '<pre class="prettyprint">${1}</pre>', $$field);
preg_match_all('/<pre>(.*?)<\/pre>/i', $$field, $pre_match);
if (isset($pre_match[1]) && is_array($pre_match[1]) && !empty($pre_match[1]))
{
foreach ($pre_match[1] as $pre_val)
$$field = str_replace($pre_val, str_replace("【】", "\r\n", $pre_val), $$field);
}
//end
} //入库之前,将对应的换行符号都还原回来
$$field = str_replace('【】', "\r\n", $$field);
//文本的过滤和替换操作
if (is_array($text_filter) && !empty($text_filter))
{
foreach ($text_filter as $tk => $tv)
$$field = str_ireplace($tk, $tv, $$field);
} if (IS_DEBUG)
$this->write('*'."\t".'字段:'.$field.' 值:'."\n****************************************************\n".$$field."\n****************************************************");
if ('downurl' == $field && stripos($$field, 'http:') === false)
if (substr($$field, 0, 1) == '/')
$$field = WEB_HOST.trim($$field);
else
$$field = WEB_HOST.'/'.trim($$field);
$sth->bindValue(':'.$field, trim($$field));
}
if (INSERT_DB)
$sth->execute();
$sth->closeCursor(); $this->write( '休息,暂停'.SLEEP_TIME.'秒后继续抓取...');
sleep(SLEEP_TIME);
}
}
else
{
$this->write('列表页面没有抓取到内容,所以过滤掉');
}
}
$this->write('', true);
} protected function closetags($html)
{
// 不需要补全的标签
$arr_single_tags = array('meta', 'img', 'br', 'link', 'area');
// 匹配开始标签
preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
$openedtags = $result[1];
// 匹配关闭标签
preg_match_all('#</([a-z]+)>#iU', $html, $result);
$closedtags = $result[1];
// 计算关闭开启标签数量,如果相同就返回html数据
$len_opened = count($openedtags);
if (count($closedtags) == $len_opened) {
return $html;
}
// 把排序数组,将最后一个开启的标签放在最前面
$openedtags = array_reverse($openedtags);
// 遍历开启标签数组
for ($i = 0; $i < $len_opened; $i++) {
// 如果需要补全的标签
if (!in_array($openedtags[$i], $arr_single_tags)) {
// 如果这个标签不在关闭的标签中
if (!in_array($openedtags[$i], $closedtags)) {
// 直接补全闭合标签
$html .= '</' . $openedtags[$i] . '>';
} else {
unset($closedtags[array_search($openedtags[$i], $closedtags)]);
}
}
}
return $html;
} protected function init_check()
{
if (!$this->check_curl_support())
$this->write('对不起,请先开启CURL的类库的支持,否则无法执行', true);
$this->check_mysql_connect();
$this->write('程序初始化检查通过,执行后续的流程...');
} private function get($url, $data = array())
{
$this->write('开始执行抓取: '.$url);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
//curl_setopt($ch, CURLOPT_USERAGENT, "Baiduspider+(+http://www.baidu.com/search/spider.htm)");
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $data);
$ret = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
unset($ch);
if (!empty($error))
{
$this->write('程序抓取URL: '.$url.'发生错误,错误信息: '.$error);
return false;
}
if (WEB_CHARSET != 'utf-8')
$ret = iconv(WEB_CHARSET, 'utf-8', $ret);
return $ret;
} //when check finish,mysql connect will auto close
private function check_mysql_connect()
{
$con = mysql_connect(DB_HOST, DB_USER, DB_PWD);
if (!is_resource($con))
$this->write('程序无法成功链接到数据库,具体的错误信息:'.mysql_error(), true);
if (!mysql_select_db(DB_NAME, $con))
$this->write('程序无法链接到数据库: '.DB_NAME.',具体的错误信息: '.mysql_error(), true);
mysql_close($con);
} private function check_curl_support()
{
if (!extension_loaded('curl') || !function_exists('curl_init'))
return false;
return true;
} private function write($str, $end = false)
{
if (PATH_SEPARATOR == ':')
echo $str,PHP_EOL,PHP_EOL;
else
echo iconv('UTF-8', 'GBK', $str),PHP_EOL,PHP_EOL; if ($end)
die("program exit"); sleep(OUTPUT_SPEED);
}
}

php web 信息采集的更多相关文章

  1. .net 信息采集ajax数据

    .net 信息采集ajax数据 关于.net信息采集的资料很多,但是如果采集的网站是ajax异步加载数据的模式,又如何采集呢?今天就把自己做信息采集时,所遇到的一些问题和心得跟大家分享一下. 采集网站 ...

  2. 20145308 《网络对抗》 Web应用 学习总结

    20145308 <网络对抗> Web应用 学习总结 实验内容 (1)Web前端HTML (2)Web前端javascipt (3)Web后端:MySQL基础:正常安装.启动MySQL,建 ...

  3. 20155207 EXP8 Web基础

    20155207 EXP8 Web基础 实验内容 (1)Web前端HTML (2)Web前端javascipt (3)Web后端:MySQL基础:正常安装.启动MySQL,建库.创建用户.修改密码.建 ...

  4. 20145318《网络对抗》Web应用

    20145318<网络对抗>Web应用 基础问题回答 (1)什么是表单 在网页中负责信息采集,在网页中用户输入信息,通过表单能够提交到后台进行相应的处理 (2)浏览器可以解析运行什么语言 ...

  5. web测试与手机测试的区别

    1.web是B/S,移动端是C/S 2.系统的性能: B/S的优势是异地浏览和信息采集比较灵活性,随时随地只要能使用浏览器上网即可 但是客户端只能完成浏览,查询,数据输入等简单工作,绝大部分又服务器承 ...

  6. Kail Linux渗透测试培训手册3第二章信息采集

    Kail Linux渗透测试培训手册3第二章信息采集 信息收集是网络攻击中最重要的步骤之一.渗透攻击.我们需要收集各种信息目标.该信息收集.攻击成功的概率越大.介绍信息收集的相关工具.本文选自< ...

  7. 城市防汛应急管理智慧 Web GIS 可视化平台

    前言 今年第 17 号台风"狮子山"(热带风暴级)登陆海南岛,受"狮子山"影响,海南岛北半部地区出现暴雨到大暴雨.局地特大暴雨.台风带来的强风雨导致海南岛多地树 ...

  8. C# Web应用调试开启外部访问

    在用C#开发Web应用时有个痛点,就是本机用VS开启Web应用调试时外部机器无法访问此Web应用.这里将会介绍如何通过设置允许局域网和外网机器访问本机的Web应用. 目录 1. 设置内网访问 2. 设 ...

  9. 网页提交中文到WEB容器的经历了些什么过程....

    先准备一个网页 <html><meta http-equiv="Content-Type" content="text/html; charset=gb ...

随机推荐

  1. C++中typename和class的区别

    C++中typename和class的区别 在c++Template中很多地方都用到了typename与class这两个关键字,而且好像可以替换,是不是这两个关键字完全一样呢? 相信学习C++的人对c ...

  2. AJAX-创建XMLHttpRequest对象

    AJAX-创建XMLHttpRequest对象 1.XMLHttpRequest是AJAX的基础,所有现在浏览器都支持,用于在后台与服务器交换数据,也就意味着可以在不加载整个页面的情况下对整个页面进  ...

  3. fielderror里的fieldName代表的是jsp里的fieldName还是Action类的成员变量?(待解答)

    1.值栈的Action对象中会有一个fielderror属性,代表着字段错误. fielderror是Map<String,List<String>>类型 例如下面的值栈里可看 ...

  4. C# webbrowser实现真正意义上的F5刷新

    关于webbrowser的刷新在C#中有提供方便的方法: webbrowser.refresh(); 但是有时候会发现,不给力啊 那怎么办? 还有一招: webBrowser1.Document.Ex ...

  5. Bugtags 实时跟踪插件 - BugtagsInsta

    BugtagsInsta 是 Bugtags SDK 的官方插件,应用集成成功后,可以在 Bugtags 云端管理平台实时查看应用的运行时数据:操作步骤.用户数据.控制台日志.Bugtags 日志.网 ...

  6. [AS3.0] FMS改变录制视频的默认地址

    FMS默认的视频录制或点播的地址是在{FMS-Install-Dir}\applications,如何指向到其他目录. 1.改变applications的目录指向: 在FMS安装目录下找到/conf/ ...

  7. form表单的enter自动提交

    当form中只有一个文本框时并且获得焦点 按enter时,就会自动提交表单.阻止自动提交 可以添加一个隐藏的input框 <input type="text" style=& ...

  8. ubuntu14.04 JDK安装

    JDK7 安装 1 sudo apt-get install openjdk-7-jdk 2 设置安装环境 在/etc/profile中追加: # Java support # export JAVA ...

  9. [转]Dynamic SQL & Stored Procedure Usage in T-SQL

    转自:http://www.sqlusa.com/bestpractices/training/scripts/dynamicsql/ Dynamic SQL & Stored Procedu ...

  10. Jquery实现兼容各大浏览器的Enter回车切换输入焦点的方法

    <script type="text/javascript"> $('input:text:first').focus(); document.onkeydown = ...