Python中模拟微信登录成功但无法获取好友列表的解决方案

如题,登录发送消息什么的都能实现,但是就是获取不到好友列表,我也看了好几个 github 模拟登陆的,发现他们代码里面都有一个这个代码,不清楚什么作用,想问问是不是这个问题导致的

https://github.com/littlecodersh/ItChat/blob/bbcb8173b611137a6fd6ac8a4d0a96cb8892fbd6/itchat/components/login.py#L157

for indexUrl, detailedUrl in (
            ("wx2.qq.com"      , ("file.wx2.qq.com", "webpush.wx2.qq.com")),
            ("wx8.qq.com"      , ("file.wx8.qq.com", "webpush.wx8.qq.com")),
            ("qq.com"          , ("file.wx.qq.com", "webpush.wx.qq.com")),
            ("web2.wechat.com" , ("file.web2.wechat.com", "webpush.web2.wechat.com")),
            ("wechat.com"      , ("file.web.wechat.com", "webpush.web.wechat.com"))):
        fileUrl, syncUrl = ['https://%s/cgi-bin/mmwebwx-bin' % url for url in detailedUrl]
        if indexUrl in core.loginInfo['url']:
            core.loginInfo['fileUrl'], core.loginInfo['syncUrl'] = \
                fileUrl, syncUrl
            break

https://github.com/0x5e/wechat-deleted-friends/blob/b37f324f9a4df68c3799da5b7dc2559921293e9b/wdf.py#L151

        # push_uri 与 base_uri 对应关系(排名分先后)(就是这么奇葩..)
        services = [
            ('wx2.qq.com', 'webpush2.weixin.qq.com'),
            ('qq.com', 'webpush.weixin.qq.com'),
            ('web1.wechat.com', 'webpush1.wechat.com'),
            ('web2.wechat.com', 'webpush2.wechat.com'),
            ('wechat.com', 'webpush.wechat.com'),
            ('web1.wechatapp.com', 'webpush1.wechatapp.com'),
        ]
        push_uri = base_uri
        for (searchUrl, pushUrl) in services:
            if base_uri.find(searchUrl) >= 0:
                push_uri = 'https://%s/cgi-bin/mmwebwx-bin' % pushUrl
                break

这两处代码有什么作用呢


Python中模拟微信登录成功但无法获取好友列表的解决方案

5 回复

itchat 里有个 get_friends 方法用于获取好友列表

itchat.get_friends()

没有看源码吗,还是研究一下


这个问题我遇到过。微信网页版登录后,获取好友列表失败通常是因为请求参数不对或者Cookie没处理好。

核心问题在于:登录成功后,需要获取正确的pass_ticketwxsid等参数,这些参数在登录响应里,但微信做了很多反爬措施。

给你一个完整的解决方案:

import requests
import re
import time
import json
from urllib.parse import unquote

class WeChatFriendFetcher:
    def __init__(self):
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        })
        self.base_url = 'https://wx.qq.com'
        
    def login(self):
        """模拟登录流程"""
        # 1. 获取登录UUID
        uuid_url = 'https://login.wx.qq.com/jslogin'
        params = {
            'appid': 'wx782c26e4c19acffb',
            'redirect_uri': 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage',
            'fun': 'new',
            'lang': 'zh_CN',
            '_': int(time.time() * 1000)
        }
        resp = self.session.get(uuid_url, params=params)
        uuid = re.findall(r'window.QRLogin.uuid = "(\S+?)";', resp.text)[0]
        
        # 2. 显示二维码(这里需要用户扫码)
        print(f'请扫描二维码: https://login.weixin.qq.com/l/{uuid}')
        
        # 3. 等待扫码确认
        check_url = 'https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login'
        while True:
            params = {'loginicon': 'true', 'uuid': uuid, 'tip': 0, '_': int(time.time()*1000)}
            resp = self.session.get(check_url, params=params)
            if 'window.code=200' in resp.text:
                # 提取登录跳转URL
                redirect_uri = re.findall(r'window.redirect_uri="(\S+?)";', resp.text)[0]
                break
            time.sleep(2)
        
        # 4. 访问跳转URL获取关键票据
        resp = self.session.get(redirect_uri + '&fun=new')
        from xml.etree import ElementTree as ET
        root = ET.fromstring(resp.text)
        
        self.skey = root.find('skey').text
        self.wxsid = root.find('wxsid').text
        self.wxuin = root.find('wxuin').text
        self.pass_ticket = root.find('pass_ticket').text
        
        # 5. 初始化微信
        init_url = f'{self.base_url}/cgi-bin/mmwebwx-bin/webwxinit'
        params = {
            'r': int(time.time() * 1000),
            'pass_ticket': self.pass_ticket
        }
        data = {
            'BaseRequest': {
                'Uin': self.wxuin,
                'Sid': self.wxsid,
                'Skey': self.skey,
                'DeviceID': f'e{int(time.time() * 1000)}'
            }
        }
        resp = self.session.post(init_url, params=params, json=data)
        self.init_data = resp.json()
        
    def get_friend_list(self):
        """获取好友列表"""
        if not hasattr(self, 'pass_ticket'):
            raise Exception('请先登录')
            
        friend_url = f'{self.base_url}/cgi-bin/mmwebwx-bin/webwxgetcontact'
        params = {
            'r': int(time.time() * 1000),
            'seq': 0,
            'skey': self.skey,
            'pass_ticket': self.pass_ticket
        }
        
        # 关键:需要带上BaseRequest
        data = {
            'BaseRequest': {
                'Uin': self.wxuin,
                'Sid': self.wxsid,
                'Skey': self.skey,
                'DeviceID': f'e{int(time.time() * 1000)}'
            }
        }
        
        resp = self.session.post(friend_url, params=params, json=data)
        
        if resp.status_code == 200:
            result = resp.json()
            if 'MemberList' in result:
                return result['MemberList']
            else:
                print('返回数据:', result)
                return []
        else:
            print(f'请求失败: {resp.status_code}')
            return []

# 使用示例
if __name__ == '__main__':
    wechat = WeChatFriendFetcher()
    wechat.login()
    friends = wechat.get_friend_list()
    print(f'获取到 {len(friends)} 个好友')

关键点:

  1. pass_ticketwxsid必须从登录响应中正确提取
  2. 所有后续请求都需要带上BaseRequest参数
  3. DeviceID需要保持一致性
  4. 注意请求URL的正确性(微信经常改)

常见问题排查:

  • 检查pass_ticket是否为空
  • 确认BaseRequest参数完整
  • 查看返回的JSON数据是否有错误码

如果还是不行,建议用Fiddler或Charles抓包对比正常请求。

一句话总结:确保BaseRequest参数完整且正确。

通讯录的接口应该是 https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact。
早前写了个简单的通讯录导出工具,好像还能用,可以参考下 http://kagent.applinzi.com/wx

看了,很神奇,其他都没问题,就是获取好友为空

用 get_friends 方法也是空? 调试一下看看

回到顶部