整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Python爬虫-新浪微博(网页版)

近事情比较多,所以从上周就开始写的新浪微博爬虫一直拖到了现在,不过不得不说新浪微博的反扒,我只想说我真的服气了。

爬取数据前的准备

向右奔跑老大说这次的就不限制要爬取哪些内容了,但是给一个参考,有兴趣的可以搞一搞:

参考想法

当我看到这个的时候感觉很有意思和搞头就想去整一整,所以我的一个想法就是去找一个粉丝比较多的人去解析他的分析信息,然后再去解析他粉丝的粉丝,以此类推(感觉解析初始用户的关注的人的粉丝会更好一点,因为他的粉丝比较多,他关注的人粉丝量肯定不会小),但是到后来我就想放弃这个想法了,因为遇到的问题真的一大堆,好了废话不多说,来看一下我抓取的信息:

  • 抓取的信息:

  • 1.微博标题

  • 2.微博nickname

  • 3.标识id

  • 4.微博等级

  • 5.地区

  • 6.毕业院校

  • 7.关注量+URL

  • 8.粉丝量+URL

  • 9.微博量+URL

大致获取的也就这么多信息,因为很多人的信息是不完善的,所以就先抓这么多进行测试。

一个基本的思路

确定了我们要找的信息,接下来就是去解析网页了(一个大的难题要出现了),在我看来获取网页目前遇到的:1.解析源码,2.抓包(json),但是新浪微博这个就比较烦了,他这个是在js中,并且是未加载的(只能用正则或者selenium模拟浏览器了),看到这个之后我想了一段时间并且问了罗罗攀 有没有其他的方法,不行我就用selenium,他说还是推荐正则,解析快一点,selenium是最后的选择,没办法了只好硬着头皮去写正则了,这里在测试正则是否正确,可以使用在线测试工具,进行正则的测试,不必去一遍又一遍运行代码。

源码+个人信息

关注+粉丝+微博

找到这些信息,盯着源码一直瞅,看的我头都大了,其实又快捷的方法ctrl+f

搜索框

现在信息的位置我们都清楚在哪了,那么就是写匹配信息的正则了,这个只能是自己慢慢去写,可以练习正则表达式。

URL+粉丝分页问题

个人主页URL

我们先来看一个示例:http://weibo.com/p/1005051497035431/home?from=page_100505&mod=TAB&is_hot=1#place,

这个URL,给大家提个醒直接用这个是看不到主页信息的,但是在代码的测试源码中我们能看到一个location重定向的连接,是将#之后的部分替换为&retcode=6102,所以URL应该为:http://weibo.com/p/1005051497035431/home?from=page_100505&mod=TAB&is_hot=1&retcode=6102,

我点击连接测试了一下,看到的内容和第一条连接一样,并且还有一点,我们之后获取的所有连接都要替换#之后的内容,来一个示例吧:

urls = re.findall(r'class=\"t_link S_txt1\" href=\"(.*?)\"',data)

如果不进行替换,我们拿获取后的仍然是无法获取到我们要的源码。

粉丝分页问题

我本想可以解析一个人的粉丝,就可以获取大量的数据,可还是栽在了系统限制(我在爬取的时候第五页之后就返回不到数据)

系统限制

看到这个之后,系统限制,这个又是什么,好吧只能看100个粉丝的信息,没办法了也只能继续写下去。所以说我们只要考虑5页的数据,总页数大于5页按五页对待,小于5页的正常去写就可以,这个搞明白之后,就是要去解决分页的连接了,通过三条URL进行对比:

  • 1.http://weibo.com/p/1005051110411735/follow?relate=fans&from=100505&wvr=6&mod=headfans&current=fans#place

  • 2.http://weibo.com/p/1005051110411735/follow?relate=fans&page=2#Pl_Official_HisRelation__60

  • 2.http://weibo.com/p/1005051110411735/follow?relate=fans&page=3#Pl_Official_HisRelation__60

通过这两个URL我们可以看出,差别就在后半部分,除了之前我说的要将是将#之后的部分替换为&retcode=6102,之外还要改动一点,就是follow?之后的内容那么改动后,我们就从第二页去构造URL。

示例代码:

urls = ['http://weibo.com/p/1005051497035431/follow?relate=fans&page={}&retcode=6102'.format(i) for i in range(2,int(pages)+1)]

那么URL分页问题就搞定了,也可以说解决了一个难题。如果你认为新浪微博只有这些反扒的话,就太天真了,让我们接着往下看。

布满荆棘的路

整个获取过程就是各种坑,之前主要是说了数据的获取方式和URL及粉丝分页的问题,现在我们来看一下新浪微博的一些反扒:

首先,在请求的时候必须加cookies进行身份验证,这个挺正常的,但是在这来说他真的不是万能的,因为cookie也是有生存期的,这个在获取个人信息的时候还没什么问题,但是在获取粉丝页面信息的时候就出现了过期的问题,那该怎么解决呢,想了很久,最后通过selenium模拟登录解决了,这个之后在详细说,总之,这一点要注意。

然后,另外一个点,不是每一个人的源码都是一样的,怎么说呢最明显的自己可以去对比下,登录微博后看一下自己粉丝的分页那部分源码和你搜索的那个用户的源码一样不,除此之外其他的源码信息也有不一样,我真的指向说一句,大公司就是厉害。

用户源码

自己本人的源码

大家自习看应该可以看出来不同,所以整体来说新浪微博挺难爬。

代码

代码这一块,确实没整好,问题也比较多,但是可以把核心代码贴出来供大家参考和探讨(感觉自己写的有点乱)

说一下代码结构,两个主类和三个辅助类:

两个主类:第一个类去解析粉丝id,另一个类去解析详细信息(解析的时候会判断id是否解析过)

三个辅助类:第一个去模拟登陆返回cookies(再爬取数据的过程中,好像是只调用了一次,可能是代码的问题),第二个辅助类去返回一个随机代理,第三个辅助类将个人信息写入MySQL。

下边我就将两个主类的源码贴出来,把辅助类相关其他的信息去掉仍然是可以运行的。

1.fansSpider.py

#-*- coding:utf-8 -*-import requestsimport reimport randomfrom proxy import Proxyfrom getCookie import COOKIEfrom time import sleepfrom store_mysql import Mysqlfrom weibo_spider import weiboSpiderclass fansSpider(object):

中间注释的一部分,因为代码在调试,大家参考正则和一些处理方式即可

2.weibo_spider.py

# -*- coding:utf-8 -*-import requestsimport refrom store_mysql import Mysqlimport MySQLdbclass weiboSpider(object):

写的比较乱,大家将就着看,还是我说的只是一个Demo

辅助类之一(存mysql,可以参考Mr_Cxy的python对Mysql数据库的操作小例),其他的两个关于随机代理和获取cookie,在下篇文章会详细讲解

运行结果+数据结果

测试结果

运行截图

200为状态码,说明请求成功

mysql数据库存储结果

总结

目前新浪微博是遇到问题最多的一个,不过也学到了很多知识,比如正则表达式,随机代理等等,在学习的过程中就是遇到的问题越多,积累的越多,进步越快,所以遇到问题和出错也是幸事。说一下代码运行过程中存在遇到的问题吧(可以一块交流解决):

  • 1.有两个id一直在循环,可能是循环那一块存在问题,可以一块交流,解决后会更新文章。

  • 2.解析的速度(单线程比较慢,后续写scrapy版)

  • 3.去重(目前是在将解析过的id写入数据库,然后在解析前进行判断)

个月是1804A班学习网页设计的第四个月,在孟迪老师的细心指导下,同学们提前开始接触了具体的网页项目制作,通过老师的认真辅导和同学们的共同努力,制作出了属于每个人的精美网页,下面请欣赏同学们的作品吧!

作品展示


徐渴欣 | 作品名称:《腾讯视频》官网 | 沧州市场部

李源庆 | 作品名称:《4399小游戏》 | 冀中市场部

骆梦宇 | 作品名称:《新浪微博》 | 冀中市场部

赵佳鹏 | 作品名称:《华为官网》 | 唐山市场部

姚金昊 | 作品名称:《京东官网》 | 沧州市场部


牛杰伟 | 作品名称:《站酷网》 | 直属一市场部

高奇| 作品名称:《小米官网》 |鲁东市场部

孙鑫铭| 作品名称:《网易云音乐》 | 松原市场部

回首望去,同学们通过自己的努力将一个个精美的页面展现在大家面前,自豪感油然而生,也为下个月的综合案例做了完美的铺垫,希望同学们在综合案例中展示出更优秀的自己!

tml>

<head>

<title>网页特效|Linkweb.cn/Js|---对联广告</title>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

</head>

<body style="margin:0px;">

<div align="center">

<center>

<table border="1" width="776" height="3000" cellspacing="0" cellpadding="0">

<tr>

<td width="100%" valign="top"><div align="center" style="color:green;font-size:23pt;font-family:黑体;"><br><br>

页<br>面<br>区<br>域</div></td>

</tr>

</table>

</center>

</div>

<SCRIPT LANGUAGE="JavaScript">

<!--

var showad = true;

var Toppx = 60; //上端位置

var AdDivW = 100; //宽度

var AdDivH = 360; //高度

var PageWidth = 800; //页面多少宽度象素下正好不出现左右滚动条

var MinScreenW = 1024; //显示广告的最小屏幕宽度象素

var ClosebuttonHtml = '<div align="right" style="position: absolute;top:0px;right:0px;margin:2px;padding:2px;z-index:2000;"><a href="javascript:;" onclick="hidead()" style="color:red;text-decoration:none;font-size:12px;">关闭</a></div>'

var AdContentHtml = '<div align="center" style="color:green;font-size:23pt;font-family:黑体;"><br><br>广<br>告<br>内<br>容</div>';

document.write ('<div id="Javascript.LeftDiv" style="position: absolute;border: 1px solid #336699;background-color:#EEEEE2;z-index:1000;width:'+AdDivW+'px;height:'+AdDivH+'px;top:-1000px;word-break:break-all;display:none;">'+ClosebuttonHtml+'<div>'+AdContentHtml+'</div></div>');

document.write ('<div id="Javascript.RightDiv" style="position: absolute;border: 1px solid #336699;background-color:#EEEEE2;z-index:1000;width:'+AdDivW+'px;height:'+AdDivH+'px;top:-1000px;word-break:break-all;display:none;">'+ClosebuttonHtml+'<div>'+AdContentHtml+'</div></div>');

function scall(){

if(!showad){return;}

if (window.screen.width<MinScreenW){

alert("临时提示:\n\n显示器分辨率宽度小于"+MinScreenW+",不显示广告");

showad = false;

document.getElementById("Javascript.LeftDiv").style.display="none";

document.getElementById("Javascript.RightDiv").style.display="none";

return;

}

var Borderpx = ((window.screen.width-PageWidth)/2-AdDivW)/2;

document.getElementById("Javascript.LeftDiv").style.display="";

document.getElementById("Javascript.LeftDiv").style.top=document.body.scrollTop+Toppx;

document.getElementById("Javascript.LeftDiv").style.left=document.body.scrollLeft+Borderpx;

document.getElementById("Javascript.RightDiv").style.display="";

document.getElementById("Javascript.RightDiv").style.top=document.body.scrollTop+Toppx;

document.getElementById("Javascript.RightDiv").style.left=document.body.scrollLeft+document.body.clientWidth-document.getElementById("Javascript.RightDiv").offsetWidth-Borderpx;

}

function hidead()

{

showad = false;

document.getElementById("Javascript.LeftDiv").style.display="none";

document.getElementById("Javascript.RightDiv").style.display="none";

}

window.onscroll=scall;

window.onresize=scall;

window.onload=scall;

//-->

</SCRIPT>

</body>

</html>

    转藏到我的图书馆 献花(1) +1 分享: 微信

    QQ空间QQ好友新浪微博推荐给朋友

    来自: 中华秘方总汇 >《网页特效》