Scrapy

微信刷票工具

2021-06-07  本文已影响0人  红薯爱帅

1. 概述

闲来无事,做一个微信刷票工具,只是验证了技术思路是否可行。不涉及任何商业利益!

2. 技术预研

微信投票工具很多,有一些是微信官方的,这个可能没办法破解;有一些是需要关注公众号,与微信深度绑定,不容易破解。
剩下一些,要么只获取了微信openid,或者只通过ip做了限制,破解起来简单一些,可以一试。

3. 破解思路

3.1. 确认投票机制

# 在chrome增加一个device,user-agent设置为wechat浏览器即可
Mozilla/5.0 (Linux; Android 7.0; MI 5s Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/64.0.3282.137 Mobile Safari/537.36 wxwork/2.4.16 MicroMessenger/6.3.22 NetType/WIFI Language/zh

Chrome浏览器模拟微信浏览器
Chrome 修改 user agent 简单模拟微信内置浏览器

3.2. 编写投票脚本

基于#2.1的探索,如果只是基于IP的投票限制,反而简单许多。
可以搞一个代理IP池,通过代理IP池发起投票request,基本可以成功。

代理IP池,依赖免费代理源,定时抓取page解析得到可用的代理IP

https://github.com/jhao104/proxy_pool
免费的可用率太低,大概1/10,网速也比较慢;做爬虫的话,可以买一个收费的,当前场景够用

DB_CONN=redis://127.0.0.1:6379/0 sh start.sh
docker run --network host --env DB_CONN=redis://127.0.0.1:6379/0 -p 5010:5010 jhao104/proxy_pool
image.png

投票脚本

import requests
from retry import retry
import random
import time
import string
import hashlib
import pickle
import pathlib


def get_user_agent():
    android_user_agents = [
        'Mozilla/5.0 (Linux; Android 7.0; MI 5s Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/64.0.3282.137 Mobile Safari/537.36 wxwork/2.4.16 MicroMessenger/6.3.22 NetType/WIFI Language/zh',
        'Mozilla/5.0 (Linux; Android 9; PCNM00 Build/PKQ1.190630.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045129 Mobile Safari/537.36 MMWEBID/1926 MicroMessenger/7.0.12.1620(0x27000C37) Process/tools NetType/WIFI Language/zh_CN ABI/arm64',
        'Mozilla/5.0 (Linux; Android 10; LYA-AL00 Build/HUAWEILYA-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045130 Mobile Safari/537.36 MMWEBID/9034 MicroMessenger/7.0.12.1620(0x27000C36) Process/tools NetType/WIFI Language/zh_CN ABI/arm64',
        'Mozilla/5.0 (Linux; Android 9; Redmi Note 8 Pro Build/PPR1.180610.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/67.0.3396.87 XWEB/1171 MMWEBSDK/200201 Mobile Safari/537.36 MMWEBID/229 MicroMessenger/7.0.12.1620(0x27000C37) Process/tools NetType/WIFI Language/zh_CN ABI/arm64',
        'Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/67.0.3396.87 XWEB/1171 MMWEBSDK/191201 Mobile Safari/537.36 MMWEBID/4454 MicroMessenger/7.0.10.1580(0x27100AFF) Process/toolsmp NetType/WIFI Language/zh_CN ABI/arm32',
        'Mozilla/5.0 (Linux; Android 9; BKL-AL20 Build/HUAWEIBKL-AL20; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045130 Mobile Safari/537.36 MMWEBID/7838 MicroMessenger/7.0.11.1600(0x27000B34) Process/tools NetType/4G Language/zh_CN ABI/arm64',
        'Mozilla/5.0 (Linux; Android 10; VOG-AL00 Build/HUAWEIVOG-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045130 Mobile Safari/537.36 MMWEBID/2687 MicroMessenger/7.0.10.1580(0x27000AFE) Process/tools NetType/WIFI Language/zh_CN ABI/arm64',
    ]
    return random.choice(android_user_agents)


def get_req_key():
    letters = random.sample('abcdefghijklmnopqrstuvwxyz', 4)
    digits = random.sample(string.digits, 4)
    return ''.join([f'{x}{y}' for x, y in zip(digits, letters)])


def get_hash(key):
    hash_str = hashlib.md5()
    hash_str.update(key.encode('utf-8'))
    return hash_str.hexdigest()


def get_proxy():
    return requests.get("http://127.0.0.1:5010/get/").json()


def delete_proxy(proxy):
    requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy))


def pickle_dump(data, file):
    with open(file, 'wb') as f:
        pickle.dump(data, f)


def pickle_load(file):
    with open(file, 'rb') as f:
        return pickle.load(f)


@retry(tries=3, delay=1)
def fake_req(proxy):
    req_key = get_req_key()
    user_agent = get_user_agent()
    url = f'http://{req_key}.gd-cj.com/index.php?g=Wap&m=Vote&a=ticket'
    headers = {
        'Content-Length': '114',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'User-Agent': user_agent,
        'Origin': f'http://{req_key}.gd-cj.com',
        'Host': f'{req_key}.gd-cj.com',
        'Referer': f'http://{req_key}.gd-cj.com/index.php?g=Wap&m=Vote&a=detail&token=Fxea5C5sj3562xdE&id=556&zid=2230',
        'X-Requested-With': 'XMLHttpRequest'
    }
    form_data = dict(
        zid='2230', vid='556', token='Fxea5C5sj3562xdE',
        __hash__=f'{get_hash(req_key)}_{get_hash(user_agent)}'
    )
    print(f'proxy: {proxy}')
    resp = requests.post(url, headers=headers, data=form_data,
                         proxies={"http": "http://{}".format(proxy)},
                         timeout=10)
    print(f'response: {resp.status_code} - {resp.content}')

    try:
        resp_json = resp.json()
        return resp_json.get('status') == 108
    except:
        pass

    return False


if __name__ == '__main__':
    used_proxy_file = './proxy_list.pkl'
    total, success = 0, 0
    proxy_list = pickle_load(used_proxy_file) if pathlib.Path(used_proxy_file).exists() else []
    proxy = None

    while True:
        try:
            proxy = get_proxy().get("proxy")
            delete_proxy(proxy)
            if proxy is None:
                time.sleep(10)
                continue
            if proxy in proxy_list:
                time.sleep(0.1)
                continue
            proxy_list.append(proxy)
            pickle_dump(proxy_list, used_proxy_file)
            total += 1

            if fake_req(proxy):
                success += 1
                print('=================== bingo')

        except Exception as e:
            # print(f'exception: {e}')
            pass
        
        print(f'success: {success}, total: {total}')
        time.sleep(random.randint(1, 5))

4. 总结

时间仓促,只是走通思路,代码没有仔细设计与调整,进而更加仿真,减少被发现的可能,比如

IP代理工具jhao104/proxy_pool很赞,省了不少事情。做了几个小优化:

道高一尺,魔高一丈,技术就是在不断的battle情况下,才日益精进

上一篇下一篇

猜你喜欢

热点阅读