# 幼兒園資料爬蟲 (1)
###### tags: `Python` `Crawler` `OCR`
https://github.com/mingpepe/kindergarten_crawler
## 序
目標是爬[這個](https://ap.ece.moe.edu.tw/webecems/pubSearch.aspx)。如果趕時間的話我會用 [selenium](https://www.selenium.dev/),但我不趕。
## Get HTML
本來以為選個地點再搜尋就是 HTTP GET 後面再帶些參數,沒想到並不是。
首先 GET 目標網頁會 [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#:~:text=The%20Set%2DCookie%20HTTP%20response,sent%20in%20the%20same%20response.)。後面的 HTTP 操作都需要這些 cookie。

接著選擇縣市,會 POST ㄧ些資料回去。


然後有些資料回應。

這裡遇到三個問題。
1. 送出去的這些 __ 開頭的欄位[是什麼](https://stackoverflow.com/questions/12786199/access-viewstate-eventvalidation-in-c-sharp)? 就是在 HTML 裡放些隱藏欄位,POST 時要帶上這些資訊。
2. 從瀏覽器的 dev tool 解析過的地方看起來,__LASTFOCUS 是有值的,但從 source 看是沒有的。只能說介面還有改善的空間。
3. POST 的回應除了ㄧ些 HTML 外還有ㄧ些更新 view state 值的資訊。
## OCR
雖然沒有實際做過,不過我直覺認為現有的工具辨識下面這種圖應該不是太難。

沒想到 OpenCV 裡竟然沒有這種 OCR,於是找到了 [pytesseract](https://pypi.org/project/pytesseract/),就是把 [tesseract](https://github.com/tesseract-ocr/tesseract) 再包一層。
結果效果超級爛,細看了一下發現[前處裡還是要自己做](https://tesseract-ocr.github.io/tessdoc/ImproveQuality.html)。
一開始的想法是轉灰階再 erode 小雜訊就好,但發現 erode 跟 dilation 的效果跟我認知的一直相反,原來是 OpenCV 假設白/黑分別是前景/背景,跟現在要用的正好相反。
好吧,那應該用 dilation 就可以了,不過試了些參數效果都不理想,最後還是決定自己做。總之概念就是 erode 掉小雜訊再二值化,結果長這樣。

我覺得應該要可以了,但結果 tesseract 表現依然很差。
目前的設定是```tessedit_char_whitelist=0123456789 --psm 7 -l eng```。待解決。
## 其它小問題
#### HTTP POST 回來的資料是什麼格式?
一些 HTML + 用 | 分隔的一些資料,如果不是通用的格式可以由瀏覽器來更新,那肯定要有對應的程式來處理。最後在 [```ScriptResource.axd```](https://social.msdn.microsoft.com/Forums/en-US/7d2a8894-d5a1-4314-96d3-bba2a8c48be4/what-is-scriptresourceaxd)找到,原來是我大微軟用來實現 AJAX 的東西。似乎是不需要特別理解。
```javascript=
_parseDelta: function(h) {
var c = h.get_responseData(), d, i, E, F, D, b = 0, e = null, k = [];
while (b < c.length) {
d = c.indexOf("|", b);
if (d === -1) {
e = this._findText(c, b);
break
}
...
```
#### 奇怪的 Cookie
```
_pk_id.xxx
_pk.ref.xxx
```
翻了一下發現是在 [matomo.js](https://github.com/matomo-org/matomo/blob/master/js/piwik.js) 裡定義的。用來分析網站的,第一次知道這個東西。順便發現 [Cookie Database](https://cookiedatabase.org/cookie/matomo/_pk_id/) 這個網站。
```javascript=
function getCookieName(baseName) {
// NOTE: If the cookie name is changed, we must also update the MatomoTracker.php which
// will attempt to discover first party cookies. eg. See the PHP Client method getVisitorId()
return configCookieNamePrefix + baseName + '.' + configTrackerSiteId + '.' + domainHash;
}
```