java|掘金社区自动签到+免费抽奖

分析页面 首先所有的自动化都是拟人操作,只需要模拟出正常的签到步骤并定时重复即可满足需求。
获取登录状态

  • 签到总要知道是哪个用户签的嘛,所以所有的请求都要带上用户登录标识,也就是在header中添加对应的cookie
  • 如何获取cookie呢,这里看了下掘金的登录请求还比较麻烦,对熟悉爬虫的同学可能小菜一碟,对后端来说虽然能做但是本着投入时间与收益的原则,我毅然决然的选择绕过登录,直接拦截请求把request header的cookie复制出来。
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hrACs4W2-1665316799526)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/88660b222a284cc18302a4679346a624~tplv-k3u1fbpfcp-zoom-1.image “image.png”)]
处理cookie失效
  • 没有登录逻辑的话等cookie失效签到请求会返回请登录,这里话通过邮箱提醒更换cookie也是可以接受的
处理https请求
  • 随便从网上找一个http方法即可
落地方案 为了快速满足直接用最熟悉的Java+SpringBoot撸出来个jar包,打开IDEA创建SpringBoot脚手架
创建脚手架
pom里直接引入springboot-web、springboot-mail、lombok、fastjson,版本管理直接继承下spring-boot-dependencies。
org.springframework.boot spring-boot-dependencies 2.4.3 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-mail org.projectlombok lombok com.alibaba fastjson 1.2.41

启动类上添加@EnableScheduling注解开启定时任务
@EnableScheduling @SpringBootApplication public class SignApplication {public static void main(String[] args) { SpringApplication.run(SignApplication.class, args); } }

整体的骨架就这么简单。
通用http方法
public static String commonReuqest(String url, String method, String cookie) throws Exception { URL serverUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) serverUrl.openConnection(); conn.setRequestMethod(method); conn.setRequestProperty("Content-type", "application/json"); conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36"); conn.setRequestProperty("Cookie", cookie); //必须设置false,否则会自动redirect到重定向后的地址 conn.setInstanceFollowRedirects(false); conn.connect(); String result = getReturn(conn); return result; }/*请求url获取返回的内容*/ public static String getReturn(HttpURLConnection connection) throws IOException { StringBuffer buffer = new StringBuffer(); //将返回的输入流转换成字符串 try (InputStream inputStream = connection.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); ) { String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } String result = buffer.toString(); return result; } }

封装成一个util类,入口加上cookie即可,这里直接从网上找了个方法。
邮箱逻辑
  • 如何开启smtp邮箱服务就不说了,这里直接贴一下教程https://blog.csdn.net/weixin_46822367/article/details/123893527
  • yml配置里需要配置上必要信息,授权码按照上述博客中的步骤获取。
spring: mail: host: smtp.qq.com #发送者邮箱 username: #申请到的授权码 password: #端口号465或587 port: 587 #默认的邮件编码为UTF-8 default-encoding: UTF-8 #其他参数 properties: mail: #配置SSL 加密工厂 smtp: ssl: #本地测试,先放开ssl enable: false required: false #开启debug模式,这样邮件发送过程的日志会在控制台打印出来,方便排查错误 debug: true

  • 邮箱业务类
@Service @Slf4j public class SendMailServiceImpl implements SendMailService {@Autowired private JavaMailSender javaMailSender; @Value("${spring.mail.username}") private String sendMailer; public void checkMail(MailRequest mailRequest) { Assert.notNull(mailRequest,"邮件请求不能为空"); Assert.notNull(mailRequest.getSendTo(), "邮件收件人不能为空"); Assert.notNull(mailRequest.getSubject(), "邮件主题不能为空"); Assert.notNull(mailRequest.getText(), "邮件收件人不能为空"); }@Override public void sendMail(MailRequest mailRequest) { SimpleMailMessage message = new SimpleMailMessage(); checkMail(mailRequest); //邮件发件人 message.setFrom(sendMailer); //邮件收件人 1或多个 message.setTo(mailRequest.getSendTo().split(",")); //邮件主题 message.setSubject(mailRequest.getSubject()); //邮件内容 message.setText(mailRequest.getText()); //邮件发送时间 message.setSentDate(new Date()); //JavaMailSender javaMailSender = new JavaMailSenderImpl(); javaMailSender.send(message); log.info("发送邮件成功:{}->{}",sendMailer,mailRequest.getSendTo()); }}

JavaMailSender为spring-boot-starter-mail依赖中封装好的业务类,yml中添加对应的配置该类会被注入到容器中。
签到请求
@Slf4j @Service public class ActionService {//签到 public static final String CHECK_IN = "https://api.juejin.cn/growth_api/v1/check_in"; //抽奖 public static final String DRAW = "https://api.juejin.cn/growth_api/v1/lottery/draw"; @Value("${spring.mail.username}") private String username; @Autowired SendMailService sendMailService; /** * 签到 */ public void checkIn(String cookie) throws Exception { String response = BaseRequest.commonReuqest(CHECK_IN, "POST", cookie); log.info("get result from juejin {}", response); Map resultMap = JSONObject.parseObject(response, Map.class); if((Integer) resultMap.get("err_no") != 0){ log.error((String) resultMap.get("err_msg")); // 推送失败消息 MailRequest mailRequest = new MailRequest(); mailRequest.setText("掘金签到失败!err_msg: " + resultMap.get("err_msg")); mailRequest.setSendTo(username); mailRequest.setSubject("juejin sign"); sendMailService.sendMail(mailRequest); } }/** * 抽奖 */ public void draw(String cookie) throws Exception { String response = BaseRequest.commonReuqest(DRAW, "POST", cookie); DrawResponce data= https://www.it610.com/article/JSON.parseObject(response,new TypeReference(){}); log.info(response); }}

签到请求和抽奖请求都很简单没有参数,带上cookie发一下矿石就到账了,每天第一次抽奖不花矿石,默认第一次抽一下。签到成功就不发邮箱了发多了烦,签到失败会把失败原因发送到配置的邮箱内。
定时任务
@Slf4j @Component public class task {@Value("${uptown.cookie}") String cookie; @Resource ActionService actionService; @Scheduled(cron = "0 0 5 * * ?") public void run() throws Exception { log.info("{} start!", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); this.actionService.checkIn(cookie); // 第一次免费抽奖 this.actionService.draw(cookie); } }

最后加上定时任务就完事了,每天5点签到,签到失败发邮箱提醒。用maven打个包放到服务器上nohup java -jar *.jar &
【java|掘金社区自动签到+免费抽奖】只需要半小时就可以往后只需要通过邮箱提醒处理cookie失效或失败的情况。

    推荐阅读