zoukankan      html  css  js  c++  java
  • Linux shell爬虫实现树洞网鼓励师(自动回复Robot)

    奇怪的赞数

    人生在世,不如意事十之八九,可与言者无二三人。幸好我们生在互联网时代,现实中找不到可以倾诉的人还可以在网络上寻找情绪宣泄口,树洞这类产品就是提供一个让人在网络上匿名倾诉的平台。

    我是偶然间发现了这个平台:http://www.6our.com/,感觉自己比较惨的时候去看看别人的不如意,发现上帝还是蛮眷顾自己的(也不知道中国在不在他老人家的管辖范围内)。不过我发现了一个奇怪的现象:秘密有一个赞和踩的功能,但是我看到的秘密的赞都没有发现有低于2的,然后尝试着发了一条,发现刚发出来就有两个赞,所以我猜测网站的开发者设定了秘密发出来时候赞的数量就是2,但是作为一个死心眼的程序员,认为只有亲手证过的才是可信的,所以我要验证一下我的想法,于是用shell写了个爬虫,爬取所有秘密的赞的数量,爬虫代码如下:

    #! /bin/bash
    
    ######################################################
    #
    #
    #
    #  树洞网赞数抓取
    #
    #
    ######################################################
    
    # env
    cd `dirname $0`
    source utils.sh
    
    # 初始化线程数控制,使用10个线程并发抓取以免把树洞网站打死
    init_thread 250 10
    
    # 初始化业务相关变量
    url="http://www.6our.com/qiushi?&p="
    total_page_num=`curl_ "${url}1" | grep -oE "<a href='/qiushi?&p=2480' >最后一页</a>" | grep -oE "[0-9]+"`
    log "total_page_num $total_page_num"
    
    # 开始抓取列表
    for page_num in `seq 1 $total_page_num`;
    do
    	read -u250
    	{
    		cur_page_url="${url}${page_num}"
    		log "url ${cur_page_url} begin"
    		curl_ $cur_page_url | grep -oE "id="yes-[0-9]+">[0-9]+" | sed -n 's/id="yes-//; s/">/ /p' >> shudong-id-yes.data
    		log "url ${cur_page_url} end"
    		echo '' >&250
    	}&
    done
    
    wait
    log "all done"
    

    需要引入的公共库:

    ################################
    #
    #  工具库,用来存放一些通用的方法
    #
    ################################
    
    
    # ha! 简易的log4shell
    log(){
    	echo "[`date +'%F %T'`] $1"
    }
    
    # 封装的线程控制器
    # $1 要使用的管道
    # $2 要使用的线程数
    init_thread(){
    	pipe_num=$1
    	thread_num=$2
    
    	fifo_path="/tmp/fifo_path_`date +%s`_${1}_${2}"
    	mkfifo $fifo_path
    	eval "exec ${pipe_num}<>${fifo_path}"
    	rm $fifo_path
    
    	for i in `seq 1 $thread_num`;
    	do
    		echo '' >&${pipe_num}
    	done
    	return $pipe_num
    }
    
    # 对curl的一层封装
    # 1. 伪装下U-A
    # 2. 模拟浏览器持久cookie的行为
    # 3. 安静模式,不显示统计信息
    # $@ 会被放在最后
    curl_(){
    	curl -s --user-agent "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36"  -b cookie -c cookie $@
    }
    
    # 类似于Stream.map()的封装,使得自定义函数支持管道调用
    # $1 函数名
    map(){
    	function_name=$1
    	while read line
    	do
    		$function_name "$line"
    	done
    }
    

    看下爬下来多少条评论数据:

    image

    不到五万条,如果这五万条中没有一个点赞数小于2的,那么就说明我的猜想是正确的,好,先看下数据格式:

    image

    第一列为秘密id,第二列为此秘密的赞数,筛选出第二列为1的共有多少条:

    image

    这…这…这就尴尬了,选一些出来看看页面是不是这样显示的:

    image

    这个是详情页的url模式:http://www.6our.com/article/{article_id},选一个id拼接出url http://www.6our.com/article/55840 进去看一下:

    image

    果然只有一个赞,又选了几个其它的进去看了一下发现都是一个赞。还好证了一下,不然就给出错误的结论了。

    我能做点什么

    我原来以为开发网站的程序员是送关怀来着,结果不是。于是我就在想,我能不能为他们做点什么呢?于是我去注册了一个账号:

     image

    然后写了个脚本,去检测页面内容,根据秘密内容进行回复,对他们送上一些鼓励的话,脚本内容:

    #! /bin/bash
    ##############################################################
    #
    #
    #
    #       树洞鼓励师
    #
    #
    #
    ##############################################################
    
    # env 
    cd `dirname $0`
    source utils.sh
    
    # 模拟登陆,保存cookie
    login(){
    	username="foo"
    	passwd="bar"
    
    	# 虽然不确定__hash__是做什么用的,但还是带上一下
    	hash_param=`curl_ "http://www.6our.com/index.php/User/Index/login" | grep -oE "[0-9a-z]+\_[0-9a-z]+" | tail -n 1`
    	curl_  -d "account=${username}&password=${passwd}&remember_me=1&submit=&__hash__=$hash_param" "http://www.6our.com/index.php/User/Index/checkLogin"  
    		| grep "登录成功" >> /dev/null
    
    	if [ $? -ne 0 ];
    	then
    		log "login failed."
    		exit -1	
    	else
    		log "login success" 
    	fi
    }
    
    # 回复秘密
    # $1 秘密id
    # $2 回复内容
    replay(){
    	id=$1
    	content=$2
    
    	# 检测已有评论避免重复回复,此处的重复是指对每条秘密回复一次,而不是对每个pattern回复一次
    	my_name="树洞鼓励师"
    	curl_ -d "id=$id" "http://www.6our.com/index.php/Reply/showReply" | grep $my_name >> /dev/null
    	if [ $? -eq 0 ];
    	then
    		return
    	fi
    
    	result=`curl_ -d "pid=${id}&anonymous=0&arcontent=${content}" "http://www.6our.com/index.php/Reply/checkReply2"`
    	if [ "$result" -eq 1 ];
    	then
    	       log "replay $id $content success"
    	else 
    		log "replay $id $content failed"
    	fi
    	# 防止回复过快
    	sleep 3
    }
    
    # 检查符合特定的条件则恢复特定内容
    # $1 秘密内容
    # $2 perl正则模式
    # $3 回复内容
    check_pattern_and_replay(){
    	content=$1
    	id=`echo $content | grep -oP 'id="content-d+"' | grep -oP 'd+'`
    	pattern=$2
    	replay_content=$3
    
    	echo $content | grep -P $pattern >> /dev/null
    	[[ $? -eq 0 ]] &&  replay $id $replay_content
    }
    
    # 对单个的秘密检测处理
    # $1 秘密元素,包含id和内容
    process_single(){
    	content=$1
    
    	# 热血青年
    	check_pattern_and_replay "$content" "需要帮助|阻碍|困难|梦想|努力" "加油,明天会更好!"
    	
    	# 孤独,纵有千种风情,更与何人说
    	check_pattern_and_replay "$content" "(烦|讨厌|不喜欢).*社交" "跟人打交道是很难的事"
    	
    	# 自杀倾向
    	check_pattern_and_replay "$content" "离开人世|自杀|我死了" "活着才有希望"
    
    	# 拯救颜值
    	check_pattern_and_replay "$content" "长的丑" "长的丑的来看下我长得有多挫,助你找回信心 :)"
    
    }
    
    # 监控第一页 
    monitor(){
    	while true;
    	do
    	 	curl_ "http://www.6our.com/qiushi" | tr -d "
    " | grep -oP 'id="content-d+".+?</div>' | map "process_single"
    		log "look first page over"
    		sleep 10
    	done
    }
    
    login
    monitor
    
    

    效果:

    image

    image

    所有脚本代码已经放到github: https://github.com/CC11001100/6our-robot

    备注:

    在调试正则的时候写了一个“foo|”类型的正则,导致有一部分在测试时进行了错误的评论,看到之后赶紧ctrl+c了,但是还是有几个评论删不掉了,吸取教训,以后细心一点。

    .

  • 相关阅读:
    可能会搞砸你的面试:你知道一个TCP连接上能发起多少个HTTP请求吗?
    iOS笔记055
    iOS笔记053- Quartz2D-练习
    iOS笔记052- Quartz2D-绘图
    IOS笔记051-手势使用
    IOS笔记050-事件处理
    IOS笔记049-UITabBarController
    IOS笔记048-数据存储
    IOS笔记047-代理传值和block传值
    IOS笔记046-UIApplication/导航控制器
  • 原文地址:https://www.cnblogs.com/cc11001100/p/8973955.html
Copyright © 2011-2022 走看看