微信刷票工具

1. 概述

閑來無事澳化,做一個(gè)微信刷票工具持寄,只是驗(yàn)證了技術(shù)思路是否可行源梭。不涉及任何商業(yè)利益娱俺!

2. 技術(shù)預(yù)研

微信投票工具很多,有一些是微信官方的废麻,這個(gè)可能沒辦法破解荠卷;有一些是需要關(guān)注公眾號,與微信深度綁定烛愧,不容易破解油宜。
剩下一些,要么只獲取了微信openid怜姿,或者只通過ip做了限制慎冤,破解起來簡單一些,可以一試沧卢。

3. 破解思路

3.1. 確認(rèn)投票機(jī)制

  • 打開手機(jī)微信蚁堤,進(jìn)入投票頁面,下拉可以看到投票網(wǎng)站的地址搏恤,如果不是wx的违寿,可以嘗試搞一下子

  • 通過電腦chrome瀏覽器模擬微信瀏覽器湃交,打開投票頁面熟空,確認(rèn)投票api

  • 確認(rèn)投票api比較麻煩,需要慢慢摸索搞莺,有時(shí)候需要看看上下文的請求息罗,有時(shí)候可能需要看看js源碼,分析投票機(jī)制才沧,也需要反復(fù)嘗試

# 在chrome增加一個(gè)device迈喉,user-agent設(shè)置為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 簡單模擬微信內(nèi)置瀏覽器

3.2. 編寫投票腳本

基于#2.1的探索,如果只是基于IP的投票限制温圆,反而簡單許多挨摸。
可以搞一個(gè)代理IP池,通過代理IP池發(fā)起投票request岁歉,基本可以成功得运。

代理IP池,依賴免費(fèi)代理源锅移,定時(shí)抓取page解析得到可用的代理IP

https://github.com/jhao104/proxy_pool
免費(fèi)的可用率太低熔掺,大概1/10,網(wǎng)速也比較慢非剃;做爬蟲的話置逻,可以買一個(gè)收費(fèi)的,當(dāng)前場景夠用

  • 代碼clone下來之后备绽,如何執(zhí)行
DB_CONN=redis://127.0.0.1:6379/0 sh start.sh
  • 也可以通過docker啟動
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. 總結(jié)

時(shí)間倉促券坞,只是走通思路鬓催,代碼沒有仔細(xì)設(shè)計(jì)與調(diào)整,進(jìn)而更加仿真报慕,減少被發(fā)現(xiàn)的可能深浮,比如

  • request里面__hash__字段的生成機(jī)制(隨意生成的,貌似不要也行眠冈。飞苇。)
  • req_key的作用是啥(只是仿照原來的規(guī)則,生成了一個(gè))

IP代理工具jhao104/proxy_pool很贊蜗顽,省了不少事情布卡。做了幾個(gè)小優(yōu)化:

  • 有一個(gè)bugfix
  • 解析免費(fèi)代理源,只看了第一頁雇盖,修改為前10頁
  • 內(nèi)部還有一些邏輯可以優(yōu)化

道高一尺忿等,魔高一丈,技術(shù)就是在不斷的battle情況下崔挖,才日益精進(jìn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贸街,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子狸相,更是在濱河造成了極大的恐慌薛匪,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脓鹃,死亡現(xiàn)場離奇詭異逸尖,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瘸右,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門娇跟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人太颤,你說我怎么就攤上這事苞俘。” “怎么了龄章?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵吃谣,是天一觀的道長。 經(jīng)常有香客問我瓦堵,道長基协,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任菇用,我火速辦了婚禮澜驮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惋鸥。我一直安慰自己杂穷,他們只是感情好悍缠,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著耐量,像睡著了一般飞蚓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上廊蜒,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天趴拧,我揣著相機(jī)與錄音,去河邊找鬼山叮。 笑死总放,一個(gè)胖子當(dāng)著我的面吹牛缀踪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播本缠,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼融虽,長吁一口氣:“原來是場噩夢啊……” “哼好唯!你這毒婦竟也來了勺卢?” 一聲冷哼從身側(cè)響起疗杉,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钞翔,沒想到半個(gè)月后严卖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嗅战,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年妄田,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了俺亮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驮捍。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖脚曾,靈堂內(nèi)的尸體忽然破棺而出东且,到底是詐尸還是另有隱情,我是刑警寧澤本讥,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布珊泳,位于F島的核電站,受9級特大地震影響拷沸,放射性物質(zhì)發(fā)生泄漏色查。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一撞芍、第九天 我趴在偏房一處隱蔽的房頂上張望秧了。 院中可真熱鬧,春花似錦序无、人聲如沸验毡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晶通。三九已至璃氢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狮辽,已是汗流浹背一也。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喉脖,地道東北人塘秦。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像动看,于是被迫代替她去往敵國和親尊剔。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容