使用 urllib2 模拟登陆 pixiv 遇到了问题

2017-07-31 13:00:19 +08:00
 Reimu

使用的是 Python2+urllib2+cookielib 模拟登陆 pixiv,post 表单后尝试获取个人收藏页面但是得到的是 pixiv 的登录页面,怀疑是模拟登陆的过程有问题,排查了一天也没解决,实在不知道哪里错了。。求各位大手看一下,谢谢。。(账号和密码我给抹去了)

import re,urllib,urllib2
import cookielib

headers = {
            'Referer': 'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) '
                          'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
        }
request_loginpage = urllib2.Request(r'https://accounts.pixiv.net/login')
getLoginPage = urllib2.urlopen(request_loginpage)
pattern = re.compile(r'<input type="hidden" name="post_key" value="(.*?)">')
getPostKey = re.search(pattern,getLoginPage.read())
postKey = getPostKey.group(1)
print postKey
data = {
    'pixiv_id':'id',
    'password':'password',
    'post_key':postKey,
    'return_to':'https://www.pixiv.net/'
}

cookie = cookielib.CookieJar()
handler=urllib2.HTTPCookieProcessor(cookie)
opener = urllib2.build_opener(handler)

encodeData = urllib.urlencode(data)
request = urllib2.Request('https://accounts.pixiv.net/api/login?lang=zh',encodeData,headers)

response = opener.open(request)

request2 = urllib2.Request('https://www.pixiv.net/bookmark.php')
response2 = opener.open(request2)
print response2.read()
3082 次点击
所在节点    Python
6 条回复
ivechan
2017-07-31 13:16:28 +08:00
你没有验证登录是否成功吗? 看一下 response 或许你没有登录成功呢.
Reimu
2017-07-31 13:19:20 +08:00
@ivechan 确实是没登录成功,但是不知道哪里出了问题,提交的表单和 header 设置的应该都是没错的,我用 requests 库进行模拟登陆都成功了,所以特别疑惑
ivechan
2017-07-31 14:46:00 +08:00
@Reimu 你可以用 fiddler (Windows) 或者其他监控程序来看看你 urllib2 和 requests 发送的 HTTP 请求内容具体有什么不同.
qwjhb
2017-07-31 15:37:27 +08:00
github 上看来下 好像都是用 oauth 的

def auth(self, username=None, password=None, refresh_token=None):
"""Login with password, or use the refresh_token to acquire a new bearer token"""

url = 'https://oauth.secure.pixiv.net/auth/token'
headers = {
'App-OS': 'ios',
'App-OS-Version': '10.3.1',
'App-Version': '6.7.1',
'User-Agent': 'PixivIOSApp/6.7.1 (iOS 10.3.1; iPhone8,1)',
}
data = {
'get_secure_url': 1,
'client_id': 'bYGKuGVw91e0NMfPGp44euvGt59s',
'client_secret': 'HP3RmkgAmEGro0gn1x9ioawQE8WMfvLXDz3ZqxpK',
}

if (username is not None) and (password is not None):
data['grant_type'] = 'password'
data['username'] = username
data['password'] = password
elif (refresh_token is not None) or (self.refresh_token is not None):
data['grant_type'] = 'refresh_token'
data['refresh_token'] = refresh_token or self.refresh_token
else:
raise PixivError('[ERROR] auth() but no password or refresh_token is set.')

r = self.requests_call('POST', url, headers=headers, data=data)
if (r.status_code not in [200, 301, 302]):
if data['grant_type'] == 'password':
raise PixivError('[ERROR] auth() failed! check username and password.\nHTTP %s: %s' % (r.status_code, r.text), header=r.headers, body=r.text)
else:
raise PixivError('[ERROR] auth() failed! check refresh_token.\nHTTP %s: %s' % (r.status_code, r.text), header=r.headers, body=r.text)

token = None
try:
# get access_token
token = self.parse_json(r.text)
self.access_token = token.response.access_token
self.user_id = token.response.user.id
self.refresh_token = token.response.refresh_token
except:
raise PixivError('Get access_token error! Response: %s' % (token), header=r.headers, body=r.text)

# return auth/token response
return token
Reimu
2017-07-31 19:14:46 +08:00
@ivechan 非常感谢你的方法,用工具抓包发现是因为 p 站在打开登陆界面会设置一个 cookie,用 requests 库发包的时候会自动把那个 cookie 带上,而 urllib2 得自己设置
timwei
2017-08-01 17:32:08 +08:00
@Reimu

Pixiv 在用户首次访问时,会设置一个 post_key 做为 CSRF 防护

并不用读取 cookies,这个 post_key 会放在响应的 body 中

你可以用 /postKey\":\"([a-zA-Z0-9]+)\"/ 匹配得到

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/379219

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX