上次发了一篇文章,题目叫做《Python使用cookielib和urllib2模拟登陆新浪微博并抓取数据》,里面的代码请不要怀疑,我测试过它是正确的。
新浪微博的模拟登陆,有个前提条件,你用新浪微博账号登陆的时候,新浪没有提示你输入验证码。若需要输入验证码,不好意思这里不作处理,你可以用以下几种方法解决验证码问题:
1、用图片识别软件识别,不过识别正确率会很低
2、登陆的时候如果需要验证码,我们的自己的程序就弹出验证码的图片,自己手工输入
3、外包给验证码输入公司,比如100元,把图片传过去,他给你送回文字结果10000个
程序运行到了后面,我提到urllib2里面的cookie已经存放了我们请求任何页面需要的数据,因此可以用urllib2请求任何页面、发微薄、投票实现任何事情,详细见如下代码,猥琐的分隔栏下面是新增的内容,为了方便,我把上次的代码一起贴出来了,代码注释很给力,大家可以看一看,本代码测试成功:
# coding=utf8 import urllib import urllib2 import cookielib import base64 import re import json import hashlib import time from django.template.defaultfilters import urlencode # 获取一个保存cookie的对象 cj = cookielib.LWPCookieJar() # 将一个保存cookie对象,和一个HTTP的cookie的处理器绑定 cookie_support = urllib2.HTTPCookieProcessor(cj) # 创建一个opener,将保存了cookie的http处理器,还有设置一个handler用于处理http的URL的打开 opener = urllib2.build_opener(cookie_support, urllib2.HTTPHandler) # 将包含了cookie、http处理器、http的handler的资源和urllib2对象板顶在一起 urllib2.install_opener(opener) postdata = { 'entry': 'weibo', 'gateway': '1', 'from': '', 'savestate': '7', 'userticket': '1', 'ssosimplelogin': '1', 'vsnf': '1', 'vsnval': '', 'su': '', 'service': 'miniblog', 'servertime': '', 'nonce': '', 'pwencode': 'wsse', 'sp': '', 'encoding': 'UTF-8', 'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack', 'returntype': 'META' } def get_servertime(): url = 'http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=dW5kZWZpbmVk&client=ssologin.js(v1.3.18)&_=1329806375939' data = urllib2.urlopen(url).read() p = re.compile('\((.*)\)') try: json_data = p.search(data).group(1) data = json.loads(json_data) servertime = str(data['servertime']) nonce = data['nonce'] return servertime, nonce except: print 'Get severtime error!' return None def get_pwd(pwd, servertime, nonce): pwd1 = hashlib.sha1(pwd).hexdigest() pwd2 = hashlib.sha1(pwd1).hexdigest() pwd3_ = pwd2 + servertime + nonce pwd3 = hashlib.sha1(pwd3_).hexdigest() return pwd3 def get_user(username): username_ = urllib.quote(username) username = base64.encodestring(username_)[:-1] return username def main(): username = 'www.crazyant.net' # 微博账号 pwd = 'xxx' # 微博密码 url = 'http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.18)' try: servertime, nonce = get_servertime() except: return global postdata postdata['servertime'] = servertime postdata['nonce'] = nonce postdata['su'] = get_user(username) postdata['sp'] = get_pwd(pwd, servertime, nonce) postdata = urllib.urlencode(postdata) headers = {'User-Agent':'Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0' , 'Referer':'http://vote.weibo.com/vid=1890981' } # 到此已经能够使用urllib2请求新浪任何的内容,登陆成功 req = urllib2.Request( url=url, data=postdata, headers=headers ) result = urllib2.urlopen(req) text = result.read() # print text p = re.compile('location\.replace\(\'(.*?)\'\)') try: login_url = p.search(text).group(1) print login_url # print login_url urllib2.urlopen(login_url) print "login success" except: print 'Login error!' # 测试读取数据,下面的URL,可以换成任意的地址,都能把内容读取下来 #--------------------------------------------------------- # 以下为2012年7月25日21新增: # 对一个投票页面进行投票 #--------------------------------------------------------- # 首先请求一下投票页面,这样做只是为了该页面会返回cookie,我们要保存cookie res = urllib2.urlopen('http://vote.weibo.com/vid=1890981') # 分析了投票的流程,需要如下几个参数的值 votedata = { 'item':'1', 'share':'1', 'poll_id':'1890981', 'poll_category':'0', '_t':'0' } # 原文的那个headers少了一项Referer,结果导致投票不成功,所以这里加上 headers_more = {'User-Agent':'Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0' , 'Referer':'http://vote.weibo.com/vid=1890981' } # 把投票的参数的值进行编码,用于urllib2请求的时候附带 votedata = urllib.urlencode(votedata) # URL、数据、请求HTTP头,我们伪造了一个请求包 req = urllib2.Request( url='http://vote.weibo.com/poll/joined', data=votedata, headers=headers_more ) # 发出请求包,到页面看一看,投票OK result = urllib2.urlopen(req) # 把返回的内容存下来看看,其实这一步无必要了 text = result.read() f = open('out.txt', 'w') f.write(text) print 'ok' main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
# coding=utf8
import
urllib
import
urllib2
import
cookielib
import
base64
import
re
import
json
import
hashlib
import
time
from
django
.
template
.
defaultfilters
import
urlencode
# 获取一个保存cookie的对象
cj
=
cookielib
.
LWPCookieJar
(
)
# 将一个保存cookie对象,和一个HTTP的cookie的处理器绑定
cookie_support
=
urllib2
.
HTTPCookieProcessor
(
cj
)
# 创建一个opener,将保存了cookie的http处理器,还有设置一个handler用于处理http的URL的打开
opener
=
urllib2
.
build_opener
(
cookie_support
,
urllib2
.
HTTPHandler
)
# 将包含了cookie、http处理器、http的handler的资源和urllib2对象板顶在一起
urllib2
.
install_opener
(
opener
)
postdata
=
{
'entry'
:
'weibo'
,
'gateway'
:
'1'
,
'from'
:
''
,
'savestate'
:
'7'
,
'userticket'
:
'1'
,
'ssosimplelogin'
:
'1'
,
'vsnf'
:
'1'
,
'vsnval'
:
''
,
'su'
:
''
,
'service'
:
'miniblog'
,
'servertime'
:
''
,
'nonce'
:
''
,
'pwencode'
:
'wsse'
,
'sp'
:
''
,
'encoding'
:
'UTF-8'
,
'url'
:
'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack'
,
'returntype'
:
'META'
}
def
get_servertime
(
)
:
url
=
'http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=dW5kZWZpbmVk&client=ssologin.js(v1.3.18)&_=1329806375939'
data
=
urllib2
.
urlopen
(
url
)
.
read
(
)
p
=
re
.
compile
(
'\((.*)\)'
)
try
:
json_data
=
p
.
search
(
data
)
.
group
(
1
)
data
=
json
.
loads
(
json_data
)
servertime
=
str
(
data
[
'servertime'
]
)
nonce
=
data
[
'nonce'
]
return
servertime
,
nonce
except
:
print
'Get severtime error!'
return
None
def
get_pwd
(
pwd
,
servertime
,
nonce
)
:
pwd1
=
hashlib
.
sha1
(
pwd
)
.
hexdigest
(
)
pwd2
=
hashlib
.
sha1
(
pwd1
)
.
hexdigest
(
)
pwd3_
=
pwd2
+
servertime
+
nonce
pwd3
=
hashlib
.
sha1
(
pwd3_
)
.
hexdigest
(
)
return
pwd3
def
get_user
(
username
)
:
username_
=
urllib
.
quote
(
username
)
username
=
base64
.
encodestring
(
username_
)
[
:
-
1
]
return
username
def
main
(
)
:
username
=
'www.crazyant.net'
# 微博账号
pwd
=
'xxx'
# 微博密码
url
=
'http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.18)'
try
:
servertime
,
nonce
=
get_servertime
(
)
except
:
return
global
postdata
postdata
[
'servertime'
]
=
servertime
postdata
[
'nonce'
]
=
nonce
postdata
[
'su'
]
=
get_user
(
username
)
postdata
[
'sp'
]
=
get_pwd
(
pwd
,
servertime
,
nonce
)
postdata
=
urllib
.
urlencode
(
postdata
)
headers
=
{
'User-Agent'
:
'Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0'
,
'Referer'
:
'http://vote.weibo.com/vid=1890981'
}
# 到此已经能够使用urllib2请求新浪任何的内容,登陆成功
req
=
urllib2
.
Request
(
url
=
url
,
data
=
postdata
,
headers
=
headers
)
result
=
urllib2
.
urlopen
(
req
)
text
=
result
.
read
(
)
# print text
p
=
re
.
compile
(
'location\.replace\(\'(.*?)\'\)'
)
try
:
login_url
=
p
.
search
(
text
)
.
group
(
1
)
print
login_url
# print login_url
urllib2
.
urlopen
(
login_url
)
print
"login success"
except
:
print
'Login error!'
# 测试读取数据,下面的URL,可以换成任意的地址,都能把内容读取下来
#---------------------------------------------------------
# 以下为2012年7月25日21新增:
# 对一个投票页面进行投票
#---------------------------------------------------------
# 首先请求一下投票页面,这样做只是为了该页面会返回cookie,我们要保存cookie
res
=
urllib2
.
urlopen
(
'http://vote.weibo.com/vid=1890981'
)
# 分析了投票的流程,需要如下几个参数的值
votedata
=
{
'item'
:
'1'
,
'share'
:
'1'
,
'poll_id'
:
'1890981'
,
'poll_category'
:
'0'
,
'_t'
:
'0'
}
# 原文的那个headers少了一项Referer,结果导致投票不成功,所以这里加上
headers_more
=
{
'User-Agent'
:
'Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20100101 Firefox/8.0'
,
'Referer'
:
'http://vote.weibo.com/vid=1890981'
}
# 把投票的参数的值进行编码,用于urllib2请求的时候附带
votedata
=
urllib
.
urlencode
(
votedata
)
# URL、数据、请求HTTP头,我们伪造了一个请求包
req
=
urllib2
.
Request
(
url
=
'http://vote.weibo.com/poll/joined'
,
data
=
votedata
,
headers
=
headers
_more
)
# 发出请求包,到页面看一看,投票OK
result
=
urllib2
.
urlopen
(
req
)
# 把返回的内容存下来看看,其实这一步无必要了
text
=
result
.
read
(
)
f
=
open
(
'out.txt'
,
'w'
)
f
.
write
(
text
)
print
'ok'
main
(
)
|