分类 开发专题 下的文章

selenium实现截图、长截图、区域截图,非常简单(Java版本)


import org.openqa.selenium.*;

import java.io.File;

/**
 * 自定义截图
 *
 * @author erichary
 */
public class CustomScreenshot {

    /**
     * 向下滑动次数
     */
    private int scrollTimes = 10;

    /**
     * 上次高度
     */
    private int lastHeight = 0;

    /**
     * 重置窗口大小(调整至可以正常截图)
     *
     * @param driver 驱动对象
     */
    private void resetWindowSizeToScreenshot(WebDriver driver) {
        // 窗口最大化
        resetWindowSize(driver);
        // 向下滑动页面:到指定次数 || 高度不再变化,退出
        JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
        for (int i = 0; i < this.scrollTimes; i++) {
            // 获取当前高度
            Object thisHeightObject = javascriptExecutor.executeScript("return document.body.scrollHeight;");
            int thisHeight = Integer.parseInt(String.valueOf(thisHeightObject));
            // 判断高度
            if (this.lastHeight != thisHeight) {
                // 向下滑动
                javascriptExecutor.executeScript("window.scrollBy(0,10000)");
                // 滑动后赋值
                this.lastHeight = thisHeight;
            } else {
                // 高度相同,跳出
                break;
            }
        }
        // 设置窗口高度
        Dimension size = driver.manage().window().getSize();
        driver.manage().window().setSize(new Dimension(size.width, this.lastHeight));
    }

    /**
     * 重置窗口大小(最大化窗口)
     *
     * @param driver 驱动对象
     */
    private void resetWindowSize(WebDriver driver) {
        driver.manage().window().maximize();
    }

    /**
     * 全屏截图(当前可视范围)
     *
     * @param driver 驱动对象
     * @return 截图内容
     */
    public File fullScreenshot(WebDriver driver) {
        // 调整窗口
        resetWindowSize(driver);
        // 截图
        File file = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        // 调整窗口
        resetWindowSize(driver);
        return file;
    }

    /**
     * 全屏截图(长图)
     *
     * @param driver 驱动对象
     * @return 截图内容
     */
    public File fullScreenshotLong(WebDriver driver) {
        // 调整窗口
        resetWindowSizeToScreenshot(driver);
        // 截图
        File file = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        // 调整窗口
        resetWindowSize(driver);
        return file;
    }

    /**
     * 局域截图(单图)
     *
     * @param driver  驱动对象
     * @param element 要截图的文档节点对象
     * @return 截图内容
     */
    public File localScreenshot(WebDriver driver, WebElement element) {
        // 调整窗口
        resetWindowSizeToScreenshot(driver);
        // 截图
        File file = element.getScreenshotAs(OutputType.FILE);
        // 调整窗口
        resetWindowSize(driver);
        return file;
    }

    public int getScrollTimes() {
        return scrollTimes;
    }

    public void setScrollTimes(int scrollTimes) {
        this.scrollTimes = scrollTimes;
    }

    public int getLastHeight() {
        return lastHeight;
    }

    public void setLastHeight(int lastHeight) {
        this.lastHeight = lastHeight;
    }
}

image.png


Java实现首字母大写、驼峰命名与、划线转换,校验null


/**
 * 首字母转大写、驼峰命名
 *
 * @param s 待转换的字符串
 * @return 转换结果
 */
public static String initialToCapital(String s) {
    StringBuilder sb = new StringBuilder();
    if (s == null || s.trim().isEmpty()) {
        return sb.toString();
    }
    if (s.length() <= 1) {
        return sb.append(s).toString().toUpperCase();
    }
    String[] split = s.split("_");
    for (String string : split) {
        sb.append(string.substring(0, 1).toUpperCase());
        sb.append(string.substring(1).toLowerCase());
    }
    return sb.toString();
}

/**
 * 首字母转小写、驼峰转下划线
 *
 * @param s 待转换的字符串
 * @return 转换结果
 */
public static String capitalToInitial(String s) {
    StringBuilder sb = new StringBuilder();
    if (s == null || s.trim().isEmpty()) {
        return sb.toString();
    }
    if (s.length() <= 1) {
        return sb.append(s).toString().toLowerCase();
    }
    for (int i = 0; i < s.length(); i++) {
        char charAt = s.charAt(i);
        if (Character.isUpperCase(charAt)) {
            sb.append("_");
            sb.append(Character.toLowerCase(charAt));
        } else {
            sb.append(charAt);
        }
    }
    return sb.toString();
}



Windows下jdk下载安装与环境变量配置


下载安装jdk

百度搜索jdk+版本,以1.8版本为例,百度搜索“jdk1.8”,一般是第一个。

1606285864808138.jpg百度搜索jdk1.8

打开jdk下载页面,这里我们下载jdk1.8 x64版本下载地址:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html

1606285845428863.jpgjdk1.8下载页面

下载历史版本的jdk自动跳转登录,需要登录你的Oracle账号才能下载,用邮箱注册登录就可以,登录成功自动下载。

1606285845540167.jpg输入账号密码登录

双击安装包,打开安装程序,下一步

1606285845878174.jpg安装引导

选择安装选项,一般默认即可。可以自定义安装位置,这里我们选择默认,下一步

1606285864768652.jpg安装选项、安装位置

jdk安装中……

1606285864633522.jpgjdk安装中……

jdk安装完成后,自动打开安装jre窗口,可以自定义安装位置,这里我们保持默认,下一步

1606285845800749.jpg配置jre安装位置

jre安装中……

1606286107864335.jpgjre安装中……

安装成功,点击关闭

1606286107876182.jpg安装成功

配置jdk环境变量

右键我的电脑 > 属性 > 高级系统设置

1606286107270711.jpg找到高级系统设置

选择环境变量

1606286107511936.jpg选择环境变量

在系统变量内,加上jdk环境变量系统变量 -> 新建JAVA_HOME变量系统变量 -> 查找path变量 -> 变量后输入%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;(如果变量结尾没有`;`,先加上`;`,然后输入变量)系统变量 -> 新建CLASSPATH变量 -> 变量值.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar(注意前面有个点)Win+R运行cmd,输入java -version (java 和 -version 之间有空格),正确输出版本号,安装配置成功。

1606285865674009.jpg验证jdk是否安装成功

1606285865446252.jpg咖啡



临近过年,推荐一款高效抢票软件,比较良心的抢票软件


春运大概是每个人都会经历的,火车票总是一票难求。开始海淘抢票工具,尝试过很多的抢票工具,都不是特别的趁手。

发现分流抢票

分流抢票官网

官网截图

不得不说知乎的内容还是比较有质量的,没错这个工具就是在知乎上发现的。当时还觉得是个骗子,回家的心情还是让我选择了他。

了解分流抢票

日志界面、下载界面

日志部分截图

解压后大概就是这个样子

目录结构

在登录界面输入你的12306账号

登录界面

登陆后界面,非常简洁,正常购票流程

截图

官方版帮助文档

分流抢票官方文档

官方视频教程

目前我所知道的最好的抢票软件,欢迎大家尝试哦!

作者的话

分流抢票,是以用户为中心、人性化的抢票软件。不做广告、不做推广、不携带病毒、不收集隐私信息,并接受各方技术评测,全心全意为用户打造一款属于自己的抢票软件

前身是大二时历时一月开发的程序,几经风霜,经过了几年的时间不断的优化和更新迭代,时至今日,还在不断的维护当中,不忘初心。

分情破爱始乱弃,流落天涯思别离。

如花似玉负情意,影如白昼暗自迷。

随风浮沉千叶落,行色匆匆鬓已稀。

一首藏头,讲得清未来,却倒不回过去,执着只为你,愿你一切安好。

任何软件都是辅助程序,不能保证100%的抢到,所有的成果都需要用户努力和坚持。


使用Python抓取12306火车信息,存入csv文件,仅介绍实现思路


马上就要年底过年了,提前去网站上请回家的票。神奇的抢到了硬座票,心里很是欣慰,今年终于不用站着回家了。
但是开心的时间总是那么短暂,一周过后我回来继续抢返程的火车票。真的是查了好几遍,都没有返程的车,多方验证之后发现没有返程的列车,所以……

网站抓取思路

打开12306的官方网站,按F12打开你的开发人员工具,找到Network标签,F5刷新一下,获取车站信息。

列车车次信息列表

获取车站信息

部分数据

var station_names ='@bjb|北京北|VAP|beijingbei|bjb|0@bjd|北京东|BOP|beijingdong|bjd|1@bji|北京|BJP|beijing|bj|2@bjn|北京南|VNP|beijingnan|bjn|3@bjx|北京西|BXP|beijingxi|bjx|4@gzn|广州南|IZQ|guangzhounan|gzn|…………
获取所有车次信息(朋友提供)

列车车次信息列表

车次详细信息查询

列车车次信息查询页面

查询到的信息

车次详细信息查询接口(G126为例)

按自己需求实现部分功能,部分功能不对外开放,仅介绍抓取思路
# -*- coding:utf-8 -*-
'''
车次信息查询页面
https://kyfw.12306.cn/otn/queryTrainInfo/init
车次信息查询接口
https://kyfw.12306.cn/otn/queryTrainInfo/query?leftTicketDTO.train_no=5i0000G12600&leftTicketDTO.train_date=2020-01-24&rand_code=

车站信息
https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9138
车次信息
https://kyfw.12306.cn/otn/resources/js/query/train_list.js
'''
import json

import requests


class MainApp(object):
    def __init__(self):
        self.session = requests.session()

    def start(self):
        self.get_station_name()
        self.get_train_list()
        pass

    # 抓取火车车次信息
    def get_train_list(self):
        line = self.session.get('https://kyfw.12306.cn/otn/resources/js/query/train_list.js').text
        item = line.replace('var train_list =', '')
        json_now = json.loads(item)['2019-10-10']
        with open('train_list.csv', 'w+') as train_list_csv:
            train_list_csv.write('字段1,字段2,字段3,字段4,字段5,字段6,字段7')
            # 高铁
            for g in json_now['G']:
                print(g)
                no = g['train_no']
                station_train_code = str(g['station_train_code'])
                che = station_train_code[0:station_train_code.find('(')]
                se = station_train_code[station_train_code.find('(') + 1:-1].split('-')
                train_list_csv.write('\n%s,%s,%s,%s,%s,%s,%s' % (no, '高铁', 'G', che, se[0], se[1], '2019-10-10'))
            # 城际高铁
            for c in json_now['C']:
                print(c)
                no = c['train_no']
                station_train_code = str(c['station_train_code'])
                che = station_train_code[0:station_train_code.find('(')]
                se = station_train_code[station_train_code.find('(') + 1:-1].split('-')
                train_list_csv.write('\n%s,%s,%s,%s,%s,%s,%s' % (no, '城际高铁', 'C', che, se[0], se[1], '2019-10-10'))
            # 动车
            for d in json_now['D']:
                print(d)
                no = d['train_no']
                station_train_code = str(d['station_train_code'])
                che = station_train_code[0:station_train_code.find('(')]
                se = station_train_code[station_train_code.find('(') + 1:-1].split('-')
                train_list_csv.write('\n%s,%s,%s,%s,%s,%s,%s' % (no, '动车', 'D', che, se[0], se[1], '2019-10-10'))
            # 直达
            for z in json_now['Z']:
                print(z)
                no = z['train_no']
                station_train_code = str(z['station_train_code'])
                che = station_train_code[0:station_train_code.find('(')]
                se = station_train_code[station_train_code.find('(') + 1:-1].split('-')
                train_list_csv.write('\n%s,%s,%s,%s,%s,%s,%s' % (no, '直达', 'Z', che, se[0], se[1], '2019-10-10'))
            # 特快
            for t in json_now['T']:
                print(t)
                no = t['train_no']
                station_train_code = str(t['station_train_code'])
                che = station_train_code[0:station_train_code.find('(')]
                se = station_train_code[station_train_code.find('(') + 1:-1].split('-')
                train_list_csv.write('\n%s,%s,%s,%s,%s,%s,%s' % (no, '特快', 'T', che, se[0], se[1], '2019-10-10'))
            # 快速
            for k in json_now['K']:
                print(k)
                no = k['train_no']
                station_train_code = str(k['station_train_code'])
                che = station_train_code[0:station_train_code.find('(')]
                se = station_train_code[station_train_code.find('(') + 1:-1].split('-')
                train_list_csv.write('\n%s,%s,%s,%s,%s,%s,%s' % (no, '快速', 'K', che, se[0], se[1], '2019-10-10'))
            # 其他
            for o in json_now['O']:
                print(o)
                no = o['train_no']
                station_train_code = str(o['station_train_code'])
                che = station_train_code[0:station_train_code.find('(')]
                se = station_train_code[station_train_code.find('(') + 1:-1].split('-')
                train_list_csv.write('\n%s,%s,%s,%s,%s,%s,%s' % (no, '其他', 'O', che, se[0], se[1], '2019-10-10'))

    # 抓取火车站信息
    def get_station_name(self):
        line = self.session.get('https://kyfw.12306.cn/otn/resources/js/framework/station_name.js').text
        item = line.replace('var station_names =\'', '').replace('\';', '').split('|')
        print(item)
        with open('station_name.csv', 'w+') as station_name_csv:
            station_name_csv.write('字段1,字段2,字段3,字段4,字段5,字段6')
            for i in item:
                if '@' in i:
                    station_name_csv.write('\n%s' % i)
                else:
                    station_name_csv.write(',%s' % i)


if __name__ == '__main__':
    main = MainApp()
    main.start()

抓取数据存入csv,后续会入库,提供个性化的查询,也会给出快捷跳转至12306官网查询页面,直接进行购票。

模拟正常人行为进行查询获取公共数据,防止对网站造成压力(我相信我做不到)

不做商业使用,进个人网站展示,展示功能不保证高可用,仅作学习交流分享出现。