【java爬虫】使用selenium通过加载cookie的方式跳过登录

前言

相信很多人在使用selenium的时候都有一个困惑,就是每一次打开的浏览器实例都是不带cookie的,当有一些页面需要登录操作的时候可能就会比较麻烦,每次都需要手动登录。

其实会造成这个问题的原因是每次打开的浏览器都不会加载本地的cookie,相当于环境被隔离了。

这个问题其实也很好解决,解决的办法就是我们首先登陆一次,然后将相应的cookie记录下载,有了cookie信息后,直接加载我们缓存的cookie就可以实现免登陆了。

首先来看一下这个方案的效果,首先是京东免登陆

可以看到当我们打开新的浏览器并且访问京东首页的时候可以很快实现登录,这是因为之前已经缓存了登录的cookie了。

接着我们来看一下百度首页免登陆的效果

因为百度登录后会有一个页面的整体的变化,所以可能看的会比较清楚。

下面我们来介绍一下这个方案的实现细节。

代码简介

整体的思路前面已经介绍过了,实际上就是首先登陆一下,将cookie记录下来,然后下次登录的时候直接加载cookie就可以了。我们记录的方式就是将cookie的信息写到一个txt临时文件中。

Cookie类中我们一共需要关系四个字段,分别是下图中展示的name,value,path和domain

将cookie信息缓存的方法如下

java 复制代码
    public void save() {
        if (driver == null) {
            return;
        }
        log.info("走到这里了");
        WebDriver.Options manage = driver.manage();
        Set<Cookie> cookies = manage.getCookies();
        // 检查缓存文件是否存在,如果存在则先删除再创建
        if (FileUtil.exist(TMP_COOKIE_PATH)) {
            FileUtil.del(TMP_COOKIE_PATH);
        }
        FileWriter writer = new FileWriter(TMP_COOKIE_PATH);
        for(Cookie c : cookies){
            StringBuilder sb = new StringBuilder();
            sb.append(c.getName() + ";");
            sb.append(c.getValue() + ";");
            sb.append(c.getDomain() + ";");
            sb.append(c.getPath() + ";\n");
            log.info("获取数据=> " + sb.toString());
            writer.append(sb.toString());
        }
    }

其中文件操作我们使用到了hutool工具库,driver是浏览器驱动实例,在执行这个方法前driver应该先被实例化。

将cookie的四个字段的数据变成字符串后写入到文件中即可,给大家展示一下缓存的百度的cookie的文件长什么样

下面说说加载cookie的方法,不知道大家之前有没有注意到,我们调用reload接口的时候,一开始的页面是没有登录的,后面才会变成登录的状态,这是因为cookie中的domian如果单独加载的话是加载不到的,我们需要首先处于当前页面中,再去加载cookie才能成功。加载的方法如下

java 复制代码
    public void reload() {
        if (!FileUtil.exist(TMP_COOKIE_PATH)) {
            log.error(TMP_COOKIE_PATH + "文件不存在");
            return;
        }
        System.setProperty("webdriver.chrome.driver", DRIVER_PATH);
        System.setProperty("webdriver.chrome.whitelistedIps", "");
//        EdgeOptions options = new EdgeOptions();
        ChromeOptions options = new ChromeOptions();
        //options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");
        options.addArguments("--remote-allow-origins=*");

        // 启动浏览器
        driver = new ChromeDriver(options);
        // 设置最长等待时间
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.get(URL);
        // 加载cookies
        List<String> lines = FileUtil.readLines(TMP_COOKIE_PATH, CharsetUtil.CHARSET_UTF_8);
        for(int i=0; i<lines.size(); i++) {
            String line = lines.get(i);
            List<String> tmplist = Arrays.asList(line.split(";"));
            Date expire = new Date(new Date().getTime() + 60 * 1000 * 15);
            Cookie cookie = new Cookie(tmplist.get(0), tmplist.get(1), tmplist.get(2), tmplist.get(3), expire);
            log.info("加载cookie=> [name=" + tmplist.get(0) + "] pvalue=" + tmplist.get(1) +
                    "] [domain=" + tmplist.get(2) + "] [path=" + tmplist.get(3) + "]" + " [expire=" + expire.toString() + "]");
            driver.manage().addCookie(cookie);

        }
        driver.manage().window().maximize();
        driver.get(URL);
    }

注意一下,我们调用的Cookie构造函数是下面这个

其中最后一个参数expiry代表的是过期时间,这个我尝试过了,需要设置成一个大于当前时间的值,否则cookie会失效。

最后展示一下完整的代码

java 复制代码
@Slf4j
@Service
public class EdgeTestService {

//    private final String DRIVER_PATH = "src/main/resources/msedgedriver.exe";
    private final String DRIVER_PATH = "src/main/resources/chromedriver-120.exe";
    private final String TMP_COOKIE_PATH = "src/main/resources/tmpcookie.txt";
    private final String URL = "https://www.baidu.com/";
//    private final String URL = "https://www.jd.com/?cu=true";
    private WebDriver driver = null;


    public void start() {
        System.setProperty("webdriver.chrome.driver", DRIVER_PATH);
        System.setProperty("webdriver.chrome.whitelistedIps", "");
//        EdgeOptions options = new EdgeOptions();
        ChromeOptions options = new ChromeOptions();
        //options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");
        options.addArguments("--remote-allow-origins=*");

        // 启动浏览器
        driver = new ChromeDriver(options);
        // 设置最长等待时间
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.manage().window().maximize();
        driver.get(URL);
    }

    public void save() {
        if (driver == null) {
            return;
        }
        log.info("走到这里了");
        WebDriver.Options manage = driver.manage();
        Set<Cookie> cookies = manage.getCookies();
        // 检查缓存文件是否存在,如果存在则先删除再创建
        if (FileUtil.exist(TMP_COOKIE_PATH)) {
            FileUtil.del(TMP_COOKIE_PATH);
        }
        FileWriter writer = new FileWriter(TMP_COOKIE_PATH);
        for(Cookie c : cookies){
            StringBuilder sb = new StringBuilder();
            sb.append(c.getName() + ";");
            sb.append(c.getValue() + ";");
            sb.append(c.getDomain() + ";");
            sb.append(c.getPath() + ";\n");
            log.info("获取数据=> " + sb.toString());
            writer.append(sb.toString());
        }
    }

    public void reload() {
        if (!FileUtil.exist(TMP_COOKIE_PATH)) {
            log.error(TMP_COOKIE_PATH + "文件不存在");
            return;
        }
        System.setProperty("webdriver.chrome.driver", DRIVER_PATH);
        System.setProperty("webdriver.chrome.whitelistedIps", "");
//        EdgeOptions options = new EdgeOptions();
        ChromeOptions options = new ChromeOptions();
        //options.setExperimentalOption("debuggerAddress", "127.0.0.1:9222");
        options.addArguments("--remote-allow-origins=*");

        // 启动浏览器
        driver = new ChromeDriver(options);
        // 设置最长等待时间
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.get(URL);
        // 加载cookies
        List<String> lines = FileUtil.readLines(TMP_COOKIE_PATH, CharsetUtil.CHARSET_UTF_8);
        for(int i=0; i<lines.size(); i++) {
            String line = lines.get(i);
            List<String> tmplist = Arrays.asList(line.split(";"));
            Date expire = new Date(new Date().getTime() + 60 * 1000 * 15);
            Cookie cookie = new Cookie(tmplist.get(0), tmplist.get(1), tmplist.get(2), tmplist.get(3), expire);
            log.info("加载cookie=> [name=" + tmplist.get(0) + "] pvalue=" + tmplist.get(1) +
                    "] [domain=" + tmplist.get(2) + "] [path=" + tmplist.get(3) + "]" + " [expire=" + expire.toString() + "]");
            driver.manage().addCookie(cookie);

        }
        driver.manage().window().maximize();
        driver.get(URL);
    }

    public void close() {
        if (driver != null) {
            driver.close();
        }
    }

}

上述的每个方法都对应一个接口

java 复制代码
@RestController
public class UserController {

    @Autowired
    private EdgeTestService edgeTestService;

    @RequestMapping("/start")
    @ResponseBody
    public String start() {
        edgeTestService.start();
        return "success";
    }

    @RequestMapping("/close")
    @ResponseBody
    public String close() {
        edgeTestService.close();
        return "success";
    }

    @RequestMapping("/save")
    @ResponseBody
    public String save() {
        edgeTestService.save();
        return "success";
    }

    @RequestMapping("/reload")
    @ResponseBody
    public String reload() {
        edgeTestService.reload();
        return "success";
    }

}

结语

基于上述思路就可以跳过登录环节,我觉得这个方法还是比较好的,如果你有更好的方法欢迎一起讨论交流。

相关推荐
xiaoxiongip6662 小时前
HTTP 和 HTTPS
网络·爬虫·网络协议·tcp/ip·http·https·ip
兆。4 小时前
掌握 PyQt5:从零开始的桌面应用开发
开发语言·爬虫·python·qt
小白学大数据5 小时前
正则表达式在Kotlin中的应用:提取图片链接
开发语言·python·selenium·正则表达式·kotlin
API快乐传递者10 小时前
淘宝反爬虫机制的主要手段有哪些?
爬虫·python
兜里有糖请分享20 小时前
Python中序列化/反序列化JSON格式的数据
爬虫·python
亿牛云爬虫专家1 天前
用Puppeteer点击与数据爬取:实现动态网页交互
javascript·爬虫·爬虫代理·puppeteer·数据·代理ip·16yun
API快乐传递者1 天前
利用Python 的爬虫技术淘宝天猫销量和库存
开发语言·爬虫·python
操练起来1 天前
【Python实战案例】爬虫项目实例(附赠源码)
数据库·爬虫·python
程序员小雷1 天前
软件测试基础:单元测试与集成测试
python·功能测试·selenium·测试工具·单元测试·集成测试·压力测试
编码小袁2 天前
利用爬虫爬取网站信息
爬虫