基于SpringBoot的问卷星自动填写

概要

基于spring boot,selenium的问卷星自动化脚本,安装即用。可以参考我的部署网站autoq13.top
项目支持需要:
jdk版本:17
chrome
chromedriver
官网下载地址:https://googlechromelabs.github.io/chrome-for-testing/(下载不了私信我)
项目gitee地址:https://gitee.com/tkf111/auto-survey-filler
在这里插入图片描述
在这里插入图片描述

整体框架

在这里插入图片描述

技术细节

ip代理配置

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
public class ProxyConfig {
    // 代理服务器配置
    private String proxyHost;
    private int proxyPort;
    private long lastUpdateTime; // 记录代理更新时间
    
    // 预热配置
    @Value("${proxy.warmup.timeout:30000}")
    private int warmupTimeout; // 预热超时时间,默认30秒
    
    @Value("${proxy.warmup.test-urls:https://www.wjx.cn/vm/examle.aspx}") // 默认问卷星URL,使用ip代理时候换成你的
    private String[] warmupTestUrls; // 预热测试URL列表,默认为问卷星URL
    
    @Value("${proxy.max-use-time:1800000}")
    private long maxUseTime; // 代理最大使用时间,默认30分钟
    
    @Value("${proxy.retry-count:3}")
    private int maxRetryCount; // 最大重试次数
    
    @Value("${proxy.retry-interval:2000}")
    private long retryInterval; // 重试间隔时间(ms)


}

这里需要修改测试链接,就是你要填写的问卷星链接,使用ip代理时候会测试是否能够成功访问这个链接

private String fetchProxyFromApi() {
        try {
            String apiUrl = "http://v2.api.juliangip.com/company/postpay/getips?auto_white=1&num=1&pt=1&result_type=text&split=1&trade_no=6652588192186751&sign=548a4dd56afe2dd53e4c3a6997e22863";    // 这里填写API地址
            if (apiUrl == null) {
                log.error("代理API URL未配置");
                return null;
            }

            log.info("开始请求代理API,URL: {}", apiUrl);
            
            URL url = new URL(apiUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            
            int responseCode = conn.getResponseCode();
            log.info("代理API响应码: {}", responseCode);
            
            if (responseCode != HttpURLConnection.HTTP_OK) {
                log.error("代理API请求失败,响应码: {}", responseCode);
                return null;
            }
            
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
                String response = reader.readLine();
                log.info("成功获取代理响应: {}", response);
                return response;
            }
        } catch (Exception e) {
            log.error("请求代理API失败:{}", e.getMessage());
            return null;
        }
    }

这里修改String apiUrl =""为你的api代理地址

浏览器以及端口配置

webdriver:
  cache:
    path: ./drivers
  chrome:
    binary: ${WEBDRIVER_CHROME_BINARY:D:\\plug\\chrome\\chrome-win64 (1)\\chrome-win64\\chrome.exe}
    driver: ${WEBDRIVER_CHROME_DRIVER:D:\\plug\\chrome\\chromedriver-win64 (1)\\chromedriver-win64\\chromedriver.exe}

server:
  port: 8080

这里需要修改成你自己的路径,注意不要有中文,chrome和driver版本要一致,官网地址https://googlechromelabs.github.io/chrome-for-testing/,端口随意

题型适配

import com.example.wenmini.entity.QuestionnaireFillRequest;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

@Service
@Slf4j
public class QuestionChoice {
    private static final Random random = new Random();
    private static final int WAIT_TIMEOUT = 10;


    // 单选题
    public void handleSingleChoice(WebElement question, QuestionnaireFillRequest.QuestionConfigDto config, Long taskId) {
        List<WebElement> options = question.findElements(By.cssSelector(".ui-radio"));
        if (options.isEmpty() || config.getOptions() == null || config.getOptions().isEmpty()) {
            return;
        }

        int selectedIndex = getRandomIndexByPercentage(config.getOptions());
        if (selectedIndex >= 0 && selectedIndex < options.size()) {
            options.get(selectedIndex).click();
            log.info("单选题选择了第{}个选项", selectedIndex + 1);
        }
    }
 ......

}

目前只适配了单选题,多选题,文本题,有需要可以在这里继续添加。

错误处理,填写调试

/**
     * 创建新的WebDriver实例
     */
    public WebDriver createWebDriver(boolean useProxy) {
        try {
            log.info("开始创建WebDriver实例...");
            System.setProperty("webdriver.chrome.driver", chromeDriverPath);

            ChromeOptions options = new ChromeOptions();
            
            // 设置Chrome二进制文件路径
            if (chromeBinaryPath != null && !chromeBinaryPath.isEmpty()) {
                options.setBinary(chromeBinaryPath);
            }

            // 配置代理
            if (useProxy) {
                configureProxy(options);
            }

            // 设置无头模式
            options.addArguments("--headless=new");

            // 配置浏览器首选项
            configureBrowserPreferences(options);

            // 添加Chrome启动参数
            addChromeArguments(options);

            // 设置随机User-Agent
            options.addArguments("--user-agent=" + fingerprintGenerator.generateUserAgent());

            // 创建WebDriver实例
            WebDriver driver = new ChromeDriver(options);

            // 配置超时设置
            configureTimeouts(driver);

            // 注入动态指纹
            injectFingerprint(driver);

            log.info("WebDriver实例创建成功");
            return driver;

        } catch (Exception e) {
            log.error("创建WebDriver实例失败:{}", e.getMessage());
            throw new RuntimeException("创建WebDriver实例失败", e);
        }
    }

有需要调试的话可以注释掉DriverService中的无头模式(默认开启,启动程序后不会弹出chrome,而是在后台运行,看不到填写细节,出现错误时候可以关闭无头模式,追踪填写过程)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值