论坛灌水机(续)

来源:互联网 发布:php array 清空 编辑:程序博客网 时间:2024/05/30 22:42
 

大概在2年零两个月前,我写过一个论坛灌水机,前几天,因为朋友要网络投票,又拿出来用了一次,改了下配置文件,又可以当投票机用了。


由于工作的关系,现在在UNIX上做开发了,我尝试了用UNIX重写了一个投票机,深深的体会到,什么叫“一行shell相当于1万行C代码了”。UNIX天生就是为程序员服务,来帮助他们完成看似不可能的任务的。
下面我以我重写的这个投票机为例,来阐述下UNIX的做事风格。


一个投票机,或曰灌水机,需要具备这么些特性:get/post、数据生成、流程控制、并发支持、代理支持、验证码识别等等。这些特性基本上是越往后越难的,看看UNIX是怎么用简单的方式来实现他们的:

get/post
UINX提倡用短小精悍的小程序组合来完成复杂的任务,对于使用HTTP协议访问网络,没有什么比wget更合用的啦。有UNIX环境的可以直接在shell下开始尝试,只有windows的也可以装一个cygwin的模拟UNIX环境来试验。
在提示符下直接输入wget,回车
$ wget
wget: missing URL
Usage: wget [OPTION]... [URL]...

Try `wget --help' for more options.
它提示你缺少URL参数,用--help来获得更多信息,注意UNIX绝大多数命令都可以用--help来获得帮助,而不是dos传统的/?。
如果你输入wget --help后,你会得到所有支持的参数列表。这些参数列表对于不怎么会得人来说,可能还是太简略了,输入man wget可以获得更加详细的解释及示例。许多UNIX程序都可以用man加上命令名来得到详细的使用说明。
man的简要使用如下:
用上下左右光标键浏览,q键退出。g到首行,G到末行,/开始查找,例如/proxy再回车,表示查找含有proxy处,n向下查找下一个,N向上查找下一个。
不看帮助,让我们来猜想最简单的用法,没错,就是这样
$wget www.csdn.net
--22:10:01--  http://www.csdn.net/
           => `index.html'
Resolving www.csdn.net... 211.100.21.179
Connecting to www.csdn.net|211.100.21.179|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 128,038 (125K) [text/html]

100%[====================================>] 128,038        4.29K/s    ETA 00:00

22:10:46 (2.90 KB/s) - `index.html' saved [128038/128038]

这是不带选项的用法,网页自动保存到文件,详细过程显示在终端上。好了,基本的get完成了,算算C代码要几行?


数据生成
对于灌水来说,上节自然是不够用的,至少也需要发送POST数据的功能吧?
这个简单,输入man wget,搜索post,就能找到答案,这里给个例子:
$wget www.xxx.com --post-data='a=1&b=2'
这里有个地方需要注意的就是,对于命令行中有&的,一定要用''把它引起来,否则会被shell解释成在后台运行,如上面的例子,如果没有'',那么shell认为是在后台执行"wget www.xxx.com --post-data=a=1",然后又执行b=2这样一个命令。
可以传递post数据了,读者一定还不满意,因为如果想让数据变化,例如a要从1变化到1000,总不能手工输入吧?

流程控制
好了,这要用到基本的shell编程了。我这里就简要的给出例子:
编辑一个shell文件start.sh,内容如下
#! /bin/sh
counter
=0
while [ $counter -lt $1 ]
do
        counter=`expr $counter + 1`
        wget "
www.xxx.com" "--post-data=a=$counter&b=2"
done

保存后,在shell下执行chmod +x start.sh, 使这个脚本可执行
然后执行./start.sh 1000,就达到了我们的目的。
(这里没什么好解释的,我也不喜欢shell的这种循环、比较与赋值的语法,不过为了它提供的其他好处,只好忍忍啦,毕竟任何事物都不是完美的,需要参考shell语法时可以查一本书:好像叫<<UNIX和LINUX shell编程指南>>,有电子版)
也许读者看到这里,还是觉得UNIX没什么好的,就刚才这些例子来说,无非是有了一个用C写好了的wget程序,我用socket或者用WININET来写,从功能上来说,哪样都不少,而且写熟练了,速度也不慢呀,那我们来看看

并发支持
UNIX重来都不考虑多线程这种烦人的东西,诸位把多线程的东西搞清楚了,又调试出了几个多线程的Bug,估计头上的白发没少生。UNIX下把上一节那个脚本在后台多运行几次,就实现并发了,简单吧,烦人的事情就该交给操作系统去做,而不是在windows中提倡的去搞一个复杂无比的多线程程序。

代理支持
我知道上面的话一定不能让人心服,现在我举这个例子,我觉得能征服至少一半读者。考虑这样的任务,你的论坛会限制你灌水的IP,同一个IP有发帖间隔限制,或者你要投票的地址限制每个IP只能投一票,你怎么办,找代理。那么你觉得需要多长时间能把这个功能完成呢?例如说从www.proxycn.com中取大量的代理地址,1天?1000行代码?有兴趣的读者可以先不往下看,看看在windows的思维方式下,能否在五分钟内完成这个任务。

我在刚尝试这件事时,我也没考虑要多快,但是我还真就五分钟内做成了。
第一分钟,我用浏览器打开www.proxycn.com,找到左下角的代理综合搜索,类型选HTTP,状态选活动,点击搜索按钮,出来3149个结果,共63页,就是它们了。
第二分钟,我复制第2页的快捷方式作为wget的参数
$wget -O result 'http://www.proxycn.com/proxysearch.php?action=proxys&searchsubmit=yes&address=&port=&AddDateBefore=&AddDateAfter=&status=1'/
'
&isedu=&type=HTTP&type2=&location=&page=2'
很快,第二页被下载下来存入result文件了。
我开始尝试
$cat result
输出了整个文件的内容,翻动一下屏幕,发现了一个好东西onDblClick="clip('219.165.115.186:3128'),运气还不错。
接着
$cat result | grep /d{1.3}
无结果
$cat result | grep '/d{1,3}'
无结果
$grep --help | grep perl
 -P, --perl-regexp         PATTERN is a Perl regular expression
$cat result | grep -P '/d{1,3}'
好了,一堆结果
$ cat result | grep -P '/d{1,3}/./d{1,3}'
这下结果很靠谱,把它匹配完
$ cat result | grep -P '/d{1,3}/./d{1,3}/./d{1,3}/./d{1,3}:/d{2,5}'
这下匹配了整个IP地址加端口了,但是grep是输出整行的呀,有多余的输出,
第三分钟
$grep --help
翻看Output control那一部分,找到一行
 -o, --only-matching       show only the part of a line matching PATTERN
试一下
$ cat result | grep -P '/d{1,3}/./d{1,3}/./d{1,3}/./d{1,3}:/d{2,5}' -o
203.160.1.47:554
66.240.123.59:3128
221.112.144.13:8080
165.228.129.10:3128
203.198.69.124:3128
203.160.1.44:554
125.247.118.226:3128
203.160.1.43:554
203.160.1.52:554
195.55.133.76:8080
202.146.67.238:8080
...成功了,现在把命令组合一下
第四分钟
编辑proxy.sh文件如下
#! /bin/sh
counter
=0
while [ $counter -lt $1
]
do
        counter=`expr $counter + 1
`
        wget -O - "
http://www.proxycn.com/proxysearch.php?action=proxys&searchsu
bmit=yes&address=&port=&AddDateBefore=&AddDateAfter=&status=1&isedu=&type=HTTP&t
ype2=&location=&page=
$counter" 2>/dev/null | grep -P '
/d{1,3}/./d{1,3}/./d{1,3}/
./d{1,3}:/d{2,5}
' -o
done
然后执行chmod +x proxy.sh
试一下
$./proxy.sh 1
没有问题,现在正式取了
第五分钟
$ ./proxy.sh 63 > result &
[1] 1680
这表示任务在后台执行了,
我可以用这个命令来观察结果
$ tail -f result
大约过了一分钟,后台的任务执行完了,我统计一下行数
$ wc -l result
1749 result
还真准,刚好3149个结果