自己编写一个简单的微博爬虫
自己编写一个简单的微博爬虫
很多做社交媒体数据分析的同学需要采集一些新浪微博上的数据,新浪微博虽然有提供api,但免费的api对获取的数据项和获取的频率都有很大的限制,商业版api据说限制较少,但是作为屌丝学生党拿来那么多钱买买商业版的api?!!!用类似于火车头采集器这种工具又很难解决问题,因此我们往往需要自己编写微博爬虫。下面我简单介绍一下我在编写微博爬虫期间遇到的问题和我的解决思路。
微博登陆问题
爬虫需先登录到新浪微博,否则微博一直返回登录页面不给数据。目前的解决办法有:
- 先手动用浏览器登录,然后导出cookie ,再写脚本加载cookie到爬虫的http协议里,这样就获取了session 和cookie,解决了身份认证的问题。
- 就是本文要介绍的模拟登陆。
注:以下模拟登陆部分是参考文章:python模拟新浪微博登陆功能(新浪微博爬虫) 所写,我在该文章的基础上做了一些小改动。
第一种方案操作较为繁琐,尤其是想要用多个微博马甲轮询,降低马甲被封概率的话。第二种方案就可以实现批量马甲登录,但是有的账号登录的时候可能需要输入验证码,验证码识别起来比较困难,目前我还没有解决这个问题。
下面是我的模拟登陆代码
WeiboLogin.py:等一了登录类 WeiboLogin.最后调用WeiboLogin.Login()方法会返回一个带有当前马甲会话cookie的opener。多个马甲登录模拟登陆的话,可以实例化多个WeiboLogin,调用它们的Login()方法返回不同的opener 带有各自的会话cookie,降低账号被封的风险。
![](/assets/blank.gif)
import urllib2,traceback,cookielib import WeiboEncode import WeiboSearch class WeiboLogin:def __init__(self, user, pwd, enableProxy=False):"初始化WeiboLogin,Proxy默认关闭" print "Initializing WeiboLogin..."self.userName = userself.passWord = pwdself.enableProxy = enableProxyself.cookiejar = cookielib.LWPCookieJar()#建立cookie self.serverUrl = "http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.11)&_=1379834957683"self.loginUrl = "http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.11)"self.postHeader = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0'}def Login(self):#"登陆程序" ERROR_COUNT =0opener = self.EnableCookie()while True:if ERROR_COUNT>3:print 'login error!'return Falsetry:url = "http://weibo.com/"req = urllib2.Request(url, None, self.postHeader)opener.open(req)serverTime, nonce, pubkey, rsakv = self.GetServerTime(opener)#登陆的第一步postData = WeiboEncode.PostEncode(self.userName, self.passWord, serverTime, nonce, pubkey, rsakv)#加密用户和密码print "Post data length:\n", len(postData)req = urllib2.Request(self.loginUrl, postData, self.postHeader)print "Posting request..."result = opener.open(req)#登陆的第二步——解析新浪微博的登录过程中3text = result.read()loginUrl = WeiboSearch.sRedirectData(text)#解析重定位结果req = urllib2.Request(loginUrl, None, self.postHeader)temp = opener.open(loginUrl)except:print traceback.format_exc()print 'retrying......'ERROR_COUNT+=1continueif WeiboSearch.sCheckLoginResult(temp.read()):#检查登录返回信息print 'Login sucess!'return openerelse :print 'login error'return Falsedef EnableCookie(self):#"Enable cookie & proxy (if needed)."cookie_support = urllib2.HTTPCookieProcessor(self.cookiejar) if self.enableProxy:proxy_support = urllib2.ProxyHandler({'http':'http://xxxxx.pac'})#使用代理opener = urllib2.build_opener(proxy_support, cookie_support, urllib2.HTTPHandler)print "Proxy enabled"else:opener = urllib2.build_opener(cookie_support, urllib2.HTTPHandler) return openerdef GetServerTime(self,opener):"Get server time and nonce, which are used to encode the password"print "Getting server time and nonce..."req = urllib2.Request(self.serverUrl, None, self.postHeader)serverData = opener.open(req).read()#得到网页内容print serverData try:serverTime, nonce, pubkey, rsakv = WeiboSearch.sServerData(serverData)#解析得到serverTime,nonce等return serverTime, nonce, pubkey, rsakvexcept:print 'Get server time & nonce error!'return None
![](/assets/blank.gif)
WeiboSearch.py:主要是WebLogin.py需要的一些 检索、分析、检查函数
![](/assets/blank.gif)
import re import json def sServerData(serverData):"Search the server time & nonce from server data"p = re.compile('\((.*)\)')jsonData = p.search(serverData).group(1)data = json.loads(jsonData)serverTime = str(data['servertime'])nonce = data['nonce']pubkey = data['pubkey']# rsakv = data['rsakv']# print "Server time is:", serverTimeprint "Nonce is:", noncereturn serverTime, nonce, pubkey, rsakvdef sRedirectData(text):p = re.compile('location\.replace\([\'"](.*?)[\'"]\)')loginUrl = p.search(text).group(1)print 'loginUrl:',loginUrlreturn loginUrldef sCheckLoginResult(text):p = re.compile('parent\.sinaSSOController\.feedBackUrlCallBack\(\{"result":true,"userinfo":\{"uniqueid":')if p.search(text):return Trueelse :return False
![](/assets/blank.gif)
WeiboEncode.py:用户名密码加密操作
![](/assets/blank.gif)
import urllib import base64import rsa import binasciidef PostEncode(userName, passWord, serverTime, nonce, pubkey, rsakv):"Used to generate POST data"encodedUserName = GetUserName(userName)#用户名使用base64加密encodedPassWord = get_pwd(passWord, serverTime, nonce, pubkey)#目前密码采用rsa加密postPara = {'entry': 'weibo','gateway': '1','from': '','savestate': '7','userticket': '1','ssosimplelogin': '1','vsnf': '1','vsnval': '','su': encodedUserName,'service': 'miniblog','servertime': serverTime,'nonce': nonce,'pwencode': 'rsa2','sp': encodedPassWord,'encoding': 'UTF-8','prelt': '115','rsakv': rsakv, 'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack','returntype': 'META'}postData = urllib.urlencode(postPara)#网络编码return postDatadef GetUserName(userName):"Used to encode user name"userNameTemp = urllib.quote(userName)userNameEncoded = base64.encodestring(userNameTemp)[:-1]return userNameEncoded def get_pwd(password, servertime, nonce, pubkey):rsaPublickey = int(pubkey, 16)key = rsa.PublicKey(rsaPublickey, 65537) #创建公钥message = str(servertime) + '\t' + str(nonce) + '\n' + str(password) #拼接明文js加密文件中得到passwd = rsa.encrypt(message, key) #加密passwd = binascii.b2a_hex(passwd) #将加密信息转换为16进制。return passwd
![](/assets/blank.gif)
使用方法:
from WeiboLogin import WeiboLoginuser_name ='abc@sina.com' passwd ='1234' opener = WeiboLogin(user_name, passwd).Login()
ip请求过频问题:
即使模拟登陆成功,写好爬虫程序,你会发现爬虫爬一小会后又不返回数据了。这是因为微博服务器监测到该ip请求数据的频率异常,一般采取的策略是加代理ip(一般的http代理即可,最好是高匿的)。而且经测试,每次更换代理的ip的时候不用重新登录,直接用当前生成的opener添加更换的ip代理handler即可:
proxy_handler = urllib2.ProxyHandler({"http" : proxyServer,"https" : proxyServer })opener.add_handler(proxy_handler)
一开始我发现网上有很多免费的http代理,也搜集了不少,结果测试一遍发现很少有能用的,即使勉强能用也极不稳定,代理有效时间也很短。后来发现有小伙伴自己扫描SOCKS4 / SOCKS5代理 或者http代理的,因为我采集的数据量很少,不准备投入那么多,所以简单租用了一下别人提供的代理(租金对学生党来说还能接受)。
爬虫的健壮性问题:
一方面考虑到爬虫脚本要长时间运行,中间可能会遇到网络不稳定、断电等不可抗力因素,因此建议及时的存储爬取结果,有条件的可以采用分布式采集,我的策略是依托数据库做了一个简单的"断点”机制,同时在代码的网络请求和文件IO的地方做了异常处理和失败重试操作。
另一方面由于微博有时会改变版面,导致原来的代码里的解析正则表达式或者BeautifulSoup 定位失效了。我的解决方案是,尽量将自己的采集任务分类,做成不同的模块,各个模块之间做到松耦合,这样更容易维护。
个人感想:如果采集少量数据,仅仅用来写个大作业或者发篇论文的话,不用过于在乎这部分结构,浪费精力不说,很可能会本末倒置。新浪微博的反爬意识也比较高,会时不时出一些新的反爬策略,辛辛苦苦设计的“优美的结构”在新的反爬策略面前可能成为鸡肋,白费工服
自己编写一个简单的微博爬虫相关推荐
- python编写登录_通过Python编写一个简单登录功能过程解析
通过Python编写一个简单登录功能过程解析 需求: 写一个登录的程序, 1.最多登陆失败3次 2.登录成功,提示欢迎xx登录,今天的日期是xxx,程序结束 3.要检验输入是否为空,账号和密码不能为空 ...
- 如何编写一个简单的 Python 程序
本教程将教你如何编写一个简单的 Python 程序.我们将从解释 Python 程序是什么开始,然后继续讨论语法的各个方面,即语言的结构. 什么是 Python? Python是一种越来越受欢迎的编程 ...
- 编写一个最简单的.php,学习猿地- 说明 如果我们要编写一个简单的PHP脚本,需要学习哪些...
说明 如果我们要编写一个简单的 PHP 脚本,需要学习哪些基础知识呢? PHP 基础 PHP 脚本可放置于文档中的任何位置. 标准 的 PHP 脚本以 <?php 开头,以 ?> 结尾: ...
- java编写存钱_用Java编写一个简单的存款
package desposit.money; public class DespositMoney { public static void main(String[] args) { Custom ...
- python脚本编写_如何用Python包编写一个简单的脚本,表达你对父母的爱?
全文共2800字,预计学习时长6分钟 在繁忙的工作生活中,我们经常忘记给所爱的人发WhatsApp.本教程将使用Python包Twilio编写一个简单的Python脚本来发送WhatsApp消息.我们 ...
- 用java编写一个简单计算器
java 采用java编写一个简单计算器,使用awt和swing 代码如下: import java.awt.Color; import java.awt.Font; import java.awt. ...
- 用 Go 编写一个简单的 WebSocket 推送服务
用 Go 编写一个简单的 WebSocket 推送服务 本文中代码可以在 github.com/alfred-zhon- 获取. 背景 最近拿到需求要在网页上展示报警信息.以往报警信息都是通过短信,微 ...
- ros如何编译python文件_Python为ROS编写一个简单的发布者和订阅者
Python为ROS编写一个简单的发布者和订阅者 1.创建工作空间 1.1建立文件夹hello_rospy,再在该目录下建立子目录src,并创建工作空间 mkdir -p ~/hello_rospy/ ...
- Java制作一个盒子程序_编写一个简单的Java程序,模拟计算器的功能。
提问:编写一个简单的Java程序,模拟计算器的功能. 网友回答: 程序参考: import java.awt.*; import java.awt.event.ActionEvent; import ...
最新文章
- java 函数内部类_java 内部类详解 转
- openfire在windows环境和linux环境下的配置
- DeepMatch :用于推荐广告的深度召回匹配算法库
- hibernate.cfg.xml hibernate 配置文件模板
- java用while循环语句输出1-100内的奇数和
- SpringBoot热部署环境搭建和原理分析
- JDK 环境变量配置
- 拼多多:有营销号“骗粉博出位” 将用法律武器维权
- Angular2之路由学习笔记
- 学生档案信息管理案例
- java开发app教程,就是这么简单
- Python 3 《List》入门练习
- linux中时间转换date
- Unity URP入门实战
- UE5中置人利用iphone驱动虚拟人面部
- 基因测序与高通量测序区别
- AIOT人工智能物联网+项目实战
- 《加州之梦》 (California Dreaming)
- 华清远见C语言笔试题,华清远见C语言学习笔记五
- 旗舰计算机系统蓝图,【求助】求助大神给这些蓝图一个参考定价
热门文章
- 武汉理工大学余家头校区计算机学院研究生宿舍(男生)条件如何,武汉理工大学余家头校区在哪 环境好不好...
- win32gui激活、关闭窗口方法
- python高性能web框架排行榜_目前最受欢迎的12个Python web框架,你用过几个?
- 简单史玉柱:成就曲径通幽的营销传奇故事
- 稳压二极管的应用及注意事项
- 游戏组装电脑配置推荐2023 游戏组装电脑配置推荐2023
- java获取项目绝对路径_如何获取项目绝对路径?
- 小工具批量将mp3音频格式转换为wav格式
- ajax异步请求,以及ajax异步返回的数据的处理方案
- 列表ListView