码迷,mamicode.com
首页 > 编程语言 > 详细

新浪微博爬虫设计(Python版)

时间:2014-09-07 03:22:35      阅读:670      评论:0      收藏:0      [点我收藏+]

标签: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版)

标签:python

原文地址:http://liandesinian.blog.51cto.com/7737219/1549701

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!