<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    stone2083

    爬取交通違章信息的腳本

    會開車了,也慢慢不規矩起來了,于是乎,違章信息也慢慢多起來了,但是無法第一時間通知到自己。
    雖說,有個網站:http://www.hzti.com/service/qry/violation_veh.aspx?pgid=&type=1&node=249
    可以查詢非現場違章情況,
    不過:
    1.我是懶人,主動去查詢的時候不太樂意做
    2.車輛識別碼,永遠記不住
    3.每次輸驗證碼,挺麻煩的

    所以,我希望,只要有違規信息,能主動通知到我。
    程序員嘛,自己動手,豐衣足食。 :)

    實現思路:
    1.爬取http://www.hzti.com/service/qry/violation_veh.aspx?pgid=&type=1&node=249的信息
    2.使用飛信命令發送短信消息(http://www.it-adv.net/)--免費的哦。

    實現難點:
    1.驗證碼破擊
    我對圖片毫無研究,幸好它的驗證碼太簡單了,只有#000000(黑色)才是驗證碼信息,其他的都是無用信息。并且元素的位置都是固定的。
    2.網站用.net實現,在post信息的時候,有一陀無用的數據信息。所幸,post數據的時候,并沒有對數據做加密,不然都挺難判斷具體參數的意義


    驗證碼破解思路:
    1.自我學習:通過程序下載多張驗證碼圖片,去噪點,切割圖片元素,找出最清楚的0-9這10個元素圖片。作為樣本;
    2.破解:下載需要破解的驗證碼圖片,去噪點,切割圖片元素,和樣本像素比較,相似度在95%以上的視為一致。

    得到圖片信息并且去噪點的方法:
     1 // 得到圖片信息,去除噪點的圖片
     2 BufferedImage getBufferedImage(InputStream in) throws Exception {
     3     BufferedImage img = ImageIO.read(in);
     4     for (int i = 0; i < img.getWidth(); i++) {
     5         for (int j = 0; j < img.getHeight(); j++) {
     6             // 黑色的才是驗證碼
     7             if (!CODE_RGB.equals(Integer.toHexString(img.getRGB(i, j)))) {
     8                 img.setRGB(i, j, -1);
     9             }
    10         }
    11     }
    12     in.close();
    13     return img;
    14 }
    得到圖片像素信息(RGB值)
     1 int[][] getImageFeature(BufferedImage img) throws Exception {
     2     int[][] feature = new int[WIDTH][HEIGHT];
     3     for (int i = 0; i < WIDTH; i++) {
     4         for (int j = 0; j < HEIGHT; j++) {
     5             if (img.getWidth() < i || img.getHeight() < j) {
     6                 continue;
     7             }
     8             feature[i][j] = img.getRGB(i, j);
     9         }
    10     }
    11     return feature;
    12 }

    下載多張圖片,切割,保存,人工尋找最清晰的0-9這10個元素圖片
    public void learn(int count) throws Exception {
        
    for (int c = 0; c < count; c++) {
            BufferedImage img 
    = getBufferedImage(new URL(IMG_URL).openStream());
            
    // 保存樣本
            for (int i = 1; i < 5; i++) {
                BufferedImage bi 
    = img.getSubimage(i * X_BASE, Y_BASE, WIDTH, HEIGHT);
                String name 
    = String.valueOf(c) + "_" + String.valueOf(i);
                ImageIO.write(bi, IMAGE_FORMAT, 
    new File(IMG_REF + "learn/" + name + ".bmp"));
            }
        }
    }
    備注:
    GifImageWriter有bug。對于BufferedImage的subBufferedImage輸出一直有問題。Sun很早就有人提交了bug,貌似還沒有修復。

    破解代碼(說破解,有點汗。。。其實壓根兒和破解沒關系)
     1 public String crack(InputStream in) throws Exception {
     2     BufferedImage img = getBufferedImage(in);
     3     StringBuilder ret = new StringBuilder();
     4 
     5     for (int c = 1; c < 5; c++) {
     6         BufferedImage bi = img.getSubimage(c * X_BASE, Y_BASE, WIDTH, HEIGHT);
     7         int[][] feature = getImageFeature(bi);
     8 
     9         for (ImageCode ic : imageCodes) {
    10             int success = 0;
    11             for (int i = 0; i < WIDTH; i++) {
    12                 for (int j = 0; j < HEIGHT; j++) {
    13                     if (feature[i][j] == ic.getFeature()[i][j]) {
    14                         success++;
    15                     }
    16                 }
    17             }
    18             // 判斷是否匹配上
    19             if (success * 100.0 / (WIDTH * HEIGHT) > 95) {
    20                 ret.append(ic.getCode());
    21 
    22                 continue;
    23             }
    24         }
    25 
    26     }
    27 
    28     return ret.toString();
    29 }
    其中,imageCodes是初始化準備的0-9這10個元素圖片的特征信息和對應的值

    之后的事情就簡單了。通過LiveHttpHeader找到Post提交的數據,通過shell腳本,模擬。搞定。
    主要用到curl命令
     1 curl -"ASP.NET_SessionId=$SESSION_ID" "$IMAGE_CODE_URL" -$TMP_CODE_BASE
     2 code=`java -cp lib/traffic.jar TrafficImgCracker $TMP_CODE_BASE`
     3 
     6 curl -"$AGENT" -$TRAFFIC_URL -"ASP.NET_SessionId=$SESSION_ID;isLoginedWeb=T;ImageV=$code" -"$QUERY_PARAM" "$TRAFFIC_URL" -$TMP_CONTENT_BASE
     7 
     8 now=`cat $TMP_CONTENT_BASE | grep -'<td class="xxcxsspoptds">' | sed 's/<[^>]*>//g' | sed 's/\s\+/ /g'`
     9 his=`cat $HIS_CONTENT_BASE | grep -'<td class="xxcxsspoptds">' | sed 's/<[^>]*>//g' | sed 's/\s\+/ /g'`
    10 
    11 if [ "$now" != "$his" ];then
    12     msg=`cat $TMP_CONTENT_BASE | grep -'<td class="xxcxsspoptds">' | sed 's/<[^>]*>//g' | sed 's/\s\+/ /g' | head -6`
    13     echo $msg
    14     #send
    15 fi
    shell一直不熟,代碼估計挺猥瑣的。。。


    最后通過飛信命令發送消息:
    1 $FETION_HOME/fetion --mobile=12345678901 --pwd=bugaosuni --to=12345678901 --msg-utf8="$msg"

    廣告下:
    飛信命令行,挺好的東東,像系統報警等,都能考慮用它來完成。

    最后,附上圖片破解的代碼:
      1 import java.awt.image.BufferedImage;
      2 import java.io.File;
      3 import java.io.FileInputStream;
      4 import java.io.InputStream;
      5 import java.net.URL;
      6 import java.util.ArrayList;
      7 import java.util.List;
      8 
      9 import javax.imageio.ImageIO;
     10 
     11 /**
     12  * 交通網圖片分析工具
     13  * 
     14  * @author <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> 2010-10-10
     15  */
     16 public class TrafficImgCracker {
     17 
     18     private static final String IMG_URL      = "http://www.hzti.com/government/CreateCheckCode.aspx";
     19     private static final String IMG_REF      = "/home/stone/tmp/imgref/";
     20 
     21     private static final int    X_BASE       = 9;
     22     private static final int    Y_BASE       = 0;
     23     private static final int    WIDTH        = 7;
     24     private static final int    HEIGHT       = 22;
     25     private static final String IMAGE_FORMAT = "bmp";
     26     private static final String CODE_RGB     = "ff000000";
     27 
     28     private List<ImageCode>     imageCodes   = new ArrayList<ImageCode>(10);
     29 
     30     public static void main(String[] args) throws Exception {
     31         if (args.length != 1) {
     32             System.out.println("java TrafficImgCracker $file_path");
     33             System.exit(1);
     34         }
     35 
     36         String file = args[0];
     37 
     38         TrafficImgCracker cracker = new TrafficImgCracker();
     39         cracker.init();
     40         System.out.print(cracker.crack(file));
     41     }
     42 
     43     /**
     44      * init
     45      * 
     46      * @throws Exception
     47      */
     48     public void init() throws Exception {
     49         File ref = new File(IMG_REF);
     50         File[] files = ref.listFiles();
     51         for (File f : files) {
     52             if (!f.isFile()) {
     53                 continue;
     54             }
     55             String code = f.getName().substring(0, f.getName().indexOf("."));
     56             BufferedImage img = getBufferedImage(new FileInputStream(f));
     57             int[][] feature = getImageFeature(img);
     58             // add to image codes
     59             imageCodes.add(new ImageCode(code, feature));
     60         }
     61     }
     62 
     63     /**
     64      * crack
     65      * 
     66      * @param file
     67      * @return
     68      * @throws Exception
     69      */
     70     public String crack(String file) throws Exception {
     71         return crack(new FileInputStream(file));
     72     }
     73 
     74     /**
     75      * crack image code
     76      * 
     77      * @param in image input stream
     78      * @return code
     79      */
     80     public String crack(InputStream in) throws Exception {
     81         BufferedImage img = getBufferedImage(in);
     82         StringBuilder ret = new StringBuilder();
     83 
     84         for (int c = 1; c < 5; c++) {
     85             BufferedImage bi = img.getSubimage(c * X_BASE, Y_BASE, WIDTH, HEIGHT);
     86             int[][] feature = getImageFeature(bi);
     87 
     88             for (ImageCode ic : imageCodes) {
     89                 int success = 0;
     90                 for (int i = 0; i < WIDTH; i++) {
     91                     for (int j = 0; j < HEIGHT; j++) {
     92                         if (feature[i][j] == ic.getFeature()[i][j]) {
     93                             success++;
     94                         }
     95                     }
     96                 }
     97                 // 判斷是否匹配上
     98                 if (success * 100.0 / (WIDTH * HEIGHT) > 95) {
     99                     ret.append(ic.getCode());
    100 
    101                     continue;
    102                 }
    103             }
    104 
    105         }
    106 
    107         return ret.toString();
    108     }
    109 
    110     /**
    111      * learn
    112      * 
    113      * @param count learning count
    114      * @throws Exception
    115      */
    116     public void learn(int count) throws Exception {
    117         for (int c = 0; c < count; c++) {
    118             BufferedImage img = getBufferedImage(new URL(IMG_URL).openStream());
    119             // 保存樣本
    120             for (int i = 1; i < 5; i++) {
    121                 BufferedImage bi = img.getSubimage(i * X_BASE, Y_BASE, WIDTH, HEIGHT);
    122                 String name = String.valueOf(c) + "_" + String.valueOf(i);
    123                 ImageIO.write(bi, IMAGE_FORMAT, new File(IMG_REF + "learn/" + name + ".bmp"));
    124             }
    125         }
    126     }
    127 
    128     // 得到圖片信息,去除噪點的圖片
    129     private BufferedImage getBufferedImage(InputStream in) throws Exception {
    130         BufferedImage img = ImageIO.read(in);
    131         for (int i = 0; i < img.getWidth(); i++) {
    132             for (int j = 0; j < img.getHeight(); j++) {
    133                 // 黑色的才是驗證碼
    134                 if (!CODE_RGB.equals(Integer.toHexString(img.getRGB(i, j)))) {
    135                     img.setRGB(i, j, -1);
    136                 }
    137             }
    138         }
    139         in.close();
    140         return img;
    141     }
    142 
    143     // 得到圖片特征
    144     private int[][] getImageFeature(BufferedImage img) throws Exception {
    145         int[][] feature = new int[WIDTH][HEIGHT];
    146         for (int i = 0; i < WIDTH; i++) {
    147             for (int j = 0; j < HEIGHT; j++) {
    148                 if (img.getWidth() < i || img.getHeight() < j) {
    149                     continue;
    150                 }
    151                 feature[i][j] = img.getRGB(i, j);
    152             }
    153         }
    154         return feature;
    155     }
    156 
    157     /**
    158      * image code bean
    159      * 
    160      * @author <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> 2010-10-10
    161      */
    162     public static class ImageCode {
    163 
    164         private String  code;
    165         private int[][] feature;
    166 
    167         public ImageCode(String code, int[][] feature){
    168             this.code = code;
    169             this.feature = feature;
    170         }
    171 
    172         public String getCode() {
    173             return code;
    174         }
    175 
    176         public void setCode(String code) {
    177             this.code = code;
    178         }
    179 
    180         public int[][] getFeature() {
    181             return feature;
    182         }
    183 
    184         public void setFeature(int[][] feature) {
    185             this.feature = feature;
    186         }
    187     }
    188 
    189 }

    ====================================================================
    10月29日編輯的內容:
    最近在學python,用python寫了個版本,發覺確實簡潔很多:
     1 import os, sys, Image
     2 
     3 class TrafficImgCracker(object):
     4     """
     5         交通信息網站圖片破解
     6     """
     7    
     8     def __init__(self, base):
     9         """
    10            base:參考圖片基本路徑
    11            codes:圖片code和feature的元組集合
    12         """
    13         self.base = base
    14         self.codes = []
    15         
    16         for i in [images for images in os.listdir(base) if images.endswith('bmp')]:
    17             self.codes.append((i[0], list(Image.open(base + i).getdata())))
    18 
    19 
    20     def crack(self, imgfile):
    21         img = Image.open(imgfile)
    22         ret = []
    23         for i in range(15):
    24             i = img.crop((i * 9, 0, i * 9 + 722))
    25             feature = [f if(f == 40else 15 for f in i.getdata()]
    26             ret.append(self._getcode(feature))
    27         return "".join(ret)
    28 
    29 
    30     def _getcode(self, feature):
    31         for code in self.codes:
    32             ref = zip(code[1], feature)
    33             if(len([x for x in ref if x[0] == x[1]]) * 100.0 / len(ref) > 95):
    34                 return code[0]
    35         return None





    posted on 2010-10-29 18:30 stone2083 閱讀(3127) 評論(8)  編輯  收藏 所屬分類: java

    Feedback

    # re: 爬取交通違章信息的腳本 2010-10-13 12:55 nkjava

    強人  回復  更多評論   

    # re: 爬取交通違章信息的腳本 2010-10-14 10:52 珂兒

    很強大  回復  更多評論   

    # re: 爬取交通違章信息的腳本[未登錄] 2010-10-14 20:49 java

    程序員嘛,自己動手,豐衣足食。確實很強大···  回復  更多評論   

    # re: 爬取交通違章信息的腳本[未登錄] 2010-10-14 23:19 阿風

    立哥有IT懶人氣質。哈哈  回復  更多評論   

    # re: 爬取交通違章信息的腳本 2010-10-15 18:18 stone2083

    @阿風
    其實是周末下午沒事情干,弄著玩的。
    之前沒有涉及過圖片相關的,趁機也稍微學習下。 :)  回復  更多評論   

    # re: 爬取交通違章信息的腳本 2010-10-29 14:31 wuzhengju

    抱著感興的態度,去看一下這網站

    發現一個更簡單的獲取他們的驗證碼

    Cache-Control private
    Content-Length 1753
    Content-Type text/html; charset=utf-8
    Server Microsoft-IIS/7.0
    X-AspNet-Version 2.0.50727
    Set-Cookie ImageV=5062; path=/
    X-Powered-By ASP.NET
    Date Fri, 29 Oct 2010 06:25:29 GMT



    ImageV就是他們驗證的值,寫在cookie,直接獲取cookie就行了  回復  更多評論   

    # re: 爬取交通違章信息的腳本 2010-10-29 18:46 stone2083

    @wuzhengju
    唉,我這個土人。。。
    之前思維一直停留在如何破解驗證碼上了。直到寫完這個東東,在寫腳本的時候:
    curl -A "$AGENT" -e $TRAFFIC_URL -b "ASP.NET_SessionId=$SESSION_ID;isLoginedWeb=T;ImageV=$code" -d "$QUERY_PARAM" "$TRAFFIC_URL" -o $TMP_CONTENT_BASE
    才發現在cookie中已經存在這個ImageV了。
    不過為時已晚,米已城粥。。。 :)
    ================================================
    好久不見了,最近工作還順利嗎?

      回復  更多評論   

    # re: 爬取交通違章信息的腳本 2010-10-29 21:32 wuzhengju

    @stone2083
    最近工作還好,要學的東西很多!
    得多向你學習!  回復  更多評論   

    主站蜘蛛池模板: 一级毛片视频免费| 亚洲精品综合久久| a级黄色毛片免费播放视频| 久久精品国产99国产精品亚洲| 亚洲日本在线观看视频| 四虎在线视频免费观看| 久操视频在线免费观看| 日韩久久无码免费毛片软件| 亚洲一区无码中文字幕乱码| 亚洲永久无码3D动漫一区| 国产乱子伦精品免费女| 国产人成免费视频网站| 精品国产免费一区二区三区香蕉| 国产亚洲精彩视频| 亚洲欧洲无码一区二区三区| 久久亚洲日韩看片无码| 亚洲欧洲日产国码无码网站| 免费成人在线观看| 国产高清免费在线| 国产精品美女午夜爽爽爽免费| 91视频免费观看| 一级成人a免费视频| 国产成人亚洲综合a∨| 亚洲精品美女久久久久久久| 亚洲一区二区三区四区视频| 亚洲精品影院久久久久久| 久久亚洲精品无码| 亚洲国产精品无码av| 中文字幕不卡亚洲 | 韩国二级毛片免费播放| 亚洲免费综合色在线视频| 久久精品免费一区二区| 曰批视频免费40分钟试看天天| 久久免费国产精品一区二区| 伊人免费在线观看| 十八禁在线观看视频播放免费| 中文字幕不卡免费视频| 十八禁在线观看视频播放免费| 免费在线观看一级片| 日韩精品极品视频在线观看免费| 无码人妻丰满熟妇区免费|