前言:

  之前一直打算写一个模拟12306的工具,一直拖到现在,实在忍不了了,最近艰难的一步一步开始。由于想重新学习一下Java相关的知识,所以使用Java来进行开发,目前总算是有了一点进展,已经实现了登录和查票功能,先记录一下。下单以及其他抢票设置还在开发中。。。

界面:

  本文主要是关注功能的实现,另外就是javaswing的排版也不是很擅长,所以界面比较丑陋,将就看一下就行,目前主要是主界面、登录界面以及日期选择界面,先看一下效果:


  这里说明一下,日期选择控件是从网上找的一片文章拿过来用的,希望不要见怪。文章地址是:DateChooser日期选择器sw

车站信息:

  由于车站信息可能会有变化,包括新增车站或者车站改名之类的,所以要保证车站名称及对应的车站编号是最新的。
  static String getStationUrl = “https://kyfw.12306.cn/otn/resources/js/framework/station_name.js”;
  getStationUrl:为Get请求,没有参数。用于获取全国车站名称信息,后续的查票操作中需要将中文车站名称转换为对应的车站编号。。

登录模块:

  登录模块主要是要解决验证码部分,其他都好说。目前已经实现完整的验证码选择、提交以及验证等功能。突然好像忘了加上验证码刷新功能了(后续补上)。当前每请求一次会保存一张验证码图片在src同级的yzm目录下(目录需要自己创建),后续可以考虑用这些已有的验证码做自动识别,这是后话了。下面按请求顺序说一下登录过程中分别请求的几个URL:
  static String initUrl = “https://kyfw.12306.cn/otn/login/init”;
  string String getJsUrl = "https://kyfw.12306.cn/otn/HttpZF/GetJS
  static String getRailUrl = “https://kyfw.12306.cn/otn/HttpZF/logdevice”+
           “?algID=XWptt1kXbs”+
           “&hashCode=K7H-SogpeC4-tIYLqCXJabQWEnBXNROVnaPuQXU8Vec”+
           “&FMQw=0”+
           “&q4f3=zh-CN”+
           “&VPIf=1”+
           “&custID=133”+
           “&VEek=unknown”+
           “&dzuS=0”+
           “&yD16=0”+
           “&EOQP=89f60554e6cb588cf7dcc391a91488a1”+
           “&lEnu=176525634”+
           “&jp76=52d67b2a5aa5e031084733d5006cc664”+
           “&hAqN=Win32”+
           “&platform=WEB”+
           “&ks0Q=d22ca0b81584fbea62237b14bd04c866”+
           “&TeRS=1010x1680”+
           “&tOHY=24xx1050x1680”+
           “&Fvje=i1l1o1s1”+
           “&q5aJ=-8”+
           “&wNLf=99115dfb07133750ba677d055874de87”+
“&0aew=Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/76.0.3809.100%20Safari/537.36”+
           “&E3gR=c0e12f6dc8fe327988a902df0d354cec”+
           “&timestamp=”+String.valueOf(System.currentTimeMillis());
  static String getYzmUrl = “https://kyfw.12306.cn/passport/captcha/captcha-image64?”;
  static String checkYzmUrl = “https://kyfw.12306.cn/passport/captcha/captcha-check?”;
  static String loginUrl = “https://kyfw.12306.cn/passport/web/login”;

  initUrl:为Get请求,没有参数。用于获取后面请求中的一些cookie信息。
  getJsUrl:为Get请求,没有参数。用于请求获取一个js文件。
  getRailUrl:为Get请求,参数前面都列出来了。用于请求RAIL_DEVICEID和RAIL_EXPIRATION两个参数,需要将这两个参数获取到,然后添加到cookie中,不然在登录的时候会重定向到https://www.12306.cn/mormhweb/logFiles/error.html,该页面显示“网络可能存在问题,请您重试一下!”。重点关注请求中的algID和hashCode两个参数,algID可以从getJsUrl这个请求中返回的js文件中拿到,大概位置在:ab.getJSON("https://kyfw.12306.cn/otn/HttpZF/logdevice" + ("?algID\x3dXWptt1kXbs\x26hashCode\x3d" + e + a), null,hashCode这个参数应该也是冲上述js代码处获取到的,但是博主对js文件看不太懂,所以直接用fiddler工具抓了个getRailUrl请求的包,直接从里面拿出来的hashCode参数。但是这两个参数应该过一段时间会失效,失效的表现就是在登录的时候会提示重定向到https://www.12306.cn/mormhweb/logFiles/error.html这个页面,此时需要重新获取js文件,重新从js文件里面获取这两个参数,或者通过fiddler工具抓包进行获取,重新设置到cookie里面。
  getYzmUrl:为Get请求,需要携带{“login_site”:“E”, “module”:“login”, “rand”:“sjrand”, “callback”:“xxx”, "":“xxx”}这五个参数,另外还有个随机数。用于获取验证码,返回的是一张图片,图片顶部为点击验证码提示语,下部为8块区域,分别显示8张验证码。请求URL示例:https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&1565256427784&callback=jQuery19105951551454704869_1565256422938&=1565256422940
  checkYzmUrl:为Get请求,需要携带{“callback”:“xxx”, “answer”:“xxx”, “rand”:“sjrand”, “login_site”:“E”, “_”:“xxx”}这五个参数,用于校验验证码。其中answer参数为验证码图片坐标,如:194,54,48,48。返回的字符串中result_code为4代表验证成功。(目前返回的是jQuery开头的一串字符串,其中()中间的部分为json格式,后面12306可能会有变动)
  loginUrl:为Post请求,需要携带{“username”:“xxx”, “password”:“xxx”, “appid”:“otn”, “answer”:“xxx”}这四个参数。answer参数与校验验证码中的answer参数一样。返回的json中对象中result_code为0代表登录成功。(目前返回的为json格式的数据,后面12306可能会有变动)
  关于验证码坐标的说明:

  • 整张图片的大小是:293*190 单位:像素
  • 打字机这一排提示语所在行的宽度为29
  • 第一排第一张小图片的范围是(5,41)~(72,108) 长:67,宽:67 间距都是5px
  • 第二排第一张小图片的范围是(5,41+5+67)~(72,41+5+67+67) 长:67,宽:67 间距都是5px
  • 第一排第二张小图片的范围是(5+67+5,41)~(5+67+5+67,108) 长:67,宽:67 间距都是5px

查票模块:

  查票模块目前不添加cookie中的JSESSIONID、RAIL_DEVICEID、RAIL_EXPIRATION也可以查询成功,但是后续下单包括支付等操作就需要携带上述cookie参数。
  static queryTicketsUrl = “https://kyfw.12306.cn/otn/leftTicket/query?”;
  queryTicketsUrl 为Get请求,需要携带{“leftTicketDTO.train_date”:“xxx”, “leftTicketDTO.from_station”:“xxx”, “leftTicketDTO.to_station”:“xxxx”, “purpose_codes”:“xxx”}这四个参数,分别是出发日期、起始站、终到站和类型。

结尾:

  目前只是简单的实现了登录和查票功能。包括根据车次类型过滤等小功能都已实现。后续持续更新下单等其他功能模块,包括界面优化等功能。

代码:

  完整代码:Java实现12306登录和查询功能,在之前代码之前需要在工程的src同级目录下创建yzm文件夹,用来保存验证码图片,另外sign.jpg文件为30*30,可以随便替换,保证大小一致就行。代码中用到的第三方jar包主要有:
beangle-bundles-my97-4.8
commons-codec-1.12
commons-httpclient-3.1
commons-logging-1.2
fastjson-1.2.58
httpclient-4.5.5
httpcore-4.4.7
jcalendarbutton-1.4.5
ps:

package my12307;import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Vector;import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableModel;import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;public class My12307 extends JFrame {private static final long serialVersionUID = 1L;private JTextField cfdField;private JTextField mddField;private DateChooser dc;private ButtonGroup radioGroup;private JRadioButton adultRadioButton;private JRadioButton studentRadioButton;private JTable table;private JScrollPane scrollPane;private String[] headers = {"车次","出发站","到达站","出发时间","到达时间","历时","商务/特等座","一等座","二等座","高级软卧","软卧","动卧","硬卧","软座","硬座","无座","其他","备注"};private JCheckBox ck01,ck02,ck03,ck04,ck05,ck06;private Set<String> ccName;private Vector<String> tableHeaders;private HashMap<String, String> cityMap;private Vector<Vector<String>> gDatas;public My12307() throws ClientProtocolException, IOException {initEntity();initFrame();Utils.initLogin();Utils.initRail();}//获取车站信息private void getStationInfo() {HttpGet httpGet = new HttpGet(Utils.getStationUrl);try {CloseableHttpResponse cHttpResp = Utils.getHttpClient().execute(httpGet);HttpEntity entity = cHttpResp.getEntity();String result = EntityUtils.toString(entity,"utf-8");Utils.putStation2Map(result, cityMap);} catch (IOException e) {e.printStackTrace();}}private void initEntity(){ccName = new HashSet<String>();cityMap = new HashMap<String, String>();gDatas = new Vector<Vector<String>>();tableHeaders = new Vector<String>();for (int i = 0; i < headers.length; i++) {tableHeaders.add(i, headers[i]);}}private void initFrame() {this.setDefaultCloseOperation(EXIT_ON_CLOSE);int width = 1000;int height = 660;Dimension d = Toolkit.getDefaultToolkit().getScreenSize();//获得屏幕尺寸setBounds((d.width - width)/2, (d.height - height)/2, width, height);getContentPane().setLayout(new BorderLayout());this.setTitle("12307票票");this.setResizable(false);this.setIconImage(new ImageIcon("src/icon.jpg").getImage());JMenuBar menubar = new JMenuBar();JMenu menuDL = new JMenu("登录");//JMenu menuTC = new JMenu("退出");JMenu menuQueryM = new JMenu("查询联系人");menubar.add(menuDL);//menubar.add(menuTC);menubar.add(menuQueryM);this.setJMenuBar(menubar);addLoginListener(My12307.this, menuDL);//addLogoutListener(menuTC);addQueryMListener(menuQueryM);JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 5));topPanel.setPreferredSize(new Dimension(1000,70));JPanel centerPanel = new JPanel();centerPanel.setPreferredSize(new Dimension(1000,380));JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 1, 5));bottomPanel.setPreferredSize(new Dimension(1000,210));//出发地,目的地JLabel label1 = new JLabel("出发地:");JLabel label2 = new JLabel("目的地:");cfdField = new JTextField();cfdField.setPreferredSize(new Dimension(cfdField.getWidth(),25));cfdField.setColumns(10);mddField = new JTextField();mddField.setPreferredSize(new Dimension(mddField.getWidth(),25));mddField.setColumns(10);//成人,学生radioGroup = new ButtonGroup();adultRadioButton = new JRadioButton("成人");studentRadioButton = new JRadioButton("学生");radioGroup.add(adultRadioButton);radioGroup.add(studentRadioButton);adultRadioButton.setSelected(true);//出发日期JLabel label3 = new JLabel("出发日期:");dc = new DateChooser("yyyy-MM-dd");//查询JButton queryBbutton = new JButton("查询");addButtonListener(queryBbutton);//车次类型JLabel label4 = new JLabel("车次类型:");JPanel panel1 = new JPanel();ck01 = new JCheckBox("GC-高铁/城际");ck02 = new JCheckBox("D-动车");ck03 = new JCheckBox("Z-直达");ck04 = new JCheckBox("T-特快");ck05 = new JCheckBox("K-快速");ck06 = new JCheckBox("其他");ck01.setName("GC");ck02.setName("D");ck03.setName("Z");ck04.setName("T");ck05.setName("K");addCheckboxListener(ck01);addCheckboxListener(ck02);addCheckboxListener(ck03);addCheckboxListener(ck04);addCheckboxListener(ck05);addCheckboxListener(ck06);panel1.add(ck01);panel1.add(ck02);panel1.add(ck03);panel1.add(ck04);panel1.add(ck05);panel1.add(ck06);JPanel panel2 = new JPanel();panel2.add(label4);panel2.add(panel1);topPanel.add(label1);topPanel.add(cfdField);topPanel.add(label2);topPanel.add(mddField);topPanel.add(adultRadioButton);topPanel.add(studentRadioButton);topPanel.add(label3);topPanel.add(dc);topPanel.add(queryBbutton);topPanel.add(panel2);//查票查询tableString[][] content = new String[0][18];TableModel model = new DefaultTableModel(content, tableHeaders.toArray());table = new JTable();DefaultTableCellRenderer tcr = new DefaultTableCellRenderer();tcr.setHorizontalAlignment(SwingConstants.CENTER);table.setDefaultRenderer(Object.class, tcr);table.setRowHeight(30);  //设置行高JTableHeader tableHeader = table.getTableHeader();tableHeader.setResizingAllowed(false);tableHeader.setReorderingAllowed(false);tableHeader.setFont(new Font("宋体", 0, 12));tableHeader.setForeground(new Color(255,255,255));//设置字体颜色tableHeader.setBackground(new Color(33,132,199)); //设置背景颜色tableHeader.setPreferredSize(new Dimension(tableHeader.getHeight(),40));table.setModel(model);Utils.setTableColumnWidth(tableHeaders, table);scrollPane = new JScrollPane(table) {private static final long serialVersionUID = 1L;public Dimension getPreferredSize() {return new Dimension(990, 312);}};centerPanel.add(scrollPane);//抢票条件设置区JPanel passengerPanel = new JPanel();JPanel seatTypePanel = new JPanel();passengerPanel.setBorder(BorderFactory.createTitledBorder("联系人"));seatTypePanel.setBorder(BorderFactory.createTitledBorder("席别"));passengerPanel.setPreferredSize(new Dimension(100,200));seatTypePanel.setPreferredSize(new Dimension(100,200));bottomPanel.add(passengerPanel);bottomPanel.add(seatTypePanel);getContentPane().add(topPanel, BorderLayout.NORTH);getContentPane().add(centerPanel, BorderLayout.CENTER);getContentPane().add(bottomPanel, BorderLayout.SOUTH);//获取车站信息getStationInfo();}private void addLoginListener(JFrame frame, JMenu menu) {menu.addMouseListener(new MouseListener() {@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseClicked(MouseEvent e) {System.out.println("点击登录");LoginDialog loginDialog;try {loginDialog = new LoginDialog(My12307.this);loginDialog.setVisible(true);} catch (IOException e1) {e1.printStackTrace();}}});}private void addTableRowListener(JTable table) {table.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {table.setSelectionBackground(new Color(135,206,250));int row = table.getSelectedRow();int col = table.getSelectedColumn();System.out.println("点击第"+row+"行"+",第"+col+"列");}});}private void addCheckboxListener(JCheckBox checkbox) {checkbox.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String chName = checkbox.getName();if("GC".equals(chName)) {if(checkbox.isSelected()) {ccName.add("G");ccName.add("C");}else {ccName.remove("G");ccName.remove("C");}}else {if(checkbox.isSelected()) {ccName.add(chName);}else {ccName.remove(chName);}}//过滤数据if(!gDatas.isEmpty()) {filterDataByCheckBox();addTableRowListener(table);}}});}private void addButtonListener(JButton button) {button.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {//清空table((DefaultTableModel)table.getModel()).getDataVector().clear();table.updateUI();//String trainDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString();String trainDate = dc.showDate.getText();String fromStationName = cfdField.getText();String toStationName = mddField.getText();String fromStation = cityMap.get(fromStationName);String toStation = cityMap.get(toStationName);if ("".equals(fromStationName) || fromStation == null) {System.out.println("出发车站名有误,请重新输入。");return;}if ("".equals(toStationName) || toStation == null) {System.out.println("目的车站名有误,请重新输入。");return;}String type = "";if(radioGroup.getSelection() == adultRadioButton.getModel()) {type = "ADULT";}else {type = "0X00";}String queryTicketsUrl = Utils.queryTicketsUrl+"leftTicketDTO.train_date=" + trainDate+ "&leftTicketDTO.from_station=" + fromStation + "&leftTicketDTO.to_station="+ toStation + "&purpose_codes=" + type;try {System.out.println(queryTicketsUrl);sendQueryTicketRequest(queryTicketsUrl);} catch (IOException e1) {e1.printStackTrace();}}});}private void colloctionData(Vector<String> row, String[] resultData) {row.add(tableHeaders.indexOf("车次"), resultData[3]);row.add(tableHeaders.indexOf("出发站"), Utils.getKeyFromMap(cityMap,resultData[6]));row.add(tableHeaders.indexOf("到达站"), Utils.getKeyFromMap(cityMap,resultData[7]));row.add(tableHeaders.indexOf("出发时间"), resultData[8]);row.add(tableHeaders.indexOf("到达时间"), resultData[9]);row.add(tableHeaders.indexOf("历时"), resultData[10]);if(resultData[32] != "") {row.add(tableHeaders.indexOf("商务/特等座"), ("".equals(resultData[32]))?"--":resultData[32]);}else {row.add(tableHeaders.indexOf("商务/特等座"), ("".equals(resultData[25]))?"--":resultData[25]);}row.add(tableHeaders.indexOf("一等座"), ("".equals(resultData[31]))?"--":resultData[31]);row.add(tableHeaders.indexOf("二等座"), ("".equals(resultData[30]))?"--":resultData[30]);row.add(tableHeaders.indexOf("高级软卧"), ("".equals(resultData[21]))?"--":resultData[21]);row.add(tableHeaders.indexOf("软卧"), ("".equals(resultData[23]))?"--":resultData[23]);row.add(tableHeaders.indexOf("动卧"), ("".equals(resultData[27]))?"--":resultData[27]);row.add(tableHeaders.indexOf("硬卧"), ("".equals(resultData[28]))?"--":resultData[28]);row.add(tableHeaders.indexOf("软座"), ("".equals(resultData[24]))?"--":resultData[24]);row.add(tableHeaders.indexOf("硬座"), ("".equals(resultData[29]))?"--":resultData[29]);row.add(tableHeaders.indexOf("无座"), ("".equals(resultData[26]))?"--":resultData[26]);row.add(tableHeaders.indexOf("其他"), ("".equals(resultData[22]))?"--":resultData[22]);//row.add(tableHeaders.indexOf("备注"), resultData[1]);gDatas.add(row);}@SuppressWarnings("unchecked")private void fillData2Table() {if (!gDatas.isEmpty()) {Vector<Vector<String>> datas = new Vector<Vector<String>>();datas = (Vector<Vector<String>>) gDatas.clone();DefaultTableModel model = new DefaultTableModel(){private static final long serialVersionUID = 1L;@Overridepublic boolean isCellEditable(int row, int column) {return false;}};model.setDataVector(datas, tableHeaders);table.setModel(model);Utils.setTableColumnWidth(tableHeaders, table);}}@SuppressWarnings("unchecked")private void filterDataByCheckBox() {Vector<Vector<String>> ckData = new Vector<Vector<String>>();for(Vector<String> v : gDatas) {if(ccName.contains(v.get(0).toString().charAt(0)+"")) {ckData.add(v);}}if (ckData.isEmpty() &&(!ck01.isSelected() && !ck02.isSelected() && !ck03.isSelected() &&!ck04.isSelected() && !ck05.isSelected() && !ck06.isSelected())) {ckData = (Vector<Vector<String>>) gDatas.clone();}((DefaultTableModel)table.getModel()).getDataVector().clear();DefaultTableModel model = new DefaultTableModel(){private static final long serialVersionUID = 1L;@Overridepublic boolean isCellEditable(int row, int column) {return false;}};model.setDataVector(ckData, tableHeaders);table.setModel(model);Utils.setTableColumnWidth(tableHeaders, table);}private void sendQueryTicketRequest(String url) throws HttpException, IOException {HttpGet get = new HttpGet(url);CloseableHttpResponse response = Utils.getHttpClient().execute(get);int statusCode = response.getStatusLine().getStatusCode();String result = "";if (statusCode == HttpStatus.SC_OK) {System.out.println("查票成功.");result = EntityUtils.toString(response.getEntity());}else {System.out.println("查票失败,url="+url+",statusCode="+statusCode);return;}JSONObject obj = JSON.parseObject(result);JSONArray array = obj.getJSONObject("data").getJSONArray("result");int len = array.size();//获取车次信息在3号位置,始发站信息在6号位置,终点站信息在7号位置,出发时间在8号位置,抵达时间在9号位置//经历时间在10号位置,特别注意,商务/特等座在32或25位置,一等座信息在31号位置,二等座信息在30号位置//高级软卧信息在21号位置,软卧信息在23号位置,动卧信息在27号位置,硬卧信息在28号位置//软座信息在24号位置,硬座信息在29号位置,无座信息在26号位置,其他信息在22号位置,备注信息在1号位置gDatas.clear();for(int i = 0; i < len; i++) {Vector<String> row = new Vector<String>();String[] resultData = array.get(i).toString().split("\\|");//收集数据colloctionData(row, resultData);}//填充数据fillData2Table();//根据复选框过滤数据if (ck01.isSelected() || ck02.isSelected() || ck03.isSelected() ||ck04.isSelected() || ck05.isSelected() || ck06.isSelected()) {filterDataByCheckBox();}//给数据添加背景色Utils.setBackgoundColorForTable(table);//添加行点击监听addTableRowListener(table);obj.clear();}private void addQueryMListener(JMenu menu) {menu.addMouseListener(new MouseListener() {@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseClicked(MouseEvent e) {try {sendQueryPassengersRequest();} catch (IOException e1) {e1.printStackTrace();}}});}private void sendQueryPassengersRequest() throws ClientProtocolException, IOException {HttpPost post = new HttpPost(Utils.queryPassengersUrl);List<NameValuePair> formPair = new ArrayList<NameValuePair>();formPair.add(new BasicNameValuePair("pageIndex", "1"));formPair.add(new BasicNameValuePair("pageSize", "15"));UrlEncodedFormEntity urlEntity = new UrlEncodedFormEntity(formPair, "UTF-8");post.setEntity(urlEntity);Utils.setPostRequestHeaders(post);CloseableHttpResponse response;response = Utils.getHttpClient().execute(post);int respCode = response.getStatusLine().getStatusCode();if(respCode == HttpStatus.SC_OK) {JSONObject obj = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));if(Integer.parseInt(obj.getString("httpstatus")) == 200) {System.out.println("获取联系人成功");System.out.println(obj.toString());}else {System.out.println("获取联系人失败");}}else {System.out.println("获取联系人失败");}}public static void main(String[] args) {EventQueue.invokeLater(new Runnable() {public void run() {try {My12307 frame = new My12307();frame.setVisible(true);} catch (Exception e) {e.printStackTrace();}}});}
}
package my12307;import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.List;import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;public class LoginDialog extends JDialog{private static final long serialVersionUID = 1L;private JTextField userField;private JPasswordField pswdField;private JPanel imagePanel;private JLabel imageLabel;private Icon icon;private int X = 10;private int Y = 15;private JLayeredPane layeredPane = new JLayeredPane();;private StringBuffer callback = new StringBuffer("jQuery19107521990954709705_");private String random = "";private String random2 = "";private String yzmAnswer;private void initFrame(JFrame parent) throws ClientProtocolException, IOException{userField = new JTextField(15);pswdField = new JPasswordField(15);JLabel userLabel = new JLabel("用户名:");JLabel pswdLabel = new JLabel("密    码::");JButton loginButton = new JButton("登录");JButton cancelButton = new JButton("取消");addLoginButtonListener(loginButton);addCancelButtonListener(cancelButton);JPanel inputPanel = new JPanel(new GridLayout(2, 2, -90, 15));JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 10, 0));imagePanel = new JPanel(new GridLayout(1, 1, 10, 0));inputPanel.add(userLabel);inputPanel.add(userField);inputPanel.add(pswdLabel);inputPanel.add(pswdField);inputPanel.setBorder(BorderFactory.createEmptyBorder(X, Y, 10, 15));buttonPanel.add(loginButton);buttonPanel.add(cancelButton);buttonPanel.setBorder(BorderFactory.createEmptyBorder(X, Y, 10, 15));setLayout(new BorderLayout());getContentPane().add(inputPanel, BorderLayout.NORTH);getContentPane().add(buttonPanel, BorderLayout.CENTER);getYzmBindListener();int parentX = parent.getX();int parentY = parent.getY();int parentWidth = (int)parent.getWidth();int parentHeight = (int)parent.getHeight();int childWidth = 280;int childHight = 300;int childX = parentX + parentWidth/2 - childWidth/2;int childY = parentY + parentHeight/2 - childHight/2;setBounds(childX, childY, childWidth, childHight);setTitle("登录");setResizable(false);pack();YzmUtils.initYzm(layeredPane);}public LoginDialog(JFrame parent) throws ClientProtocolException, IOException {super(parent, true);setDefaultCloseOperation(DISPOSE_ON_CLOSE);if(Utils.cookieStore.getCookies().size() == 0) {try {Utils.initLogin();Utils.initRail();} catch (IOException e1) {e1.printStackTrace();}}initFrame(parent);}private void clearYzmPanel(){YzmUtils.yzm1 = 0;YzmUtils.yzm2 = 0;YzmUtils.yzm3 = 0;YzmUtils.yzm4 = 0;YzmUtils.yzm5 = 0;YzmUtils.yzm6 = 0;YzmUtils.yzm7 = 0;YzmUtils.yzm8 = 0;imagePanel.removeAll();layeredPane.removeAll();}@SuppressWarnings("deprecation")//获取验证码图片并绑定点击验证码事件private void getYzmBindListener() throws ClientProtocolException, IOException {clearYzmPanel();String image = getYzmImage();imageLabel = new JLabel();icon = new ImageIcon(image);imageLabel.setIcon(icon);addLabelListener(imageLabel);//监听验证码点击事件imagePanel.add(imageLabel);imagePanel.setBounds(0, 0, icon.getIconWidth(), icon.getIconHeight());Dimension dimension = new Dimension(icon.getIconWidth(), icon.getIconHeight());layeredPane.setPreferredSize(dimension);layeredPane.add(imagePanel, new Integer(0));getContentPane().add(layeredPane, BorderLayout.SOUTH);YzmUtils.initYzm(layeredPane);}private void addLabelListener(JLabel imageLbel) {imageLbel.addMouseListener(new MouseListener() {@Overridepublic void mouseReleased(MouseEvent e) {}@Overridepublic void mousePressed(MouseEvent e) {}@Overridepublic void mouseExited(MouseEvent e) {}@Overridepublic void mouseEntered(MouseEvent e) {}@Overridepublic void mouseClicked(MouseEvent e) {YzmUtils.addSign2Yzm(e);}});}private void addCancelButtonListener(JButton cancelButton) {cancelButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {LoginDialog.this.dispose();}});}private String login12306(String username, String password) throws IOException {String uamtk = "";HttpPost post = new HttpPost(Utils.loginUrl);List<NameValuePair> formPair = new ArrayList<NameValuePair>();formPair.add(new BasicNameValuePair("username", username));formPair.add(new BasicNameValuePair("password", password));formPair.add(new BasicNameValuePair("appid", "otn"));formPair.add(new BasicNameValuePair("answer", yzmAnswer));UrlEncodedFormEntity urlEntity = new UrlEncodedFormEntity(formPair, "UTF-8");post.setEntity(urlEntity);Utils.setPostRequestHeaders(post);CloseableHttpResponse response;int respCode = 0;int loop = 5;while(loop > 0) {response = Utils.getHttpClient().execute(post);respCode = response.getStatusLine().getStatusCode();JSONObject obj = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));if(respCode == HttpStatus.SC_OK) {if("0".equals(obj.getString("result_code"))) {System.out.println("登录成功,result_code:"+respCode+"result_message:"+obj.getString("result_message")+"uamtk:"+obj.getString("uamtk"));uamtk = obj.getString("uamtk");this.setVisible(false);return uamtk;}else {System.out.println("登录失败,result_code="+obj.getString("result_code")+",result_message:"+obj.getString("result_message"));//getYzmBindListener();break;}}else if(respCode == HttpStatus.SC_MOVED_TEMPORARILY){System.out.println("请求登录重定向,Location:"+response.getFirstHeader("Location").getValue());//getYzmBindListener();loop--;}else {System.out.println("登录失败,respCode="+respCode+",result_message:"+obj.getString("result_message"));//getYzmBindListener();break;}}getYzmBindListener();return uamtk;}private void addLoginButtonListener(JButton loginButton) {loginButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {//校验验证码url为:https://kyfw.12306.cn/passport/captcha/captcha-checkyzmAnswer = YzmUtils.getYzmAnswer();if ("".equals(yzmAnswer)) {System.out.println("请先选择验证码后再登录");return;}random2 = String.valueOf(Long.parseLong(random2)+1);String checkYzmUrl = Utils.checkYzmUrl+"callback="+callback+"&answer="+yzmAnswer+"&rand=sjrand&login_site=E&_="+random2;System.out.println("校验验证码的url:"+checkYzmUrl);HttpGet get = new HttpGet(checkYzmUrl);Utils.setGetRequestHeaders(get);// 通过请求对象获取响应对象String[] res = null;String result = "";CloseableHttpResponse response;try {response = Utils.getHttpClient().execute(get);int respCode = response.getStatusLine().getStatusCode();HttpEntity entity = null;if (respCode == HttpStatus.SC_OK) {entity = response.getEntity();result = EntityUtils.toString(entity);System.out.println("result:"+result);res = result.split("\"");}else {System.out.println("验证失败,statusCode="+respCode);getYzmBindListener();}if ("4".contentEquals(res[7])) {System.out.println("验证成功,result_message="+res[3]);String username = userField.getText();String password = new String(pswdField.getPassword());//saveCookies();String uamtk = login12306(username, password);if(!"".equals(uamtk)) {sendGetUamTkRequest();}}else {System.out.println("验证失败,result_message="+res[3]);getYzmBindListener();}} catch (IOException e1) {e1.printStackTrace();}}});}private void sendGetUamTkRequest() throws ClientProtocolException, IOException {HttpPost post = new HttpPost(Utils.getUamTk);List<NameValuePair> formPair = new ArrayList<NameValuePair>();formPair.add(new BasicNameValuePair("appid", "otn"));UrlEncodedFormEntity urlEntity = new UrlEncodedFormEntity(formPair, "UTF-8");post.setEntity(urlEntity);Utils.setPostRequestHeaders(post);CloseableHttpResponse response;response = Utils.getHttpClient().execute(post);int respCode = response.getStatusLine().getStatusCode();JSONObject obj = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));if(respCode == HttpStatus.SC_OK) {System.out.println("获取uamtk成功,result_code:"+respCode+"result_message:"+obj.getString("result_message")+"newapptk:"+obj.getString("newapptk"));String newAppTk = obj.getString("newapptk");sendUamAuthClientRequest(newAppTk);}else {System.out.println("获取uamtk失败,respCode="+respCode+"result_message:"+obj.getString("result_message"));}}private void sendUamAuthClientRequest(String newAppTk) throws ClientProtocolException, IOException {HttpPost post = new HttpPost(Utils.uamAuthClient);List<NameValuePair> formPair = new ArrayList<NameValuePair>();formPair.add(new BasicNameValuePair("tk", newAppTk));UrlEncodedFormEntity urlEntity = new UrlEncodedFormEntity(formPair, "UTF-8");post.setEntity(urlEntity);Utils.setPostRequestHeaders(post);CloseableHttpResponse response;response = Utils.getHttpClient().execute(post);int respCode = response.getStatusLine().getStatusCode();JSONObject obj = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));if(respCode == HttpStatus.SC_OK) {System.out.println("uamAuth成功,result_code:"+respCode+"result_message:"+obj.getString("result_message")+"newapptk:"+obj.getString("newapptk")+"username:"+obj.getString("username"));//saveCookies();}else {System.out.println("uamAuth失败,respCode="+respCode+"result_message:"+obj.getString("result_message"));}}private String getYzmImage() throws ClientProtocolException, IOException {random = String.valueOf(System.currentTimeMillis());random2 = random;random2 = String.valueOf(Long.parseLong(random2)+1);callback.append(random);String getYzmUrl = Utils.getYzmUrl+"login_site=E&module=login&rand=sjrand&"+random+"callback="+callback+"&_="+random2;System.out.println("请求验证码的url:"+getYzmUrl);HttpGet getMethod = new HttpGet(getYzmUrl);Utils.setGetRequestHeaders(getMethod);CloseableHttpClient client = Utils.getHttpClient();Utils.printCookies();CloseableHttpResponse response = client.execute(getMethod);HttpEntity entity = null;int statusCode = response.getStatusLine().getStatusCode();if (statusCode == HttpStatus.SC_OK) {entity = response.getEntity();System.out.println("获取验证码成功.");}else {System.out.println("获取验证码失败,url="+getYzmUrl+",statusCode="+statusCode);return "";}JSONObject obj = JSON.parseObject(EntityUtils.toString(entity));Decoder decoder = Base64.getDecoder();try {  //Base64解码  byte[] b = decoder.decode(obj.getString("image"));for(int i = 0; i < b.length; ++i){  if(b[i] < 0){//调整异常数据  b[i] += 256;  }  }  //生成jpg图片  String imgFilePath = "yzm/yzm_"+random+".jpg";//新生成的图片  OutputStream out = new FileOutputStream(imgFilePath);      out.write(b);  out.flush();  out.close();  return imgFilePath;} catch (Exception e){  }obj.clear();return "";}
}
package my12307;import java.awt.Color;
import java.awt.Component;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.util.EntityUtils;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;public class Utils {static CookieStore cookieStore = new BasicCookieStore();static CloseableHttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();static String accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";static String acceptEncoding = "gzip, deflate, br";static String acceptLanguage = "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2";static String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0";//urlstatic String getStationUrl = "https://kyfw.12306.cn/otn/resources/js/framework/station_name.js";static String queryTicketsUrl = "https://kyfw.12306.cn/otn/leftTicket/query?";static String getRailUrl = "https://kyfw.12306.cn/otn/HttpZF/logdevice"+//"?algID=8iIPwpB28l"+"?algID=XWptt1kXbs"+//"&hashCode=XQTW18RSf_dOYnqpGaj_yA-WKSsKbH77QE7zN-cCdB0"+"&hashCode=K7H-SogpeC4-tIYLqCXJabQWEnBXNROVnaPuQXU8Vec"+"&FMQw=0"+"&q4f3=zh-CN"+"&VPIf=1"+"&custID=133"+"&VEek=unknown"+"&dzuS=0"+"&yD16=0"+"&EOQP=89f60554e6cb588cf7dcc391a91488a1"+"&lEnu=176525634"+"&jp76=52d67b2a5aa5e031084733d5006cc664"+"&hAqN=Win32"+"&platform=WEB"+"&ks0Q=d22ca0b81584fbea62237b14bd04c866"+"&TeRS=1010x1680"+"&tOHY=24xx1050x1680"+"&Fvje=i1l1o1s1"+"&q5aJ=-8"+"&wNLf=99115dfb07133750ba677d055874de87"+"&0aew=Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/76.0.3809.100%20Safari/537.36"+"&E3gR=a54e6d6499e595ae2cfaf80eda685cc2"+"&timestamp="+String.valueOf(System.currentTimeMillis());static String initUrl = "https://kyfw.12306.cn/otn/login/init";static String loginUrl = "https://kyfw.12306.cn/passport/web/login";static String logoutUrl = "https://kyfw.12306.cn/otn/login/conf";static String logoutUamtk = "https://kyfw.12306.cn/passport/web/auth/uamtk-static";static String getYzmUrl = "https://kyfw.12306.cn/passport/captcha/captcha-image64?";static String checkYzmUrl = "https://kyfw.12306.cn/passport/captcha/captcha-check?";static String getUamTk = "https://kyfw.12306.cn/passport/web/auth/uamtk";static String uamAuthClient = "https://kyfw.12306.cn/otn/uamauthclient";static String queryPassengersUrl = "https://kyfw.12306.cn/otn/passengers/query";static CloseableHttpClient getHttpClient() {return httpClient;}static CookieStore getCookieStore() {return cookieStore;}static void addRailCookies(String exp, String dfp) {BasicClientCookie expCookie = new BasicClientCookie("RAIL_EXPIRATION", exp);expCookie.setDomain("kyfw.12306.cn");expCookie.setPath("/");cookieStore.addCookie(expCookie);BasicClientCookie dfpCookie = new BasicClientCookie("RAIL_DEVICEID", dfp);dfpCookie.setDomain("kyfw.12306.cn");dfpCookie.setPath("/");cookieStore.addCookie(dfpCookie);}static void setGetRequestHeaders(HttpGet get) {get.addHeader("Accept",Utils.accept);get.addHeader("Accept-Encoding", Utils.acceptEncoding);get.addHeader("Accept-Language", Utils.acceptLanguage);get.addHeader("User-Agent",Utils.userAgent);}static void setPostRequestHeaders(HttpPost post) {post.addHeader("Accept",Utils.accept);post.addHeader("Accept-Encoding", Utils.acceptEncoding);post.addHeader("Accept-Language", Utils.acceptLanguage);post.addHeader("User-Agent",Utils.userAgent);}static void initLogin() throws ClientProtocolException, IOException {HttpGet getMethod = new HttpGet(Utils.initUrl);Utils.setGetRequestHeaders(getMethod);CloseableHttpResponse response = Utils.getHttpClient().execute(getMethod);int statusCode = response.getStatusLine().getStatusCode();if (statusCode == HttpStatus.SC_OK) {System.out.println("初始化12306成功.");Utils.printCookies();}else {System.out.println("初始化12306失败,url="+Utils.initUrl+",statusCode="+statusCode);return;}}static void initRail() throws ClientProtocolException, IOException {//获取RAIL_DEVICEID和RAIL_EXPIRATION//String getJsUrl = "https://kyfw.12306.cn/otn/HttpZF/GetJS";HttpGet get = new HttpGet(Utils.getRailUrl);Utils.setGetRequestHeaders(get);CloseableHttpResponse response = Utils.getHttpClient().execute(get);int statusCode = response.getStatusLine().getStatusCode();if (statusCode == HttpStatus.SC_OK) {System.out.println("GetJS成功.");Utils.printCookies();String resStr = EntityUtils.toString(response.getEntity());String str = resStr.substring(resStr.indexOf("{"),resStr.indexOf("}")+1);System.out.println(str);JSONObject obj = JSON.parseObject(str);Utils.addRailCookies(obj.getString("exp"), obj.getString("dfp"));obj.clear();}else {System.out.println("GetJS失败,url="+Utils.getRailUrl+",statusCode="+statusCode);return;}}static void printCookies() {System.out.println("打印cookie信息:");List<org.apache.http.cookie.Cookie> cs = Utils.getCookieStore().getCookies();for (int i = 0; i < cs.size(); i++) {System.out.println(cs.get(i).getName()+":"+cs.get(i).getValue());}}static void clearCookies() {System.out.println("清空cookie信息");cookieStore.clear();}static void putStation2Map(String result, HashMap<String, String> cityMap) {int startIdx = result.indexOf("'");int endIdx = result.length();String city = result.substring(startIdx, endIdx);String[] c = city.split("@");for(int i = 1; i < c.length; i++) {String[] cc = c[i].split("\\|");cityMap.put(cc[1], cc[2]);}}static String getKeyFromMap(HashMap<String, String> map, String value) {for(String getKey: map.keySet()) {if(map.get(getKey).equals(value)) {return getKey;}}return "";}static void setTableColumnWidth(Vector<String> tableHeaders, JTable table) {table.getColumn(tableHeaders.get(1)).setPreferredWidth(55);table.getColumn(tableHeaders.get(2)).setPreferredWidth(55);table.getColumn(tableHeaders.get(7)).setPreferredWidth(55);table.getColumn(tableHeaders.get(8)).setPreferredWidth(55);table.getColumn(tableHeaders.get(9)).setPreferredWidth(60);table.getColumn(tableHeaders.get(10)).setPreferredWidth(45);table.getColumn(tableHeaders.get(11)).setPreferredWidth(45);table.getColumn(tableHeaders.get(12)).setPreferredWidth(45);table.getColumn(tableHeaders.get(13)).setPreferredWidth(45);table.getColumn(tableHeaders.get(14)).setPreferredWidth(45);table.getColumn(tableHeaders.get(15)).setPreferredWidth(45);table.getColumn(tableHeaders.get(16)).setPreferredWidth(45);}static void setBackgoundColorForTable(JTable table) {DefaultTableCellRenderer tcr = new DefaultTableCellRenderer() {private static final long serialVersionUID = 1L;@Overridepublic Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,boolean hasFocus, int row, int column) {//return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);JButton button;JPanel panel;Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);if (row % 2 == 0) {setBackground(Color.white); //设置奇数行底色}else if (row % 2 == 1) {setBackground(new Color(238,241,248)); //设置偶数行底色}//设置'有'和'无'的颜色if (value != null && column >= 6 && column <= 16) {if("--".equals(value.toString()) || "无".equals(value.toString())) {setForeground(new Color(153,153,153));}else if("有".equals(value.toString())) {setForeground(new Color(38,163,6));}else { //数字setForeground(Color.black);}}else {setForeground(Color.black);}//添加预定按钮if (column == 17) {Object obj6 = table.getModel().getValueAt(row, 6);Object obj7 = table.getModel().getValueAt(row, 7);Object obj8 = table.getModel().getValueAt(row, 8);Object obj9 = table.getModel().getValueAt(row, 9);Object obj10 = table.getModel().getValueAt(row, 10);Object obj11 = table.getModel().getValueAt(row, 11);Object obj12 = table.getModel().getValueAt(row, 12);Object obj13 = table.getModel().getValueAt(row, 13);Object obj14 = table.getModel().getValueAt(row, 14);Object obj15 = table.getModel().getValueAt(row, 15);if ( (obj6 != null) && (!"--".equals(obj6.toString())) && (!"无".equals(obj6.toString())) && (("有".equals(obj6.toString())) || (Integer.parseInt(obj6.toString()) > 0)) || (obj7 != null) && (!"--".equals(obj7.toString())) && (!"无".equals(obj7.toString())) && (("有".equals(obj7.toString())) || (Integer.parseInt(obj7.toString()) > 0)) || (obj8 != null) && (!"--".equals(obj8.toString())) && (!"无".equals(obj8.toString())) && (("有".equals(obj8.toString())) || (Integer.parseInt(obj8.toString()) > 0)) || (obj9 != null) && (!"--".equals(obj9.toString())) && (!"无".equals(obj9.toString())) && (("有".equals(obj9.toString())) || (Integer.parseInt(obj9.toString()) > 0)) ||(obj10 != null) && (!"--".equals(obj10.toString())) && (!"无".equals(obj10.toString())) && (("有".equals(obj10.toString())) || (Integer.parseInt(obj10.toString()) > 0)) || (obj11 != null) && (!"--".equals(obj11.toString())) && (!"无".equals(obj11.toString())) && (("有".equals(obj11.toString())) || (Integer.parseInt(obj11.toString()) > 0)) || (obj12 != null) && (!"--".equals(obj12.toString())) && (!"无".equals(obj12.toString())) && (("有".equals(obj12.toString())) || (Integer.parseInt(obj12.toString()) > 0)) || (obj13 != null) && (!"--".equals(obj13.toString())) && (!"无".equals(obj13.toString())) && (("有".equals(obj13.toString())) || (Integer.parseInt(obj13.toString()) > 0)) || (obj14 != null) && (!"--".equals(obj14.toString())) && (!"无".equals(obj14.toString())) && (("有".equals(obj14.toString())) || (Integer.parseInt(obj14.toString()) > 0)) || (obj15 != null) && (!"--".equals(obj15.toString())) && (!"无".equals(obj15.toString())) && (("有".equals(obj15.toString())) || (Integer.parseInt(obj15.toString()) > 0)) ){panel = new JPanel();button = new JButton();button.setText("预定");button.setForeground(Color.white);button.setBackground(new Color(0,119,255));panel.add(button, SwingConstants.CENTER);return panel;}else {setForeground(new Color(153,153,153));setValue("预定");}}return cell;}};tcr.setHorizontalAlignment(SwingConstants.CENTER);table.setDefaultRenderer(Object.class, tcr);}
}
package my12307;import java.awt.event.MouseEvent;import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;public class YzmUtils {private static String signImage = "src//sign.png";public static int yzm1 = 0;public static int yzm2 = 0;public static int yzm3 = 0;public static int yzm4 = 0;public static int yzm5 = 0;public static int yzm6 = 0;public static int yzm7 = 0;public static int yzm8 = 0;private final static int YZM_1 = 1;private final static int YZM_2 = 2;private final static int YZM_3 = 3;private final static int YZM_4 = 4;private final static int YZM_5 = 5;private final static int YZM_6 = 6;private final static int YZM_7 = 7;private final static int YZM_8 = 8;private static JPanel yzmPanel1;private static JPanel yzmPanel2;private static JPanel yzmPanel3;private static JPanel yzmPanel4;private static JPanel yzmPanel5;private static JPanel yzmPanel6;private static JPanel yzmPanel7;private static JPanel yzmPanel8;private static String yzm1Point = "35,72,";private static String yzm2Point = "111,72,";private static String yzm3Point = "181,72,";private static String yzm4Point = "250,72,";private static String yzm5Point = "35,148,";private static String yzm6Point = "111,148,";private static String yzm7Point = "181,148,";private static String yzm8Point = "250,148,";@SuppressWarnings("deprecation")static void initYzm(JLayeredPane layeredPane){yzmPanel1 = initSignImage(24, 55);yzmPanel2 = initSignImage(94, 55);yzmPanel3 = initSignImage(164, 55);yzmPanel4 = initSignImage(240, 55);yzmPanel5 = initSignImage(24, 130);yzmPanel6 = initSignImage(94, 130);yzmPanel7 = initSignImage(164, 130);yzmPanel8 = initSignImage(240, 130);layeredPane.add(yzmPanel1, new Integer(1));layeredPane.add(yzmPanel2, new Integer(1));layeredPane.add(yzmPanel3, new Integer(1));layeredPane.add(yzmPanel4, new Integer(1));layeredPane.add(yzmPanel5, new Integer(1));layeredPane.add(yzmPanel6, new Integer(1));layeredPane.add(yzmPanel7, new Integer(1));layeredPane.add(yzmPanel8, new Integer(1));yzmPanel1.setVisible(false);//表示验证码没有选中yzmPanel2.setVisible(false);yzmPanel3.setVisible(false);yzmPanel4.setVisible(false);yzmPanel5.setVisible(false);yzmPanel6.setVisible(false);yzmPanel7.setVisible(false);yzmPanel8.setVisible(false);}static JPanel initSignImage(int x, int y) {JPanel panel = new JPanel();JLabel signLabel = new JLabel();Icon signIcon = new ImageIcon(signImage);signLabel.setIcon(signIcon);panel.setOpaque(false);panel.add(signLabel);panel.setBounds(x, y, signIcon.getIconWidth(), signIcon.getIconHeight());return panel;}static void setYzmIndexVisiable(JPanel panel, int yzm) {if(yzm%2 == 0) {  //表示验证码没有选中panel.setVisible(true);} else {panel.setVisible(false);}}static void setYzmsVisiable(int index) {switch (index) {case YZM_1:setYzmIndexVisiable(yzmPanel1, yzm1);yzm1++;break;case YZM_2:setYzmIndexVisiable(yzmPanel2, yzm2);yzm2++;break;case YZM_3:setYzmIndexVisiable(yzmPanel3, yzm3);yzm3++;break;case YZM_4:setYzmIndexVisiable(yzmPanel4, yzm4);yzm4++;break;case YZM_5:setYzmIndexVisiable(yzmPanel5, yzm5);yzm5++;break;case YZM_6:setYzmIndexVisiable(yzmPanel6, yzm6);yzm6++;break;case YZM_7:setYzmIndexVisiable(yzmPanel7, yzm7);yzm7++;break;case YZM_8:setYzmIndexVisiable(yzmPanel8, yzm8);yzm8++;break;default:break;}}static String getYzmAnswer() {StringBuffer yzmAnswer = new StringBuffer();if (yzm1%2 == 1) { //该验证码被选中yzmAnswer.append(yzm1Point);}if (yzm2%2 == 1) { //该验证码被选中yzmAnswer.append(yzm2Point);}if (yzm3%2 == 1) { //该验证码被选中yzmAnswer.append(yzm3Point);}if (yzm4%2 == 1) { //该验证码被选中yzmAnswer.append(yzm4Point);}if (yzm5%2 == 1) { //该验证码被选中yzmAnswer.append(yzm5Point);}if (yzm6%2 == 1) { //该验证码被选中yzmAnswer.append(yzm6Point);}if (yzm7%2 == 1) { //该验证码被选中yzmAnswer.append(yzm7Point);}if (yzm8%2 == 1) { //该验证码被选中yzmAnswer.append(yzm8Point);}if (yzmAnswer.length() == 0) {System.out.println("请选择验证码");return "";}return (yzmAnswer.deleteCharAt(yzmAnswer.length() - 1)).toString();}static void addSign2Yzm(MouseEvent e) {//(5,41)  第一张验证码坐标int top = 41;int gap = 5;int xUnit = 67;  //每一个小图宽int yUnit = 67;  //每一个小图宽int xPoint = e.getX();int yPoint = e.getY();if(gap <= xPoint && xPoint < (gap + xUnit)) {if ((gap + top) <= yPoint && yPoint < (gap + yUnit + top)) {setYzmsVisiable(YZM_1);}else if ((gap + yUnit + top) <= yPoint && yPoint < (2*(gap + yUnit) + top)){setYzmsVisiable(YZM_5);}}else if((gap + xUnit) <= xPoint && xPoint < (2*(gap + xUnit))) {if ((gap + top) <= yPoint && yPoint < (gap + yUnit + top)) {setYzmsVisiable(YZM_2);}else if ((gap + yUnit + top) <= yPoint && yPoint < (2*(gap + yUnit) + top)){setYzmsVisiable(YZM_6);}}else if((2*(gap + xUnit)) <= xPoint && xPoint < (3*(gap + xUnit))) {if ((gap + top) <= yPoint && yPoint < (gap + yUnit + top)) {setYzmsVisiable(YZM_3);}else if ((gap + yUnit + top) <= yPoint && yPoint < (2*(gap + yUnit) + top)){setYzmsVisiable(YZM_7);}}else if((3*(gap + xUnit)) <= xPoint && xPoint < (4*(gap + xUnit))){if ((gap + top) <= yPoint && yPoint < (gap + yUnit + top)) {setYzmsVisiable(YZM_4);}else if ((gap + yUnit + top) <= yPoint && yPoint < (2*(gap + yUnit) + top)){setYzmsVisiable(YZM_8);}}}
}

Java实现12306登录和查票相关推荐

  1. C#利用HttpWebRequest、HttpWebResponse调用12306接口,实现登录、查票、买票。

    [免责申明]本文只为学习使用,若有用作商业.其他行为,与本人无关. 使用工具 - UI bootstrap - 后台C# - 插件 datetimepicker.js,select.js UI界面效果 ...

  2. java实现12306查票_[转]java抓取12306信息实现火车余票查询示例firefox

    最近在弄一个微信的公众帐号,涉及到火车票查询,之前用的网上找到的一个接口,但只能查到火车时刻表,12306又没有提供专门的查票的接口.今天突然想起自己直接去12306上查询,抓取查询返回的数据包,这样 ...

  3. Java获取12306余票信息(一)

    写在前面 写给自己,也分享给大家. Java获取12306余票信息(一) Java获取12306余票信息(二) Java获取12306余票信息(三) 步骤: 首先找找12306的API 1.打开谷歌浏 ...

  4. python爬虫抢火车票_利用Python实现12306爬虫--查票

    在上一篇文章(http://www.cnblogs.com/fangtaoa/p/8321449.html)中,我们实现了12306爬虫的登录功能,接下来,我们就来实现查票的功能. 其实实现查票的功能 ...

  5. 12306自动刷票下单-查票下单

    12306自动刷票下单-登录 前言 上篇写了12306登录,隔了快一个月了,才准备动手写下单篇,真的要非常感谢博客园的 Asimple朋友,如果不是看到你的留言,我几乎都忘了要写下篇了,这一点在简书上 ...

  6. 12306自动刷票下单-查票下单(二)

    前言 上篇写了12306登录,隔了快一个月了,才准备动手写下单篇,真的要非常感谢博客园的 Asimple朋友,如果不是看到你的留言,我几乎都忘了要写下篇了,这一点在简书上就不好,都没人看/(ㄒoㄒ)/ ...

  7. 第二篇 12306自动刷票下单-查票下单

    前言 上篇写了12306登录,隔了快一个月了,才准备动手写下单篇,真的要非常感谢博客园的 Asimple朋友,如果不是看到你的留言,我几乎都忘了要写下篇了,这一点在简书上就不好,都没人看/(ㄒoㄒ)/ ...

  8. 小年到了,回家抢票太难,用Python做个脚本12306自动查票以及自动购票....

    今天就是小年了,听说还有人买不到票?不要慌,今天咱们来用Python做一个自动查票抢票的脚本,24小时抢票,谁抢的过你!源码包已打包文件夹获取方式:点击这里[ Python全套资料] 即可获取. 准备 ...

  9. 快过年了,Python实现12306查票以及自动购票....

    嗨害大家好鸭!我是小熊猫~ 明天就是2023年啦~ 还有谁像我小熊猫一样没有回家的? 这次康康能不能12306抢票回家!!! Python实现12306查票以及自动购票 [代码来源]: 青灯教育-自游 ...

  10. Java获取12306余票信息(二)

    接上 前面我们说到如何用Firefox浏览器抓取数据,并 对json进行了分析,下面就是用Java代码来进行操作.以下代码都没有导入包,有需要自行导入 Java获取12306余票信息(一) Java获 ...

最新文章

  1. Java: 面向对象程序设计(上)
  2. mysql数据采集中间件_开源 | MySQL数据传输中间件—DTLE
  3. DLL中导出函数的声明有两种方式
  4. [Qt教程] 第27篇 XML(一)使用DOM读取XML文档
  5. lm opencv 算法_OpenCV进行图像相似度对比的几种办法
  6. 综述 | 卷积神经网络:从基础技术到研究前景
  7. 武汉大学计算机系学哪些专业,武汉大学最好的专业是什么(10大热门专业排名)...
  8. python3.8自带matlop和numpy吗_python3.8自带matlop和numpy吗_python之matloplib可视化
  9. 多功能笔记工具Notability创建甜甜圈图案的趣味教程
  10. 爱奇艺Android移动客户端app瘦身经验
  11. MySQL数据库基础理论
  12. C语言状态机模块实现
  13. DNS域名解析配置详解
  14. Excel文本如何间隔指定字符插入分隔符
  15. python画一棵树的心理测试_心理测验:空白纸上画棵树,破除心防从这里开始
  16. Calc3: Partial Derivative
  17. mac shell 清理缓存-如微信mac清理微信缓存
  18. 安装widows XP时蓝屏代码0X0000007B的问题的解决方案
  19. java实验四 综合应用实验
  20. 免费的编程中文书籍索引

热门文章

  1. 微信公众平台版面设计需要服务器,谈谈微信公众号如何快速在线排版设计好看又实用的方法...
  2. java poi dataformat_poi的data format可真不怎么样
  3. 控制台程序实现暂停功能
  4. 怎么用软件测试iPad,Apple:如何在iphone、ipad上安装一些常用命令行命令
  5. python time和datetime、pytz
  6. Springboot毕设项目房屋租赁系统4yvi2(java+VUE+Mybatis+Maven+Mysql)
  7. 无法绑定由多个部分组成的标识符 yvi312082007@163.com。
  8. 冒泡排序图解并通过Java实现
  9. fcm算法的MATLAB实现
  10. 使用BoundsChecker