Linux 使用bash脚本登陆网站方法及示例代码

本文主要介绍Linux中,通过bash脚本的方式实现网站访问登陆的方法,以及相关的示例代码。

使用openssl

#!/bin/bash
shopt -s extglob

URL='https://stackoverflow.com/'
IFS=: read  -r user pass < <(gpg -qd 

后台运行openssl:

exec {wwwE}<> <(: - O)
exec {wwwI}<> <(: - b)
exec {wwwO}< <(
  exec stdbuf -o0 openssl s_client -quiet -connect "$hst":443 <&$wwwI 2>&$wwwE)
osslpid=$!

doReq函数可以创建 2 个变量:$cookieand $htstatus和 3 个数组:$hthead, $htbody 和 $hterr:

doReq() {
    hthead=() htbody=() hterr=()
    local target=$1 method=${2:-GET} head=true line cookies
    printf >&$wwwI '%s\r\n' "$method $target HTTP/1.1" "Host: $hst" \
           "User-Agent: aobs/0.01" "Connection: keep-alive" "Accept: */*"
    [ "$cookie" ] && printf >&$wwwI '%s' "$cookie"
    if [ "$method" = "POST" ];then
        printf >&$wwwI '%s\r\n%s\r\n\r\n%s' "Content-Length: ${#3}" \
                       'Content-Type: application/x-www-form-urlencoded' "$3"
    else printf >&$wwwI '\r\n'
    fi
    read -t 10 -ru $wwwO line
    htstatus=${line%$'\r'} ; hthead=("$htstatus")
    while read -t .3 -ru $wwwO line;do
        [ "${line%$'\r'}" ] || head=false;
        if $head ;then
            hthead+=("${line%$'\r'}");
            case $line in
                [sS]et-[cC]ookie:* ) line=${line#*: };
                                 cookies+=("${line%%;*}");;
            esac
        else htbody+=("${line%$'\r'}") ;fi
    done
    if read -t 0 -ru $wwwE;then
        while read -t .1 -ru $wwwE line;do
            hterr+=("${line%$'\r'}")
            case $line in
                depth* | verify* ) ;;
                * ) echo "ERR: $line" ;;
    esac ; done ; fi
    [ ! -v "cookie" ] && [ "${cookies[0]}" ] &&
        printf -v cookie 'Cookie: %s\r\n' "${cookies[@]}"
}

登陆:

doReq /users/login POST "email=$user&password=$pass"

显示网站信息:

doReq /
for ((i=${#htbody[@]};i--;)) ;do
line="${htbody[i]}"
case $line in
*badge1* ) line="${htbody[i-1]}${htbody[i]}${htbody[i+1]}"
line=${line//>+([0-9])</><} line=${line//<*([^>])>}
printf '%b\n' "${line//&#9679;/ \\U25cf }" ;;
esac ; done

现在可以随时运行doReq,因为连接保持打开状态。完成后,在退出之前,可以停止openssl并关闭您的 fd:

ls -l /dev/fd/ ; ps --tty $(tty) ufw
kill $osslpid
exec {wwwE}<&-
exec {wwwI}>&-
exec {wwwO}<&-
ls -l /dev/fd/ ; ps --tty $(tty) ufw

getSo.sh脚本内容:

#!/bin/bash
# getSo.sh - Sample HTTPS client w/Connection_Keep-Alive, using OpenSSL
# (C) 2020 - F-Hauri.ch
# Licensed by GNU GENERAL PUBLIC LICENSE Version 3
shopt -s extglob
URL='https://stackoverflow.com/'
IFS=: read  -r user pass < <(gpg -qd <socred.gpg)
IFS=/ read -r _ _ hst _ <<<"$URL"
exec {wwwE}<> <(: - O)
exec {wwwI}<> <(: - b)
exec {wwwO}< <(
  exec stdbuf -o0 openssl s_client -quiet -connect "$hst":443 <&$wwwI 2>&$wwwE)
osslpid=$!
doReq() {
    hthead=() htbody=() hterr=()
    local target=$1 method=${2:-GET} head=true line cookies
    printf >&$wwwI '%s\r\n' \
		   "$method $target HTTP/1.1" \
		   "Host: $hst" \
		   "User-Agent: aobs/0.01" \
		   "Connection: keep-alive" \
		   "Accept: */*"
    [ "$cookie" ] && printf >&$wwwI '%s' "$cookie"
    if [ "$method" = "POST" ];then
	printf >&$wwwI '%s\r\n%s\r\n\r\n%s' \
		       "Content-Length: ${#3}" \
		       'Content-Type: application/x-www-form-urlencoded' \
		       \
		       "$3"
    else
	printf >&$wwwI '\r\n'
    fi
    read -t 10 -ru $wwwO line
    htstatus=${line%$'\r'}
    hthead=("$htstatus")
    while read -t .3 -ru $wwwO line;do
	[ "${line%$'\r'}" ] || head=false;
	if $head ;then
	    hthead+=("${line%$'\r'}");
	    case $line in
		[sS]et-[cC]ookie:* ) line=${line#*: };
				     cookies+=("${line%%;*}");;
	    esac
	else
	    htbody+=("${line%$'\r'}") ;fi
    done
    if read -t 0 -ru $wwwE;then
	while read -t .1 -ru $wwwE line;do
	    hterr+=("${line%$'\r'}")
	    case $line in
		depth* | verify* ) ;;
		* ) echo "ERR: $line" ;;
	    esac
	done
    fi
    [ ! -v "cookie" ] && [ "${cookies[0]}" ] &&
	printf -v cookie 'Cookie: %s\r\n' "${cookies[@]}"
}
trUnicode() { 
    local lhs rhs chr;
    local -n string=$1;
    while [ "$string" ] && [ -z "${string//*&#*([0-9]);*}" ]; do
        rhs=${string#*&#*([0-9]);}
        lhs=${string%&#*([0-9]);$rhs}
        chr=${string%;$rhs}
        printf -v chr '\\U%X' "${chr#$lhs&#}"
        printf -v chr %b "$chr"
        string="$lhs $chr $rhs"
    done
}
doReq /users/login POST "email=$user&password=$pass"
while true;do
    doReq /
    out=''
    for ((i=${#htbody[@]};i--;)) ;do
	line="${htbody[i]}"
	case $line in
	    *badge1* )
		startdiv=$i enddiv=$i
		while [ "${htbody[startdiv]//*<div *}" ];do ((startdiv--));done
		while [ "${htbody[enddiv]//*<\/div>*}" ];do ((enddiv++));done
		line=""
		for ((bdg=startdiv;bdg<=enddiv+1;bdg++)) ;do
		    line+="${htbody[bdg]//*([$'\n\r\t']} "
		done
		line=${line//>+([0-9])</><}
		line=${line//<+([^>])>}
		line=${line//+([ ])/ }
		trUnicode line
		out+=" $line"
		;;
            *"title=\"your reputation:"* )
	       	line=${line#*reputation:}
		out="Rep: ${line%%\"*} $out"
		;;
	esac
    done
    if [ "$out" ] ;then
	[ "$out" = "$last" ] && printf '\e[A'
	printf "%(%d %b %T)T " -1
	echo "${out}"
	last="$out"
	printf -v tosleep '120-(%(%S)T%%20)' -1
	tosleep=$((tosleep))
	read -sn 1 -rt ${tosleep:1} _ && break
	penalty=0
    else
	(( penalty++ > 10 )) && break
	unset cookie
	doReq /users/login POST "email=$user&password=$pass"
	read -rt 0 _ && break
    fi
done
ls -l /dev/fd/
ps --tty "$(tty)" ufw
kill $osslpid
exec {wwwE}<&-
exec {wwwI}>&-
exec {wwwO}<&-
ls -l /dev/fd/
ps --tty "$(tty)" ufw

推荐阅读
cjavapy编程之路首页