事情的原由,所有都来自于一个叫 邀请码 的东西。。。。php
1024论坛的游客成百上千万,可是注册从未开放注册过,一直都是邀请码注册。会员机制很特殊,有连坐的惩罚,即下家若是被禁言了,上家也跟着倒霉。并且,自己注册会员获取邀请码也很难,得养本身的号才行。这一切都致使了一个结果:真的是一码难求啊。html
还有个特色,就是论坛发码,通常都不发明码,发的都是加了密的暗码,好比下面这种:web
8d43#a8f182*1b53
正则表达式
上面这个暗码, *
表明一个数字,0~9; #
表明一个字母,a~z;也有的就是用一个标点符号来表明一个数字或字母。一个暗码可能被遮掩好多个字符。因此,若是不经过点很是手段,单靠人工一个一个的实验,抢到邀请码并注册成功是很难的。小程序
那么如何可以抢到码呢?简单来分析一下步骤,大体能够分为如下几步:微信小程序
无心间,我在『皮克啪的铲屎官交流群』里看到有一张这个图:浏览器
可能大家看到这张图,会是一脸懵逼的状态。可是,若是结合我上面讲述的那几个步骤,大家就会发现,其实这个图片里面的信息,基本都涵盖了。bash
只不过啊,这个注册器是针对单个帖子而写的。服务器
好比,论坛里面经常有些帖子会在重大节日啥的,会在一个帖子里面,每一个楼层跟着发码,有的是明码,有的是暗码,大家看第一行,地址一栏的URL模式,就能看出来,这种URL表明的就是单独帖子第几页的url。下面第二行的页码
,间隔
,和规则
则是可能表示最大页数,访问时间间隔(论坛刷新时间不得小于两秒),以及十六位的邀请码正则表达式。微信
接着探测进程,则是说检测可能的邀请码的post请求进程。
注册信息啥的都不须要多说,以后的显示结果啥的,这些都是锦上添花的东西而已。
因此,按照铲屎官以前分析的思路,这个探测的过程是彻底可行的。那么我注意到,论坛里面最近有些帖子确实是在发码,就好比,论坛里面有个叫 苏*
的用户,就基本天天发个帖子,而后在帖子里面,把邀请码遮挡,作成暗码,而后拆分红三段,藏在帖子里。并且这个用户,基本天天上午发帖子。
针对这个需求,铲屎官就利用早上吃早饭的时间,简单的用Python写了一个demo,过程基本实现了,中间的细节还须要填充,有些地方不是很完善,可是,骨架模型什么的都已经搭建好了。
接下来就来讲一下这段Python代码中,再结合上面的思路,说一下他们的做用吧:
首先,咱们来在论坛里面找到特定做者的帖子:
1 def requestFid7(self):
2 print("requestFid7")
3 fid7_url = self.root_url + "thread0806.php?fid=7"
4 fid7_header = {
5 "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.2412.123 Safari/497.06",
6 "Accept-Encoding": "gzip, deflate",
7 "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6,ru;q=0.5",
8 }
9 request_result = requests.get(url=fid7_url,headers=fid7_header)
10 request_result.encoding = "gbk"
11 soup = BeautifulSoup(request_result.content, "html.parser")
12 tr_list = soup.find_all(name="tr", attrs={"class": "tr3 t_one tac"})
13 for tr_item in tr_list:
14 auth_temp = tr_item.find_all(name="a", attrs={"class": "bl"})
15 if len(auth_temp) != 0:
16 # print("auth: " + auth_temp[0].text)
17 if "苏*" == auth_temp[0].text:
18 time_temp = tr_item.find_all(name="div", attrs={"class": "f12"})
19 if len(time_temp) != 0:
20 print("time: " + time_temp[0].text)
21 if "今天" in time_temp[0].text:
22 page_url = self.root_url + tr_item.find(name="a", attrs={"target": "_blank"})["href"]
23 print("找到了::: " + page_url)
24 self.parsePage(page_url)
25 break
26 print("requestfid7 finished")
复制代码
这里面,用 requests 来发送 GET 请求,为了避免被屏蔽,咱们须要添加表头数据。将返回的结果,咱们用 BeautifulSoup 来解析,当找到目标帖子,咱们就进入下一步,解析页面,读取帖子内容,抽离出来暗码:
1 def parsePage(self, page_url):
2 page_header = {
3 "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.2412.123 Safari/497.06",
4 "Accept-Encoding": "gzip, deflate",
5 "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6,ru;q=0.5",
6 }
7 request_result = requests.get(url=page_url, headers=page_header)
8 soup = BeautifulSoup(request_result.content, "html.parser")
9 print("parsePage")
10 body_temp = soup.find_all(name="div", attrs={"class": "tpc_content do_not_catch"})
11 if len(body_temp) != 0:
12 body_text = body_temp[0].text
13 code_one = re.compile("(1)[0-9a-f*]*").findall(body_text)[0]
14 code_two = re.compile("(2)[0-9a-f*]*").findall(body_text)[0]
15 code_three = re.compile("(3)[0-9a-f*]*").findall(body_text)[0]
16 mis_code = code_one[3:] + code_two[3:] + code_three[3:]
17 print("成功找到mis_code:" + mis_code)
18 self.generateCode(mis_code)
复制代码
这里没什么难度,主要就是经过 BeautifulSoup 来寻找到咱们要的文本文件,而后将文本文件中,提取出来咱们想要的暗码,而后再拼起来。
可能有些同窗对这个文本文件不是很了解,我截取了一下,长这个样子:
提取出来纯文本文字以后,就是大概长这个样子:
"我我的以为是可以发挥很大效果的。(1)d*7ee因此作了按摩。生意好的时候一个月能赚个四五千,少的时候两三千。(2)07e0ca我心想合着你也知道效果不大啊。(3)31b98这是我第一次在德国"
那么咱们须要在这里面匹配出来咱们想要的暗码,这里我就想到了万能的正则表达式。可能有些同窗一听正则表达式就头大,不要紧,铲屎官之前也头大,可是自从看了这篇文章以后,再结合一些网上的正则表达式匹配网站,铲屎官的正则表达式功力基本可以应付通常的请求了。
在线正则表达式验证网站:tool.oschina.net/regex/
正则表达式文章:《读懂正则表达式就这么简单》(https://www.cnblogs.com/zery/p/3438845.html)
这里,咱们使用的正则表达式就是: [0-9a-f*]*
就能够完美解决。咱们简单来说一下这个正则表达式表达的含义。[0-9a-f*]
这部分用中括号包裹起来,表示每一位能够匹配的字符,就是括号里面的这些,数字和小写字母,外加一个*
号,最后的那个*
号表示的则是以前中括号里面包裹的东西,能够重复屡次。若是想重复五次,则只须要将最后的*
号换成{5}
便可,大括号包裹表示重复的次数。
这样,走到这一步,咱们就找到了咱们的暗码,那么接下来就就是计算邀请码可能的状况。
1# * 表明数字,@表明表明字母,#表明数字和字母
2 def generateCode(self, original_code):
3 print(original_code)
4 code_size = len(original_code)
5 cur_process = 1
6 while cur_process <= code_size:
7 cur_char = original_code[cur_process - 1: cur_process]
8 if cur_char == "*":
9 self.potential_code_list = self.replaceChar(self.potential_code_list, cur_process, original_code, self.num_list)
10 elif cur_char == "@":
11 self.potential_code_list = self.replaceChar(self.potential_code_list, cur_process, original_code, self.alpha_list)
12 elif cur_char == "#":
13 self.potential_code_list = self.replaceChar(self.potential_code_list, cur_process, original_code, self.num_alpha_list)
14 else:
15 self.potential_code_list = self.replaceChar(self.potential_code_list, cur_process, original_code)
16 cur_process = cur_process + 1
17 print("length:" + str(len(self.potential_code_list)))
18 if len(self.potential_code_list) != 0:
19 for item in self.potential_code_list:
20 if self.checkCodeIsValid(item):
21 print("******** 这个邀请码可使用: " + item + " *********")
22 self.flag = 1
23 break
复制代码
这一部分我仅仅只是用*
来表数字,严格意义上讲,这里的生产过程并非很全面。每个可能的邀请码状况,咱们都会调用checkCodeIsValid()
方法来检验它是否可用:
1 def checkCodeIsValid(self, code):
2 print("check code: " + code)
3 # check_url = "register.php?#iframeload"
4 check_url_he = "https://dd.etet.men/register.php"
5 login_values = {
6 "reginvcode": code,
7 "action": "reginvcodeck"
8 }
9
10 login_header = {
11 "origin": self.root_url[:-1],
12 "content-type": "application/x-www-form-urlencoded",
13 "Referer": "https://dd.etet.men/register.php",
14 "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.2412.123 Safari/497.06",
15 "Accept-Encoding": "gzip, deflate",
16 "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6,ru;q=0.5",
17 }
18
19 request_result = requests.post(check_url_he, data=login_values, headers=login_header)
20 result_text = request_result.text.split(">")
21 if len(result_text) > 1:
22 result = re.sub("\D", "", result_text[1])
23 print("check " + code + " : " + result)
24 if int(result) == 0:
25 return True
26 return False
复制代码
这个东西的抓取过程,就是在注册页面,有个检测邀请码是否合法:
这里,咱们经过查看源码,就能够发现当点击这个按钮的时候,你本地的电脑其实就是发送了一个Post请求来校验邀请码是否合法。
一旦校验成功,则会打印到log里。
最后就是拿着合法的邀请码去完成注册了,这一步也能够用代码写好,铲屎官这里就不写了。
大家会发现,其实上面的这些代码,都只是发送一次请求所走的流程。实际状况是咱们须要对论坛每隔一段时间就访问一次,来检测是否有发码的帖子出来,因此,铲屎官这里用最简单的方法来写一个定时器:
1 def startTimer(self):
2 self.timer = threading.Timer(1, self.timeFunction)
3 self.timer.start()
4
5 def timeFunction(self):
6 if self.flag == 1:
7 print("即将打开浏览器:")
8 webbrowser.open_new("https://dd.etet.men/register.php")
9 webbrowser.get()
10 pass
11 print("第 " + str(self.count) + " 次请求:" + str(datetime.datetime.now()))
12 self.requestFid7()
13 self.count = self.count + 1
14 global timer
15 timer = threading.Timer(30, self.timeFunction)
16 timer.start()
复制代码
好了,以上的代码很少,代码能够修改的地方有不少,真的不少,具体的点,你能够本身想。铲屎官这个代码运行了一下,惋惜那我的今天没有发帖。
可是,交流群里有个小伙伴告诉我,这我的发的码是假的,实际目的就是为了给他的公众号引流,kao,我说呢么,这我的发的码,检查出来都是假的,并且新上岸的游客也没有报道。因此,铲屎官以为,这我的发的码 95% 是假的。
不过,这波经历不亏,虽然最后没有抢到吗,可是这种训练的思路仍是有意义的。骨架已经搭建完成,后续能够加入提早写好的配置文件,将程序部署到服务器上面去运行,增长不一样的header,代理,来防止被网站封掉等等。其实这个东西作出来,市场仍是蛮
大的,毕竟,好多游客都没有码。
最后闲扯两句,想要这个代码的,请关注微信公众号:『皮克啪的铲屎官』,回复『
同时,喜迎新春,铲屎官本身编写的
好了,最后,给你们带来福利,新年送你们一个充电宝,新年须要电量满满的来过。抽奖条件:只须要关注微信公众号:『皮克啪的铲屎官』,扫描下面的图片便可。超级简单,2月1日开奖。