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

2022-10-31 13:05:39

分析页面

首先所有的自动化都是拟人操作,只需要模拟出正常的签到步骤并定时重复即可满足需求。

获取登录状态

  • 签到总要知道是哪个用户签的嘛,所以所有的请求都要带上用户登录标识,也就是在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。

   <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.4.3</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.41</version>
        </dependency>
    </dependencies>

启动类上添加@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即可,这里直接从网上找了个方法。

邮箱逻辑

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<String, Object> 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= JSON.parseObject(response,new TypeReference<DrawResponce>(){});
        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 &

只需要半小时就可以往后只需要通过邮箱提醒处理cookie失效或失败的情况。

  • 作者:在下uptown
  • 原文链接:https://blog.csdn.net/m0_37817220/article/details/127232970
    更新时间:2022-10-31 13:05:39