标签:python
最近手头上有一个项目,是关于新浪微博的,其中有一环要做新浪微博的爬虫。虽然之前把《Python学习手册》和《Python核心编程》都囫囵吞栆地通读完了,不过真正到做项目的时候还是什么都不会。于是在网上找了大量的资料。关于获取新浪微博的内容,大致有两种方法,一种是用纯爬虫,还有一种是用新浪提供的API。
使用API的话,需要先申请一个新浪的开发帐号,这个过程有一点复杂,最终目的是获得新浪的app_key和app_secret。通过引导用户授权,获得access_token,再调用API。虽然新浪提供的API便于开发者开发,不过其限制也是很大的。首先就是用户必须授权,自从新浪接口升级后,很多接口只有对授权的用户使用才有效,像friends_timeline,user_timeline这些获取用户微博的,还有很多其他的接口都有这样的限制。除此以外,access_token有所谓的有效期,开发者为5年,而其他人的话,如果授权级别是测试则只有一天,普通则是7天,具体可看官网介绍。也就是说,超过有效期的话就要重新授权,挺麻烦的。除了这些外,其实它对接口访问的频次也是有限制的。就我们这个项目而言,因为要获取的微博信息与地理位置有关,用API的话不太方便。虽然我花了不少时间研究API,不过最终还是放弃了。
最后我决定使用爬虫来做,感谢以下文章给我提供的思路:
http://blog.csdn.net/codingmirai/article/details/17754645
这篇文章的作者用的是JAVA语言,不过他给我提供了一个很好的想法。他并未用到模拟登录,用的是代理IP,不过在最新的文章中他也说到,新浪因为进行了升级,所以代理IP不能用了,只能进行模拟登录。于是,我又要感谢以下文章的作者:
http://www.jb51.net/article/44779.htm
他帮我解决了模拟登录的问题,主要是通过模拟登录来保存cookies,这我在之后会介绍。
当然在实际做的过程中还是有不少问题的,像是要通过正则表达式来解析html,坑爹的新浪微博的网页源码中文字是以utf-8的形式出现的,也就是像‘\u4f60\u7684‘的形式出现的,看的时候麻烦的不得了,一度让人情绪失控。具体解析方法我会在之后的文中介绍,同时给出源代码。
顺便说一下,本人的编译环境:Linux,Python 2.7版本。一切的源代码都是在这个环境中测试的,如有不同的系统,或是Python3.X版本的请自行修改。。。
这是v1版本,之后可能会进行修改,也可能会做图形化界面。。。
第一次制作,难免有不足之处,欢迎提出意见。。
文件不多,Main.py:主文件;Matcher.py:解析html;WeiboLogin.py,WeiboEncode.py,WeiboSearch.py:用于模拟登录;还有一个userlists文件存放用户名和密码,这是为了防止新浪的反爬虫功能,之后我会介绍(不过并不完美)
主函数(Main.py):
#!/usr/bin/env python #-*-coding:utf-8-*- from WeiboLogin import WeiboLogin import re import urllib2 import Matcher def main(): urlheader=‘http://s.weibo.com/weibo/‘ para=raw_input(‘请输入搜索内容:\n‘) page=1 userlists=open(‘userlists‘).readlines() reg1=re.compile(r‘\\u4f60\\u7684\\u884c\\u4e3a\\u6709\\u4e9b\\u5f02\\u5e38\\uff0c\\u8bf7\\u8f93\\u5165\\u9a8c\\u8bc1\\u7801\\uff1a‘) #你的行为有些异常,请输入验证码 reg2=re.compile(r‘\\u62b1\\u6b49\\uff0c\\u672a\\u627e\\u5230‘)#抱歉,未找到搜索结果 for userlist in userlists: username=userlist.split()[0] password=userlist.split()[1] weibologin=WeiboLogin(username,password) if weibologin.Login()==True: print ‘登录成功‘ user=True #帐号可用 while page<=50 and user: url=urlheader+para+‘&page=‘+str(page) print ‘获取第%d页。。‘ % page f=urllib2.urlopen(url) ###开始匹配网页内容### for line in f: if re.search(r‘pid":"pl_weibo_direct"‘,line): #匹配一定要准确!! if reg2.search(line): print ‘抱歉,未找到结果。。。‘ return else: Matcher.matcher(line) page+=1 break if re.search(r‘pid":"pl_common_sassfilter‘,line): if reg1.search(line): print ‘此帐号被锁,使用下一个帐号‘ user=False #帐号不可用 if __name__==‘__main__‘: main()
首先,爬取的微博是通过输入关键词搜索到的含指定关键字的微博,也就是在:http://s.weibo.com这个网站上搜索到的微博。上文的reg1匹配的是“你的行为有些异常,请输入验证码”。在这里我要解释一下,新浪微博反爬虫功能,当一次性搜索过多页面时便会跳出这条信息,极限大概是30多页,然后便会被这样锁住。我也尝试过使用代理IP来做,不过会显示登录次数过多,致使无法登录的情况。因此我的办法便是使用多个帐号,当某个帐号被锁住时便使用下一个,之后再人工去解锁。这并不是一个好方法,我也还在尝试其他方法,如果有谁有好的方法可以提供给我。
reg2匹配的是没有找到含指定关键词的微博信息。
在网页源代码中,含“pid":"pl_weibo_direct"的一行就是搜索结果,所有搜索到的微博都在这一行上,之后只要针对这一行进行解析就可以了。如果某一行含有”pid":"pl_common_sassfilter"则表示出现帐号被锁的情况。
模拟登录:
关于这部分可以查看上文的链接,或是本人的转载博文:
http://liandesinian.blog.51cto.com/7737219/1549692(对应此项目)
解析网页内容(Matcher.py):
#!/usr/bin/env python #-*-coding:utf-8-*- import re import codecs def matcher(line): reg=r‘<em>(.*?)<\\/em>.*?allowForward=1&url=(.*?)&‘#先将微博内容全部匹配下来,含url sub=r‘color:red‘#子串 reg=re.compile(reg) reg2=re.compile(‘<.*?>‘)#去除其中的<...> mats=reg.findall(line) if mats!=‘[]‘: for mat in mats: with codecs.open(‘result.txt‘,‘a‘,encoding=‘utf-8‘) as f:#写入utf-8文件 if mat[0].find(sub)!=-1:#含有子串 t=reg2.sub(‘‘,mat[0])#剔除其中的<...> f.write(t.decode(‘unicode_escape‘).replace(‘\\‘,‘‘)+‘\n‘)#去除"\" f.write(u‘单条微博信息:‘) f.write(mat[1].replace(‘\\‘,‘‘)+‘\n\n‘)
微博内容在<em>和<\/em>之间。首先先将所有的微博内容匹配下来,这里面可能包含转载微博,而有些转载微博都是不含指定关键词的,所以需要剔除。
基本上现在就是这样的,当然还有很多不足之处,尤其是如何应对新浪的反爬虫功能,还需完善。。。
本文出自 “莲的思念” 博客,请务必保留此出处http://liandesinian.blog.51cto.com/7737219/1549701
标签:python
原文地址:http://liandesinian.blog.51cto.com/7737219/1549701