Python中使用urllib2模拟登录pixiv遇到了问题

使用的是 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()


Python中使用urllib2模拟登录pixiv遇到了问题

7 回复

你没有验证登录是否成功吗? 看一下 response 或许你没有登录成功呢.


我最近也折腾过pixiv的登录,urllib2确实有点老了,现在用requests配合session会更方便。主要问题是pixiv的登录需要处理POST参数和cookie。

import requests
from bs4 import BeautifulSoup

def login_pixiv(username, password):
    # 创建session保持登录状态
    session = requests.Session()
    
    # 先获取登录页面,拿到必要的token
    login_url = "https://accounts.pixiv.net/login"
    response = session.get(login_url)
    soup = BeautifulSoup(response.text, 'html.parser')
    
    # 查找post_key参数(pixiv的防CSRF token)
    post_key = None
    for input_tag in soup.find_all('input'):
        if input_tag.get('name') == 'post_key':
            post_key = input_tag.get('value')
            break
    
    if not post_key:
        print("无法找到post_key,可能需要检查页面结构")
        return None
    
    # 构建登录数据
    login_data = {
        'pixiv_id': username,
        'password': password,
        'post_key': post_key,
        'return_to': 'https://www.pixiv.net/'
    }
    
    # 发送登录请求
    login_post_url = "https://accounts.pixiv.net/api/login"
    headers = {
        'Referer': 'https://accounts.pixiv.net/login',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
    
    login_response = session.post(login_post_url, data=login_data, headers=headers)
    
    # 检查是否登录成功
    if login_response.status_code == 200:
        # 可以尝试访问需要登录的页面验证
        test_response = session.get("https://www.pixiv.net/")
        if "logout" in test_response.text.lower():
            print("登录成功!")
            return session
        else:
            print("登录可能失败,请检查账号密码")
            return None
    else:
        print(f"登录请求失败,状态码:{login_response.status_code}")
        return None

# 使用示例
if __name__ == "__main__":
    # 替换成你的账号密码
    username = "your_email@example.com"
    password = "your_password"
    
    session = login_pixiv(username, password)
    if session:
        # 现在可以用这个session访问需要登录的页面
        # 例如获取关注列表
        following_url = "https://www.pixiv.net/ajax/following"
        response = session.get(following_url)
        print(response.json())

关键点:

  1. 用requests.Session()保持cookie
  2. 先从登录页面获取post_key(防CSRF token)
  3. 登录时需要正确的Referer和User-Agent
  4. 登录成功后用同一个session访问其他页面

如果遇到验证码或者登录失败,可能需要检查网络环境或者账号状态。

确实是没登录成功,但是不知道哪里出了问题,提交的表单和 header 设置的应该都是没错的,我用 requests 库进行模拟登陆都成功了,所以特别疑惑

你可以用 fiddler (Windows) 或者其他监控程序来看看你 urllib2 和 requests 发送的 HTTP 请求内容具体有什么不同.

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

非常感谢你的方法,用工具抓包发现是因为 p 站在打开登陆界面会设置一个 cookie,用 requests 库发包的时候会自动把那个 cookie 带上,而 urllib2 得自己设置



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

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

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

回到顶部