获取百度贴吧的BDUSS
在电脑端登录百度贴吧,按F12进入开发者控制台,点击Application
找到BDUSS,记录当中的值
申请Server酱中的Key并且绑定微信
代码如下
代码语言:javascript复制<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>TiebaSignIn</artifactId>
<version>1.0-SNAPSHOT</version>
<name>TiebaSignIn</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
代码语言:javascript复制package com.ljfchtcc.domain;
/**
* 存入用户所填写的BDUSS
* @author LiYu
* @Time 2020-11-23
*/
public class Cookie {
private static final Cookie cookie = new Cookie();
private String BDUSS;
private Cookie(){};
public static Cookie getInstance() {
return cookie;
}
public String getBDUSS() {
return BDUSS;
}
public void setBDUSS(String BDUSS) {
this.BDUSS = BDUSS;
}
public String getCookie() {
return "BDUSS=" BDUSS;
}
}
代码语言:javascript复制package com.ljfchtcc.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.security.MessageDigest;
/**
* 对字符串进行加密
* @author LiYu
* @Time 2020-11-23
*/
public class Encryption {
/** 获取日志记录器对象 */
private static final Logger LOGGER = LoggerFactory.getLogger(Encryption.class);
/**
* 对字符串进行 MD5加密
* @param str 传入一个字符串
* @return String 加密后的字符串
* @author LiYu
* @Time 2020-11-23
*/
public static String enCodeMd5(String str){
try{
// 生成一个MD5加密计算摘要
MessageDigest md = MessageDigest.getInstance("MD5");
// 计算md5函数
md.update(str.getBytes("UTF-8"));
// digest()最后确定返回md5 hash值,返回值为8位字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
// BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
//一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方)
return new BigInteger(1, md.digest()).toString(16);
} catch (Exception e){
LOGGER.error("字符串进行MD5加密错误 -- " e);
return "";
}
}
}
代码语言:javascript复制package com.ljfchtcc.util;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ljfchtcc.domain.Cookie;
/**
* 封装的网络请求请求工具类
* @author LiYu
* @Time 2020-11-23
*/
public class Request {
/** 获取日志记录器对象 */
private static final Logger LOGGER = LoggerFactory.getLogger(Request.class);
/** 获取Cookie对象 */
private static Cookie cookie = Cookie.getInstance();
private Request(){};
/**
* 发送get请求
* @param url 请求的地址,包括参数
* @return JSONObject
* @author LiYu
* @Time 2020-11-23
*/
public static JSONObject get(String url){
RequestConfig defaultConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
HttpClient client = HttpClients.custom().setDefaultRequestConfig(defaultConfig).build();
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("connection","keep-alive");
httpGet.addHeader("Content-Type","application/x-www-form-urlencoded");
httpGet.addHeader("charset","UTF-8");
httpGet.addHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36");
httpGet.addHeader("Cookie",cookie.getCookie());
HttpResponse resp = null;
String respContent = null;
try{
resp = client.execute(httpGet);
HttpEntity entity=null;
if(resp.getStatusLine().getStatusCode()<400){
entity = resp.getEntity();
} else{
entity = resp.getEntity();
}
respContent = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e){
LOGGER.info("get请求错误 -- " e);
} finally {
return JSONObject.parseObject(respContent);
}
}
/**
* 发送post请求
* @param url 请求的地址
* @param body 携带的参数
* @return JSONObject
* @author LiYu
* @Time 2020-11-23
*/
public static JSONObject post(String url , String body){
StringEntity entityBody = new StringEntity(body,"UTF-8");
RequestConfig defaultConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
HttpClient client = HttpClients.custom().setDefaultRequestConfig(defaultConfig).build();
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("connection","keep-alive");
httpPost.addHeader("Host","tieba.baidu.com");
httpPost.addHeader("Content-Type","application/x-www-form-urlencoded");
httpPost.addHeader("charset","UTF-8");
httpPost.addHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36");
httpPost.addHeader("Cookie",cookie.getCookie());
httpPost.setEntity(entityBody);
HttpResponse resp = null;
String respContent = null;
try{
resp = client.execute(httpPost);
HttpEntity entity=null;
if(resp.getStatusLine().getStatusCode()<400){
entity = resp.getEntity();
} else{
entity = resp.getEntity();
}
respContent = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e){
LOGGER.info("post请求错误 -- " e);
}
finally {
return JSONObject.parseObject(respContent);
}
}
}
代码语言:javascript复制package com.ljfchtcc;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ljfchtcc.domain.Cookie;
import com.ljfchtcc.util.Encryption;
import com.ljfchtcc.util.Request;
import java.util.*;
/**
* 程序运行开始的地方
* @author LiYu
* @Time 2020-11-23
*/
public class Run
{
/** 获取日志记录器对象 */
private static final Logger LOGGER = LoggerFactory.getLogger(Run.class);
/** 贴吧BDUSS */
private static final String BDUSS = "刚刚保存的BDUSS";
/** Server酱KEY */
private static final String SCKEY = "刚刚申请的KEY";
/** 获取用户所有关注贴吧 */
String LIKE_URL = "https://tieba.baidu.com/mo/q/newmoindex";
/** 获取用户的tbs */
String TBS_URL = "http://tieba.baidu.com/dc/common/tbs";
/** 贴吧签到接口 */
String SIGN_URL = "http://c.tieba.baidu.com/c/c/forum/sign";
/** 存储用户所关注的贴吧 */
private List<String> follow = new ArrayList<>();
/** 签到成功的贴吧列表 */
private static List<String> success = new ArrayList<>();
/** 用户的tbs */
private String tbs = "";
/** 用户所关注的贴吧数量 */
private static Integer followNum = 201;
public static void main( String[] args ){
Cookie cookie = Cookie.getInstance();
// 存入Cookie,以备使用
cookie.setBDUSS(BDUSS);
Run run = new Run();
run.getTbs();
run.getFollow();
run.runSign();
LOGGER.info("共 {} 个贴吧 - 成功: {} - 失败: {}",followNum,success.size(),followNum-success.size());
run.send(SCKEY);
}
/**
* 进行登录,获得 tbs ,签到的时候需要用到这个参数
* @author LiYu
* @Time 2020-11-23
*/
public void getTbs(){
try{
JSONObject jsonObject = Request.get(TBS_URL);
if("1".equals(jsonObject.getString("is_login"))){
LOGGER.info("获取tbs成功");
tbs = jsonObject.getString("tbs");
} else{
LOGGER.warn("获取tbs失败 -- " jsonObject);
}
} catch (Exception e){
LOGGER.error("获取tbs部分出现错误 -- " e);
}
}
/**
* 获取用户所关注的贴吧列表
* @author LiYu
* @Time 2020-11-23
*/
public void getFollow(){
try{
JSONObject jsonObject = Request.get(LIKE_URL);
LOGGER.info("获取贴吧列表成功");
JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONArray("like_forum");
followNum = jsonArray.size();
// 获取用户所有关注的贴吧
for (Object array : jsonArray) {
if("0".equals(((JSONObject) array).getString("is_sign"))){
// 将为签到的贴吧加入到 follow 中,待签到
System.out.println(((JSONObject) array).getString("forum_name") "吧待签到");
follow.add(((JSONObject) array).getString("forum_name"));
} else{
// 将已经成功签到的贴吧,加入到 success
System.out.println(((JSONObject) array).getString("forum_name") "吧已签到");
success.add(((JSONObject) array).getString("forum_name"));
}
}
} catch (Exception e){
LOGGER.error("获取贴吧列表部分出现错误 -- " e);
}
}
/**
* 开始进行签到,每一轮性将所有未签到的贴吧进行签到,一共进行5轮,如果还未签到完就立即结束
* 一般一次只会有少数的贴吧未能完成签到,为了减少接口访问次数,每一轮签到完等待1分钟,如果在过程中所有贴吧签到完则结束。
* @author LiYu
* @Time 2020-11-23
*/
public void runSign(){
// 当执行 5 轮所有贴吧还未签到成功就结束操作
Integer flag = 5;
try{
while(success.size()<followNum&&flag>0){
LOGGER.info("-----第 {} 轮签到开始-----", 5 - flag 1);
LOGGER.info("还剩 {} 贴吧需要签到", followNum - success.size());
Iterator<String> iterator = follow.iterator();
while(iterator.hasNext()){
String s = iterator.next();
String body = "kw=" s "&tbs=" tbs "&sign=" Encryption.enCodeMd5("kw=" s "tbs=" tbs "tiebaclient!!!");
JSONObject post = Request.post(SIGN_URL, body);
if("0".equals(post.getString("error_code"))){
iterator.remove();
success.add(s);
LOGGER.info(s ": " "签到成功");
} else {
LOGGER.warn(s ": " "签到失败");
}
}
if (success.size() != followNum){
// 为防止短时间内多次请求接口,触发风控,设置每一轮签到完等待 5 分钟
Thread.sleep(1000 * 60 * 5);
/**
* 重新获取 tbs
* 尝试解决以前第 1 次签到失败,剩余 4 次循环都会失败的错误。
*/
getTbs();
}
flag--;
}
} catch (Exception e){
LOGGER.error("签到部分出现错误 -- " e);
}
}
/**
* 发送运行结果到微信,通过 server 酱
* @param sckey
* @author LiYu
* @Time 2020-11-23
*/
public void send(String sckey){
/** 将要推送的数据 */
String text = "总: " followNum " - ";
text = "成功: " success.size() " 失败: " (followNum - success.size());
String desp = "共 " followNum " 贴吧nn";
desp = "成功: " success.size() " 失败: " (followNum - success.size());
String body = "text=" text "&desp=" "TiebaSignIn运行结果nn" desp;
StringEntity entityBody = new StringEntity(body,"UTF-8");
HttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://sc.ftqq.com/" sckey ".send");
httpPost.addHeader("Content-Type","application/x-www-form-urlencoded");
httpPost.setEntity(entityBody);
HttpResponse resp = null;
String respContent = null;
try{
resp = client.execute(httpPost);
HttpEntity entity=null;
if(resp.getStatusLine().getStatusCode()<400){
entity = resp.getEntity();
} else{
entity = resp.getEntity();
}
respContent = EntityUtils.toString(entity, "UTF-8");
LOGGER.info("server酱推送正常");
} catch (Exception e){
LOGGER.error("server酱发送失败 -- " e);
}
}
}