如何使用OCR圖像識別繞過自如房價的反Spider策略

公元2015 第28個秋天html

九月的午後,微風吹動窗紗,從24樓看去遠處的白雲一朵朵的棉花糖浮在空中,兩個街角外教堂上的鐘敲響了第十三下。git

X坐在桌前,雙層的書桌上擺滿了各類漫畫,電腦旁邊的《新世紀福音戰士》是他最近從舊物箱裏從新翻出來的,望了一眼窗外,閉上眼睛深深地吸了一口氣。github

他又要換房子了,每到這個季節老是要從新換個地方,換一個身份,周圍都是陌生人才會讓他有安全感,這樣就沒有人會發現他的祕密。chrome


打開ZR租房的網站,房源的搜索列表頁面映入眼前,適合本身的房子老是本身租不起的。可是X仍是要從裏面挑選最優的。數組

Spider是個很不錯的選擇,Goquery也是個很好的選擇安全

軍刀工具 Goquery

採用dom的選擇器語法,若是使用Chrome很是容易提取元素的選擇器。dom

chrome 右鍵->檢查->選擇須要的dom元素->代碼上右鍵->copy->copy selector

安裝

go get github.com/PuerkitoBio/goquery

使用方法

讀取頁面內容生成Documentide

res, e := http.Get(url);
if e != nil {
    // e
}

defer res.Body.Close()

doc, e := goquery.NewDocumentFromReader(res.Body)
if e != nil {
    // e
}

使用選擇器選擇頁面內容工具

doc.Find("#houseList > li").Each(func(i int, selection *goquery.Selection) {
    // 房屋名稱
    houseName := selection.Find("div.txt > h3 > a").Text()
}

或者可使用直接選取的方式測試

// 獲取經緯度
houseLat, _ := doc.Find("#mapsearchText").Attr("data-lat")
houseLng, _ := doc.Find("#mapsearchText").Attr("data-lng")

反蜘蛛策略

常見的頁面元素價格,是相似<span>$5880</span>這種實現方式,可是ZR採用了另一種。
ta的價格是經過CSS樣式表對背景圖片的偏移來實現的,例如價格¥2690的實現:

<span style="background-position:1000px" class="num rmb">¥</span>
<span style="background-position:-90px" class="num"></span>
<span style="background-position:-210px" class="num"></span>
<span style="background-position:-0px" class="num"></span>
<span style="background-position:-240px" class="num"></span>

圖片地址是

images/price/0fcc0d83409c547d3a9d038cc7808fa3s.png

圖片的內容是

6532148907

那麼針對如上的狀況X提出一個方案:根據偏移量來轉換獲得價格

這個思路是對的,可是仔細測試後,發現每次訪問,圖片的地址都會發生變化,對應的圖片裏面的數字的排序也會發生變化。

這時X的嘴角露出了微笑,很明顯

  1. 圖片每次訪問都發生變化
  2. 價格的偏移量數據也會發生變化
  3. 爲了保證價格每次展現都同樣,那麼必須有一個跟圖片對應的數字轉換規則

結論

  1. 沒法經過直接轉換方式
  2. 尋找這個圖片偏移量和價格的轉換規則

因而X經過Chrome的search找到了價格元素修改的js代碼

var ROOM_PRICE = {"image":"//xxxx.com/phoenix/pc/images/price/0fcc0d83409c547d3a9d038cc7808fa3s.png","offset":[[3,7,0,8],[3,7,0,8],[2,3,0,8],[2,3,7,8],[2,0,2,8],[3,7,2,8],[2,2,7,8],[2,2,2,8],[3,6,7,8],[3,6,7,8],[2,8,2,8],[2,8,7,8],[3,7,0,8],[2,4,7,8],[2,5,7,8],[2,8,7,8],[2,5,7,8],[2,3,7,8]]};


// 這一段不用看了,其實就是將圖片上的字符,按照上面ROOM_PRICE的規則,按照數組的索引取出來便可
$('#houseList p.price').each(function(i){
    var dom = $(this);
    if(!ROOM_PRICE['offset'] || !ROOM_PRICE['offset'][i]) return ;
    var pos = ROOM_PRICE['offset'][i];
    for(i in pos){
        var inx = pos.length -i -1;
        var seg = $('<span>', {'style':'background-position:-'+(pos[inx]*offset_unit)+'px', 'class':'num'});
        dom.prepend(seg);
    }
    var seg = $('<span>', {'style':'background-position:1000px', 'class':'num rmb'}).html('¥');
    dom.prepend(seg);
});

經過上面這段代碼,整個反爬蟲策略就暴露無遺了,其實設計者也是心思巧妙。

OCR 解密之 Tesseract 超立方體

X 在筆記本上寫下了以下的話:

  1. 咱們有了解密規則
  2. 有了待解密圖片
  3. 須要提取圖片內容,做爲解密的字符串,交由程序處理

因而利用到了另外一款軍刀工具 Tesseract

介紹

Tesseract是一個光學字符識別引擎,支持多種操做系統。Tesseract是基於Apache許可證的自由軟件,自2006 年起由Google贊助開發。2006年,Tesseract被認爲是最精準的開源光學字符識別引擎之一。

Tesseract 翻譯過來是 超立方體

安裝

這裏是Wiki :https://github.com/tesseract-...

Mac 下的安裝很簡單

brew install tesseract

安裝完畢以後能夠解析下試試

➜  go tesseract ~/Desktop/7d9a5bb074a89f93a5b4e82bea5dc872s.png stdout --psm 6
2436851907

安裝Go的package

go get -v -t github.com/otiai10/gosseract

使用方法

直接上代碼了,調用很方便

package ocr

import (
    "fmt"
    "net/http"
    "os"
    "github.com/otiai10/gosseract"
    "io/ioutil"
    "io"
    "bytes"
)

func Parse(imageUrl string)(string) {

    f, _ := os.Create("s.png")
    defer f.Close()

    resp, _ := http.Get(imageUrl)
    defer  resp.Body.Close()

    pic, _ := ioutil.ReadAll(resp.Body)
    io.Copy(f, bytes.NewReader(pic))

    client := gosseract.NewClient()
    defer client.Close()

    client.SetImage("./s.png")
    text, e := client.Text()

    if e != nil {
        fmt.Println("error")
    }

    return text
}

最終,使用OCR解密了圖片內容,再經過轉換才的到了真正的價格

{
    "_id" : ObjectId("5b88dfa8644d03deebc6ba6a"),
    "name" : "天通苑中苑4居室-南臥",
    "image" : "http://img.xxxx.com/pic/house_images/g2m1/M00/66/82/ChAFB1uGM-KAZfN6AAQ6qYhGUtc084.JPG_C_264_198_Q80.jpg",
    "price" : "2290",
    "url" : "http://www.xxxx.com/z/vr/61676366.html",
    "size" : "13 ㎡",
    "floor" : "5/6層",
    "room" : "4室1廳",
    "loc" : [ 
        "40.077562", 
        "116.432684"
    ],
    "toilet" : 0,
    "balcony" : 1
}

/* 2 */
{
    "_id" : ObjectId("5b88dfa9644d03deebc6ba6f"),
    "name" : "天通苑中苑4居室-南臥",
    "image" : "http://img.xxxx.com/pic/house_images/g2m1/M00/4F/6E/ChAFBlt9cXaAY-38AARyYlEU6S4611.JPG_C_264_198_Q80.jpg",
    "price" : "2430",
    "url" : "http://www.xxxx.com/z/vr/61663763.html",
    "size" : "11.8 ㎡",
    "floor" : "5/10層",
    "room" : "4室1廳",
    "loc" : [ 
        "40.077562", 
        "116.432684"
    ],
    "toilet" : 0,
    "balcony" : 1
}

/* 3 */
{
    "_id" : ObjectId("5b88dfa9644d03deebc6ba74"),
    "name" : "天通苑本三區4居室-南臥",
    "image" : "http://img.xxxx.com/pic/house_images/g2m1/M00/5A/E5/ChAFBluBaA-APjRgAASBBLkpT0w953.JPG_C_264_198_Q80.jpg",
    "price" : "2790",
    "url" : "http://www.xxxx.com/z/vr/61666427.html",
    "size" : "25.5 ㎡",
    "floor" : "6/6層",
    "room" : "4室1廳",
    "loc" : [ 
        "40.066064", 
        "116.426734"
    ],
    "toilet" : 0,
    "balcony" : 1
}

END

ZR若是想使用這種方式來作到反爬蟲,其實只是限制了一下反制門檻,可是設計很巧妙。其實本次也是初試Tesseract-OCR這款軍刀工具。

相關文章
相關標籤/搜索