├── run.sh ├── loop.sh ├── README.md ├── Dockerfile └── hostloc_auto_get_points.py /run.sh: -------------------------------------------------------------------------------- 1 | touch /app/log 2 | nohup sh /app/loop.sh >> /app/log & 3 | tail -f /app/log 4 | -------------------------------------------------------------------------------- /loop.sh: -------------------------------------------------------------------------------- 1 | while true; 2 | do 3 | python3 /app/hostloc_auto_get_points.py 4 | sleep 6h 5 | done 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | env 2 | HOSTLOC_USERNAME=username1,username2... 3 | HOSTLOC_PASSWORD=password1,password2... 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | WORKDIR /app 3 | RUN apk update \ 4 | && apk add --no-cache curl python3 py3-pip \ 5 | && pip install requests pyaes \ 6 | && curl -L https://raw.githubusercontent.com/jzl1/hostloc-auto-get-points-docker/main/hostloc_auto_get_points.py > /app/hostloc_auto_get_points.py \ 7 | && curl -L https://raw.githubusercontent.com/jzl1/hostloc-auto-get-points-docker/main/run.sh > /app/run.sh \ 8 | && curl -L https://raw.githubusercontent.com/jzl1/hostloc-auto-get-points-docker/main/loop.sh > /app/loop.sh \ 9 | && chmod 755 /app/* \ 10 | && rm -rf /var/cache/apk/* 11 | CMD ["/bin/sh","/app/run.sh"] 12 | -------------------------------------------------------------------------------- /hostloc_auto_get_points.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import random 4 | import re 5 | import textwrap 6 | import requests 7 | 8 | from pyaes import AESModeOfOperationCBC 9 | from requests import Session as req_Session 10 | 11 | 12 | # 随机生成用户空间链接 13 | def randomly_gen_uspace_url() -> list: 14 | url_list = [] 15 | # 访问小黑屋用户空间不会获得积分、生成的随机数可能会重复,这里多生成两个链接用作冗余 16 | for i in range(12): 17 | uid = random.randint(10000, 50000) 18 | url = "https://hostloc.com/space-uid-{}.html".format(str(uid)) 19 | url_list.append(url) 20 | return url_list 21 | 22 | 23 | # 使用Python实现防CC验证页面中JS写的的toNumbers函数 24 | def toNumbers(secret: str) -> list: 25 | text = [] 26 | for value in textwrap.wrap(secret, 2): 27 | text.append(int(value, 16)) 28 | return text 29 | 30 | 31 | # 不带Cookies访问论坛首页,检查是否开启了防CC机制,将开启状态、AES计算所需的参数全部放在一个字典中返回 32 | def check_anti_cc() -> dict: 33 | result_dict = {} 34 | headers = { 35 | "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36" 36 | } 37 | home_page = "https://hostloc.com/forum.php" 38 | res = requests.get(home_page, headers=headers) 39 | aes_keys = re.findall('toNumbers\("(.*?)"\)', res.text) 40 | cookie_name = re.findall('cookie="(.*?)="', res.text) 41 | 42 | if len(aes_keys) != 0: # 开启了防CC机制 43 | print("检测到防 CC 机制开启!") 44 | if len(aes_keys) != 3 or len(cookie_name) != 1: # 正则表达式匹配到了参数,但是参数个数不对(不正常的情况) 45 | result_dict["ok"] = 0 46 | else: # 匹配正常时将参数存到result_dict中 47 | result_dict["ok"] = 1 48 | result_dict["cookie_name"] = cookie_name[0] 49 | result_dict["a"] = aes_keys[0] 50 | result_dict["b"] = aes_keys[1] 51 | result_dict["c"] = aes_keys[2] 52 | else: 53 | pass 54 | 55 | return result_dict 56 | 57 | 58 | # 在开启了防CC机制时使用获取到的数据进行AES解密计算生成一条Cookie(未开启防CC机制时返回空Cookies) 59 | def gen_anti_cc_cookies() -> dict: 60 | cookies = {} 61 | anti_cc_status = check_anti_cc() 62 | 63 | if anti_cc_status: # 不为空,代表开启了防CC机制 64 | if anti_cc_status["ok"] == 0: 65 | print("防 CC 验证过程所需参数不符合要求,页面可能存在错误!") 66 | else: # 使用获取到的三个值进行AES Cipher-Block Chaining解密计算以生成特定的Cookie值用于通过防CC验证 67 | print("自动模拟计尝试通过防 CC 验证") 68 | a = bytes(toNumbers(anti_cc_status["a"])) 69 | b = bytes(toNumbers(anti_cc_status["b"])) 70 | c = bytes(toNumbers(anti_cc_status["c"])) 71 | cbc_mode = AESModeOfOperationCBC(a, b) 72 | result = cbc_mode.decrypt(c) 73 | 74 | name = anti_cc_status["cookie_name"] 75 | cookies[name] = result.hex() 76 | else: 77 | pass 78 | 79 | return cookies 80 | 81 | 82 | # 登录帐户 83 | def login(username: str, password: str) -> req_Session: 84 | headers = { 85 | "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", 86 | "origin": "https://hostloc.com", 87 | "referer": "https://hostloc.com/forum.php", 88 | } 89 | login_url = "https://hostloc.com/member.php?mod=logging&action=login&loginsubmit=yes&infloat=yes&lssubmit=yes&inajax=1" 90 | login_data = { 91 | "fastloginfield": "username", 92 | "username": username, 93 | "password": password, 94 | "quickforward": "yes", 95 | "handlekey": "ls", 96 | } 97 | 98 | s = req_Session() 99 | s.headers.update(headers) 100 | s.cookies.update(gen_anti_cc_cookies()) 101 | res = s.post(url=login_url, data=login_data) 102 | res.raise_for_status() 103 | return s 104 | 105 | 106 | # 通过抓取用户设置页面的标题检查是否登录成功 107 | def check_login_status(s: req_Session, number_c: int) -> bool: 108 | test_url = "https://hostloc.com/home.php?mod=spacecp" 109 | res = s.get(test_url) 110 | res.raise_for_status() 111 | res.encoding = "utf-8" 112 | test_title = re.findall("