登录  /  注册

博客爬取系统

php中文网
发布: 2016-08-08 09:30:25
原创
893人浏览过

引言

  周末没事干,无聊,使用php做了个博客抓取系统,我经常访问的是cnblogs,当然从博客园(看看我还是很喜欢博客园的)开始入手了,我的抓取比较简易,获取网页内容,然后通过正则匹配,获取到想要的东西,然后保存数据库,当然了,在实际过程中会遇到一些问题。做这个之前已经想好了,要做成可扩充的,以后要是哪天想添加csdn、51cto、新浪博客这些内容了可以很容易的扩展。

那些东西可以抓取?

  首先要说些,这个是个简易的抓取,不是所有网页中看到的东西都可以抓取,有些东西是抓取不到的,就像下面这些

  其中圈红的阅读次数、评论次数、推荐次数、反对次数、评论……,这些是通过js调用ajax动态获取的,所以是获取不到的,其实就一句话,你打开一个网页,然后右键点击查看源代码,在源代码中直接看不到的,这种简易抓取可能就有问题,要抓取那些ajax填充的内容,要想想其他办法,之前看见过一篇文章,有人先通过浏览器加载完网页,然后对整个dom就行筛选(那篇文章也说了,这样效率很低),当然了,拼接这些js请求也是可以的,估计会比较麻烦。

爬取的思路

  首先说下爬取深度depth

比如从链接a开始爬,如果depth是1,获取玩当前链接的内容就完事,如果depth是2的话,就从a链接的内容中再去按指定的规则匹配链接,对匹配到的链接也做depth为1的处理,以此类推,depth是获取链接的深度、层级。这样爬虫才可以”爬动起来“。

  当然了,用一个链接去爬特定的内容,这个爬到的东西是很有限的,或者有可能还没爬起来就死掉了(往后的层级没有匹配到内容),所以在爬取的时候可以设置多个起始链接。当然了,在爬取的时候很可能会遇到很多重复的链接,所以还得给抓取到的链接做记号,防止重复获取相同的内容,造成冗余。有几个变量来缓存这些信息,格式如下

第一,就是一个hash数组,键值是url的md5值,状态是0,维护一个不重复的url数组,形如下面的形式

<span>Array</span><span>
(
    [bc790cda87745fa78a2ebeffd8b48145] </span>=&gt; 0<span>
    [9868e03f81179419d5b74b5ee709cdc2] </span>=&gt; 0<span>
    [4a9506d20915a511a561be80986544be] </span>=&gt; 0<span>
    [818bcdd76aaa0d41ca88491812559585] </span>=&gt; 0<span>
    [9433c3f38fca129e46372282f1569757] </span>=&gt; 0<span>
    [f005698a0706284d4308f7b9cf2a9d35] </span>=&gt; 0<span>
    [e463afcf13948f0a36bf68b30d2e9091] </span>=&gt; 0<span>
    [23ce4775bd2ce9c75379890e84fadd8e] </span>=&gt; 0
    ......<span>
)</span>
登录后复制

第二个就是要获取的url数组,这个地方还可以优化,我是将所有的链接链接全部获取到数组中,再去循环数组获取内容,就等于是说,所有最大深度减1的内容都获取了两次,这里可以直接在获取下一级内容的时候顺便把内容获取了,然后上面的数组中状态修改为1(已经获取),这样可以提高效率。先看看保存链接的数组内容:

<span>Array</span><span>
(
    [</span>0] =&gt; <span>Array</span><span>
        (
            [</span>0] =&gt; http:<span>//</span><span>zzk.cnblogs.com/s?t=b&amp;w=php&amp;p=1</span>
<span>        )
    [</span>1] =&gt; <span>Array</span><span>
        (
            [</span>0] =&gt; http:<span>//</span><span>www.cnblogs.com/baochuan/archive/2012/03/12/2391135.html</span>
            [1] =&gt; http:<span>//</span><span>www.cnblogs.com/ohmygirl/p/internal-variable-1.html</span>
            [2] =&gt; http:<span>//</span><span>www.cnblogs.com/zuoxiaolong/p/java1.html</span>
                ......<span>
        )

    [</span>2] =&gt; <span>Array</span><span>
        (
            [</span>0] =&gt; http:<span>//</span><span>www.cnblogs.com/ohmygirl/category/623392.html</span>
            [1] =&gt; http:<span>//</span><span>www.cnblogs.com/ohmygirl/category/619019.html</span>
            [2] =&gt; http:<span>//</span><span>www.cnblogs.com/ohmygirl/category/619020.html</span>
                ......<span>
        )

)</span>
登录后复制

最后将所有的链接拼为一个数组返回,让程序循环获取连接中的内容。就像上面的获取层级是2,0级的链内容接获取过了,仅仅用来获取1级中的链接,1级中的所有链接内容也获取过了,仅仅用来保存2级中的链接,等到真正获取内容的时候又会对上面的内容进行一次获取,而且上面的hash数组中的状态都没有用到。。。(有待优化)。

  还有一个获取文章的正则,通过分析博客园中的文章内容,发现文章标题、正文部分基本都可以很规则的获取到

标题,标题html代码的形式都是下图的那种格式,可以很轻松的用下面的正则匹配到

<span>#</span><span><a>]*?&gt;(.*?)#is</a></span>
登录后复制

正文,正文部分是可以通过正则表达式的高级特性平衡组很容易获取到的,但弄了半天发现php好像对平衡组支持的不是很好,所以放弃额平衡组,在html源码中发现通过下面的正则也可以很容易匹配到文章正文的内容,每篇文章基本都有下图中的内容

<span>#</span><span>(<div>]*?&gt;.*)<div>#is



<blockquote>
<p>开始:</p>
<p><img alt="" src="http://image.codes51.com/Article/image/20150127/20150127100647_9869.png"    style="max-width:90%"  style="max-width:90%" border="0"></p>
<p>结束:</p>
<p><img alt="" src="http://image.codes51.com/Article/image/20150127/20150127100648_0650.png"    style="max-width:90%"  style="max-width:90%" border="0"> </p>
</blockquote>
<p>  博客的发布时间也是可以获取到的,但有些文章在获取发布时间的时候可能会找不到,这个就不列在这里了,有了这些东西就可以爬取内容了。</p>
<p>开始爬取</p>
<p>  开始爬取内容了,最初我设置的爬取深度是2级,初始页面是博客园首页,发现爬取不了多少内容,后来发现博客园首页有个页码导航</p>
<p><img alt="" src="http://image.codes51.com/Article/image/20150127/20150127100648_0962.png"    style="max-width:90%"  style="max-width:90%" border="0">  就试图拼接成页码格式http://www.cnblogs.com/#p2,循环200次,以每页为起始页面,深度为2去抓取。但我高兴的太早了,开了几个进程跑了好久程序,抓了几十万条,后来发现完全在重复,都是从第一页中抓取的,因为博客园首页点击导航的时候(除了第一页),都是ajax请求获取到的。。。。看来博客园还是考虑到这个问题,因为大多数人都是只打开首页,不会去点击后面的内容(我可能偶尔会去点击下一页),所以为了在防止初级抓取者去抓取和性能发面做权衡,将第一页设置为静态网页的方式,缓存有效期是几分钟(或者是根据跟新频率,当更新多少篇的时候去更新缓存,或者两者的结合),这也是为什么有时候发布的文章,过一会儿才会显示出来的原因(我猜的^_^)。</p>
<p>  难道不能一次性抓取很多内容吗?后来我发现这个地方使用的全部是静态网页</p>
<p><img alt="" src="http://image.codes51.com/Article/image/20150127/20150127100648_1119.png"    style="max-width:90%"  style="max-width:90%" border="0"></p>
<p>     从找找看这个地方获取到的内容都是静态的,包括最下面的导航链接中的所有页面都是静态的,而且,这个搜索右边还有筛选条件,可以更好的提高抓取的质量。好了有了这个入口,就可以获取到好多高质量的文章了,下面是循环抓取100页的代码</p>
<blockquote>
<p>
</p>
<pre class="brush:php;toolbar:false"><span>for</span>(<span>$i</span>=1;<span>$i</span>$i++<span>){
            </span><span>echo</span> "PAGE{<span>$i</span>}*************************[begin]***************************\r"<span>;
            </span><span>$spidercnblogs</span> = <span>new</span> C\Spidercnblogs("http://zzk.cnblogs.com/s?t=b&amp;w=php&amp;p={$i}"<span>);
            </span><span>$urls</span> = <span>$spidercnblogs</span>-&gt;<span>spiderUrls();
            </span><span>die</span><span>();
            </span><span>foreach</span> (<span>$urls</span> <span>as</span> <span>$key</span> =&gt; <span>$value</span><span>) {
                </span><span>$cnblogs</span>-&gt;grap(<span>$value</span><span>);
                </span><span>$cnblogs</span>-&gt;<span>save();
            }
        }</span>
登录后复制

  至此,就可以去抓去自己喜欢的东西了,抓取速度不是很快,我在一台普通pc上面开了10个进程,抓了好几个小时,才获取到了40多万条数据,好了看看抓取到的内容稍微优化之后的显示效果,这里面加上了博客园的基础css代码,可以看出效果和

抓取到的内容稍作修改:

原始内容

 

 

 再看下文件目录结构,也是用上篇的自制目录生成工具生成的:

 +myBlogs-master
    +controller
        |_Blog.php
        |_Blogcnblogs.php
        |_Spider.php
        |_Spidercnblogs.php
    +core
        |_Autoload.php
    +interface
        |_Blog.php
    +lib
        |_Mysql.php
    +model
        |_Blog.php
    |_App.php

 效果还是很不错的,这里再猜下推酷这种专门爬取的网站的工作方式,一个常驻进程,隔一段时间去获取一次内容(比如说首页),如果有新鲜的内容入库,没有的话放弃这次获取的内容,等待下次获取,当时间很小的时候就可以一篇不漏的抓取的”新鲜“的内容。

这是github地址:

github——myBlogs

  本文版权归作者iforever(luluyrt@163.com)所有,未经作者本人同意禁止任何形式的转载,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

以上就介绍了博客爬取系统,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

智能AI问答
PHP中文网智能助手能迅速回答你的编程问题,提供实时的代码和解决方案,帮助你解决各种难题。不仅如此,它还能提供编程资源和学习指导,帮助你快速提升编程技能。无论你是初学者还是专业人士,AI智能助手都能成为你的可靠助手,助力你在编程领域取得更大的成就。
来源:php中文网
收藏 点赞
上一篇:阅读DVWA系统代码之config.inc.php 下一篇:微信账户绑定
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
最新问题
关于CSS思维导图的课件在哪? 课件
凡人来自于2024-04-16 10:10:18
相关专题
更多>
热门推荐
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号