spider 介绍
Spider又叫WebCrawler或者Robot,是一个沿着链接漫游Web 文档集合的程序。它一般驻留在服务器上,通过给定的一些URL,利用HTTP等标准协议读取相应文档,然后以文档中包括的所有未访问过的URL作为新的起点,继续进行漫游,直到没有满足条件的新URL为止。WebCrawler的主要功能是自动从Internet上的各Web 站点抓取Web文档并从该Web文档中提取一些信息来描述该Web文档,为搜索引擎站点的数据库服务器追加和更新数据提供原始数据,这些数据包括标题、长度、文件建立时间、HTML文件中的各种链接数目等
1. 搜索策略
① IP 地址搜索策略
先赋予爬虫一个起始的IP地址,然后根据IP地址递增的方式搜索本IP地址段后的每一个WWW地址中的文档,它完全不考虑各文档中指向其它Web 站点的超级链接地址。优点是搜索全面,能够发现那些没被其它文档引用的新文档的信息源;缺点是不适合大规模搜索。
② 深度优先搜索策略
深度优先搜索是一种在开发爬虫早期使用较多的方法。它的目的是要达到被搜索结构的叶结点(即那些不包含任何超链的HTML文件) 。在一个HTML文件中,当一个超链被选择后,被链接的HTML文件将执行深度优先搜索,即在搜索其余的超链结果之前必须先完整地搜索单独的一条链。深度优先搜索沿着HTML文件上的超链走到不能再深入为止,然后返回到某一个HTML文件,再继续选择该HTML文件中的其他超链。当不再有其他超链可选择时,说明搜索已经结束。优点是能遍历一个Web 站点或深层嵌套的文档集合;缺点是因为Web结构相当深,,有可能造成一旦进去,再也出不来的情况发生。
③ 宽度优先搜索策略
在宽度优先搜索中,先搜索完一个Web 页面中所有的超级链接,然后再继续搜索下一层, 直到底层为止。例如,一个HTML 文件中有三个超链,选择其中之一并处理相应的HTML文件,然后不再选择第二个HTML文件中的任何超链, 而是返回并选择第二个超链,处理相应的HTML文件,再返回,选择第三个超链并处理相应的HTML文件。一旦一层上的所有超链都己被选择过,就可以开始在刚才处理过的HIML 文件中搜索其余的超链。这就保证了对浅层的首先处理。当遇到一个无穷尽的深层分支时,不会导致陷进WWW 中的深层文档中出现出不来的情况发生。宽度优先搜索策略还有一个优点,即它能在两个HTML文件之间找到最短路径。宽度优先搜索策略通常是实现爬虫的最佳策略,因为它容易实现,而且具备大多数期望的功能。但是如果要遍历一个指定的站点或者深层嵌套的HTML文件集,用宽度优先搜索策略则需要花费比较长的时间才能到达深层的HTML文件。综合考虑以上几种策略和国内信息导航系统搜索信息的特点,国内一般采用以宽度优先搜索策略为主、线性搜索策略为辅的搜索策略。对于某些不被引用的或很少被引用的HTML文件,宽度优先搜索策略可能会遗漏这些孤立的信息源,可以用线性搜索策略作为它的补充。
④ 专业搜索引擎的爬虫策略
目前,专业搜索引擎网络爬虫通常采用“最好优先”原则访问WEB,即为快速、有效地获得更多的与主题相关的页面(简称“回报”),每次选择“最有价值”的链接进行访问。由于链接包含于页面之中,而通常具有较高价值的页面包含的链接也具有较高的价值,因而对链接价值的评价有时也转换为对页面价值的评价。
⑤ 爬虫的设计中应该注意的问题
第一个问题是URL地址的标准化:在WWW上,一个URL地址可以有多种表示方法,可以用IP地址表示,也可以用域名来表示。为了避免爬虫重复访问同一地址。第二个问题是避免掉进网络陷阱:网络上的链接情况比较复杂,一些静态的网页可能构成闭环回路。为了避免爬虫在一条循环路线上反复抓取,在把URL加入待搜索地址列表之前都要检查是否已在待搜索的地址列表中出现过。对于动态网页,爬虫应该忽略所有带参数的URL。第三个问题:对于拒绝访问的页面,爬虫应该遵从“漫游拒绝访问规则”。
KEY `file_url_md5` (`url_md5`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT=grab history; CREATE TABLE `pic_gallery` ( `id` int(11) NOT NULL auto_increment, `file_url_md5` varchar(100) NOT NULL, `file_url` varchar(1024) default NULL, `file_data` longblob, `file_type` varchar(100) default NULL, `file_name` varchar(255) default NULL, `file_size` int(11) default NULL, PRIMARY KEY (`id`), KEY `file_url_md5` (`file_url_md5`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE `web_page` ( `id` bigint(20) NOT NULL auto_increment, `page_url_md5` varchar(100) NOT NULL, `page_url` varchar(1024) default NULL, `page_content` longblob, `page_pic` varchar(1024) default NULL, `page_length` int(11) default NULL, `grab_time` datetime default NULL, PRIMARY KEY (`id`), KEY `page_url_md5` (`page_url_md5`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT=网络爬虫数据存储表;
function put_web_page($url, $content, $filesize) { $sql = "insert into web_page (page_url_md5, page_url, page_content, page_length, grab_time) values (".md5($url).",$url,$content,$filesize,".date("Y-m-d H:i:s", time()).")"; } 抓取图片内容插入数据库 function put_web_pic($url, $content, $filename, $filesize, $ref_page) { $sql = "insert into pic_gallery (file_url_md5, file_url, file_data, file_name, file_size) values (".md5($url).",$url,$content,$filename,$filesize)"; } 抓取url历史插入数据库 function add_history($url, $md5) { $sql = "insert into grab_history (file_url, url_md5) values ($url, $md5);"; } function get_grab_history( $oldhistory, $subkey) { $sql = "select id, file_url,url_md5 from grab_history where url_md5 like $subkey%"; $result = mysql_query($sql); $num = mysql_num_rows($result); $i; for ($i = 0; $i $num; $i++) { $url = mysql_result($result, $i, 1); $md5 = mysql_result($result, $i, 2); //$oldhistory[$url] = $url; $oldhistory[$md5] = $url; //if (count($oldhistory) % 1000 == 0) { // $id = count($oldhistory); // echo("the size of history is $id!\n"); //} } }
function web_site_info($url) { $temp = ereg_replace("http://", "", $url); $sp = split([/], $temp); $sc = count($sp); $i; echo("$url\n"); $this- web_site = $sp[0]; if ($sc == 1) { return; } if ($sc == 2) { $this- web_filename = $sp[1]; }else { for ($i = 1; $i $sc -1; $i++) { if ($i 1) { $this- web_dir = $this- web_dir . "/"; } $this- web_dir = $this- web_dir . $sp[$i]; } $this- web_filename = $sp[$sc-1]; } } //分析网页中的url,构建正确的url function calc_path($url_path) { $ret = ""; $temp = ""; $url = trim($url_path); $pos = strncmp($url, "http://", 7); if ($pos == 0) { return $url; } $pos = strncmp($url, "../", 3); if ($pos == 0) { $ret = $this- web_site ."/" .$this- web_dir; $ret = dirname($ret); $ret = "http://" .$ret ."/"; $temp = ereg_replace("../", $ret, $url); return $temp; } $pos = strncmp($url, "./", 2); if ($pos == 0) { $ret = "http://" .$this- web_site ."/"; if (strlen($this- web_dir) 0) $ret = $ret .$this- web_dir ."/"; $temp = ereg_replace("./", $ret, $url); return $temp; } $pos = strncmp($url, "/", 1); if ($pos == 0) { $ret = "http://" .$this- web_site .$url; return $ret; } $ret = "http://" .$this- web_site ."/"; if (strlen($this- web_dir) 0) { $ret = $ret .$this- web_dir ."/"; } $ret = $ret .$url; return $ret; } //获取url中的路径名 function get_save_path() { $ret; if (strlen($this- web_dir)) { $ret = $this- web_site."\\".$this- web_dir; }else { $ret = $this- web_site; } $ret = ereg_replace("/", "\\", $ret); return $ret; } //获取url中的文件名 function get_save_filename() { $ret = $this- get_save_path(); if (strlen($this- web_filename) == 0) { $ret = $ret."\\index.html"; }else { $ret = $ret ."\\".$this- web_filename; } $ret = ereg_replace("/", "\\", $ret); return $ret; }
function get_save_filename() { return $this- url_info- get_save_filename(); } function sub_job_count() { return count($this- sub_job); } function do_sub_job() { $i; global $global_download; //计算总任务数 $count = count($this- sub_job); for ($i = 0; $i $count; $i++) { $url = $this- url_info- calc_path($this- sub_job[$i]); if ($global_download- have_key($url)) { echo "have downloaded: ".$url ."\n"; continue; } $pos = strpos($url, "http://"); if ($pos === false) { echo "error url: $url\n"; }else { //$global_download- add_key($url); $sub = new web_crawl_job($url, $this- m_level + 1, $this- dbc, $this- m_max_deep); unset($sub); } sleep(2); } } //下载图片 function down_page_pic() { $i; global $global_download; $count = count($this- page_images); for ($i = 0; $i $count; $i++) { $url = $this- url_info- calc_path($this- page_images[$i]); if ($global_download- have_key($url)) { echo "have downloaded: ".$url ."\n"; continue; } $pos = strpos($url, "http://"); if ($pos === false) { echo "error image url: $url\n"; }else { echo $url."\n"; //$global_download[$url] = $url; $global_download- add_key($url); $content = file_get_contents($url); if (strlen($content) == 0) { continue; } if (strlen($content) == 0) { $retry_count = 0; while (strlen($content) == 0) { if ($retry_count++ = 2) { break; } sleep(1); $content = file_get_contents($url); } } $this- dbc- put_web_pic($url, addslashes($content), basename($url), strlen($content), $this- m_url); } } } function web_crawl_job($url, $level, $db_in_op, $m_dp) { $this- m_level = $level; $this- m_url = $url; $this- url_info = new web_site_info($url); $this- dbc = $db_in_op; $this- m_max_deep = $m_dp; global $global_download; echo "My Level is:" .$level ."\n"; //检查内容是否为空 $content = file_get_contents($url); if (strlen($content) == 0) { $retry_count = 0; while(strlen($content) == 0) { sleep(10); $content = file_get_contents($url); $retry_count = $retry_count + 1; if ($retry_count 3) { $global_download- add_key($url); return; } } } $md5_str; //取出页面中的url放到任务里面 //分析链接 $reg = "# a[^ ]+href=([\"])(.+)\\1#isU"; preg_match_all($reg, $content, $m); foreach($m[2] as $src) { $this- sub_job[] = $src; } //分析图片 $reg = "# img[^ ]+src=([\"])(.+)\\1#isU"; preg_match_all($reg, $content, $m); foreach($m[2] as $src) { $this- page_images[] = $src; } $db_in_op- put_web_page($url, addslashes($content), strlen($content)); $this- down_page_pic(); $global_download- add_key($url); if ($this- m_level $this- m_max_deep and count($this- sub_job) 0) { //执行子任务 $this- do_sub_job(); } } //检查链接是否被抓取过 class web_grab_history { var $m_db_op; var $m_oldhistory; var $m_newhistory; var $m_subkey; function __construct($db_op) { $this- m_db_op = $db_op; //$db_op- get_grab_history($this- m_oldhistory); } //保存链接历史 function save_history() { foreach($this- m_newhistory as $md5 = $url) { $this- m_db_op- add_history($url, $md5); } } //从数据库查询出链接历史 function load_subkey($subkey) { $this- m_subkey[$subkey] = $subkey; $this- m_db_op- get_grab_history($this- m_oldhistory, $subkey); } function __destruct() {} function have_key($url) { $ret = false; $md5 = md5($url); $subkey = $md5[0] .$md5[1] .$md5[2]; if (strstr($url, "rar") 0) { return true; } //先从内存中查询链接 if (count($this- m_subkey) 0 array_key_exists($subkey, $this- m_subkey) == true) { }else { $this- load_subkey($subkey); } if (count($this- m_oldhistory)) { //$ret |= array_key_exists($url, $this- m_oldhistory); $ret |= array_key_exists($md5, $this- m_oldhistory); } if ($ret == true) { return $ret; } if (count($this- m_newhistory)) { //$ret |= array_key_exists($url, $this- m_newhistory); $ret |= array_key_exists($md5, $this- m_newhistory); } return $ret; } //添加链接历史 function add_key($url) { $md5 = md5($url); //$this- m_newhistory[$url] =$url; $this- m_newhistory[$md5] = $url; if (count($this- m_newhistory) 400) { // } }
scrapy相关专题总结 本月的scrapy已经写完,关于scrapy写了常用的中间件、数据管道、以及scrapy的相关源码,但是感觉可写的内容不是很多,要门是使用相关的要么是一些不用关注的源码。 所以写完scrapy之后还写了些一些其他内容,算是在充数吧,同时预下一个专题是python的数据结构和算法,将对九大算法及其常用数据结构分享,同时将算法应用于数据结构上。
Scrapy框架的使用之Spider的用法 在Scrapy中,要抓取网站的链接配置、抓取逻辑、解析逻辑里其实都是在Spider中配置的。在前一节实例中,我们发现抓取逻辑也是在Spider中完成的。本节我们就来专门了解一下Spider的基本用法。
Scrapy是一个为了爬取网站数据提取结构性数据而编写的应用框架,可以应用于数据挖掘,信息处理或存储历史数据等一些列的程序中。
相关文章
- C# 写入XML文档三种方法详细介绍
- elasticsearch介绍集群,模拟横向扩展节点、节点宕机、改变分片
- iscsi网络存储介绍及客户端配置操作
- 实例介绍Cocos2d-x物理引擎:HelloPhysicsWorld
- JVM之几种垃圾收集器简单介绍
- reactjs全局状态管理:redux介绍
- Android修行手册 - CardView属性介绍
- 【差分算法】一维差分和二维差分算法介绍
- ORACLE SEQUENCE 介绍
- 100集华为HCIE安全培训视频教材整理 | IKE介绍(一)
- CFileDialog的使用方法简单介绍
- 前端开发和后端开发究竟有什么区别?详细介绍
- 【Nginx笔记01】Nginx配置文件介绍、反向代理、负载均衡