如何实现一个拍照搜题功能
如何實(shí)現(xiàn)一個(gè)拍照搜題功能
主要分4步數(shù)據(jù)抓取,數(shù)據(jù)處理 ,圖文轉(zhuǎn)換,搜索引擎
1.數(shù)據(jù)抓取
主要抓取網(wǎng)頁(yè)網(wǎng)站題庫(kù)數(shù)據(jù)
可抓取題庫(kù)網(wǎng),無(wú)憂網(wǎng),新東方題庫(kù)
技術(shù)實(shí)現(xiàn):
利用jsoup抓取相應(yīng)網(wǎng)站的數(shù)據(jù),利用htmlunit模擬客戶端抓取數(shù)據(jù)
通過(guò)下面鏈接可下載Jsoup的jar包
http://central.maven.org/maven2/org/jsoup/jsoup/1.12.1/jsoup-1.12.1.jar
通過(guò)下面鏈接可下載htmlunit的jar包
http://central.maven.org/maven2/net/sourceforge/htmlunit/htmlunit/2.35.0/htmlunit-2.35.0.jar
遇到問(wèn)題:
js異步加載 :
如組卷網(wǎng)會(huì)通過(guò)js異步加載導(dǎo)致jsoup第一步抓取的只是一個(gè)網(wǎng)站空殼,抓不到想要的數(shù)據(jù)
可以通過(guò)htmlunit技術(shù)去模擬瀏覽器,把js異步加載過(guò)程也模擬完成后能獲得正確數(shù)據(jù)
需要登陸:
有些網(wǎng)站一些頁(yè)面需要登陸操作
可以通過(guò)設(shè)置hander cookie來(lái)跳過(guò)登陸,但是cookie部分?jǐn)?shù)據(jù)會(huì)動(dòng)態(tài)發(fā)生改變需要時(shí)時(shí)注意,
public static Document setHeader(String url) throws IOException {//設(shè)置header返回docMap<String, String> header = new HashMap<String, String>();Connection conn=Jsoup.connect(url);conn.header("Host","www.tiku.cn");conn.header("Connection","keep-alive");conn.header("User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:66.0) Gecko/20100101 Firefox/66.0");conn.header("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");conn.header("Accept-Encoding","gzip, deflate");conn.header("Accept-Language","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");conn.header("Cookie","Hm_lvt_02f32149c7ea90d0cd47ed89025e457c=1555984749,1555986859,1556607888,1557306767; PHPSESSID=5i8v8easa3uhkev2r36uennqai; Hm_lpvt_02f32149c7ea90d0cd47ed89025e457c=1557399030; AD=None; token=6ce06f56f40d000c3bb79b7a65bed7e8; userId=25431; isLogin=1");//題庫(kù)網(wǎng)的PHPSESSID會(huì)動(dòng)態(tài)改變的得實(shí)時(shí)更新conn.header("Referer","http://www.tiku.cn/");//設(shè)置header的參數(shù)conn.execute();return conn.get(); }或者通過(guò)htmlunit取模擬登陸
CookieManager cm=webClient.getCookieManager();//得到當(dāng)前分配得到的cookieSet<Cookie> cookies=((CookieManager) cm).getCookies();Iterator<Cookie> it=cookies.iterator();while(it.hasNext()){webClient.getCookieManager().addCookie(it.next());}rootPage=webClient.getPage(url);HtmlForm form=rootPage.getForms().get(0);//獲取當(dāng)前頁(yè)面的表單HtmlInput name=form.getInputByName("LoginForm[username]");HtmlInput pwd=form.getInputByName("LoginForm[password]");name.setValueAttribute("17684721017");pwd.setValueAttribute("123456");HtmlButton btn= (HtmlButton) rootPage.getByXPath("/html/body/div/div/form/div/div[3]/button").get(0);rootPage=btn.click();//獲得登陸后的頁(yè)面訪問(wèn)頻率限制:
某些網(wǎng)站對(duì)于一個(gè)ip有訪問(wèn)次數(shù)限制,所以需要正確線程池大小,而且盡量減少一次抓取所需要的訪問(wèn)次數(shù)
而且訪問(wèn)次數(shù)過(guò)多會(huì)導(dǎo)致網(wǎng)站連接延遲增加所以要提高連接超時(shí)限制
鎖賬戶和ip機(jī)制
有些網(wǎng)站會(huì)有個(gè)動(dòng)態(tài)黑名單,封鎖異常多次訪問(wèn)的ip和賬戶
2.抓取數(shù)據(jù)的處理
遇到問(wèn)題
抓取的數(shù)據(jù)可能是xml代碼,json代碼,其中可能帶有html特殊字符,所以需要對(duì)其去轉(zhuǎn)義,圖片地址有可能是不帶域名的所以處理的時(shí)候得加上域名
str= str.replace("<","<"); str= str.replace(""","\""); str= str.replace(">",">"); str= str.replace("&","&"); str= str.replace("'","'"); str= str.replace(""","");3.OCR技術(shù)(文字識(shí)別)
| iocr | 百度 | http://ai.baidu.com/tech/ocr/iocr | 否 | 每個(gè)賬戶50000次/天 | |
| tesseract | 谷歌 | 作為開(kāi)源項(xiàng)目發(fā)布在Google Project上 | 是 | 無(wú)限制 | 官方字庫(kù)準(zhǔn)確率過(guò)低,需要自己訓(xùn)練字庫(kù) |
百度ocr調(diào)用實(shí)現(xiàn)
將圖片文件進(jìn)行轉(zhuǎn)碼獲得一個(gè)處理后的字符串
byte[] imgData = FileUtil.readFileByBytes(filePath);//需要自定義兩個(gè)工具類 String imgStr = Base64Util.encode(imgData); String params = URLEncoder.encode("image", "UTF-8") + "=" + URLEncoder.encode(imgStr, "UTF-8");//Base64Util,FileUtil這兩個(gè)是自定義的工具類將圖片文件轉(zhuǎn)碼利用百度對(duì)每個(gè)賬戶分配的 API Key 和 Secret Key 獲得新的accessToken通行證
public static String getAuth(String ak, String sk) {// 獲取token地址String authHost = "https://aip.baidubce.com/oauth/2.0/token?";String getAccessTokenUrl = authHost// 1. grant_type為固定參數(shù)+ "grant_type=client_credentials"// 2. 官網(wǎng)獲取的 API Key+ "&client_id=" + ak// 3. 官網(wǎng)獲取的 Secret Key+ "&client_secret=" + sk;try {URL realUrl = new URL(getAccessTokenUrl);// 打開(kāi)和URL之間的連接HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();connection.setRequestMethod("GET");connection.connect();// 獲取所有響應(yīng)頭字段Map<String, List<String>> map = connection.getHeaderFields();// 遍歷所有的響應(yīng)頭字段for (String key : map.keySet()) {System.err.println(key + "--->" + map.get(key));}// 定義 BufferedReader輸入流來(lái)讀取URL的響應(yīng)BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));String result = "";String line;while ((line = in.readLine()) != null) {result += line;}/*** 返回結(jié)果示例*/System.err.println("result:" + result);JSONObject jsonObject = new JSONObject(result);String access_token = jsonObject.getString("access_token");return access_token;} catch (Exception e) {System.err.printf("獲取token失敗!");e.printStackTrace(System.err);}return null;}通過(guò)訪問(wèn)這個(gè)url可以得到通行證碼
再通過(guò)http訪問(wèn)百度給的接口,需要在url地址帶上通行證信息和圖像處理后的字符串
String result = HttpUtil.post(otherHost, accessToken, params);//HttpUtil是一個(gè)自定義的連接類最后獲得百度傳回的json文件,獲得的文件格式為識(shí)別的每一行的字,所以好得處理下把每行字取出來(lái)合并
遇到問(wèn)題
百度ocr api有賬戶次數(shù)限制 每個(gè)賬戶5w次/日
開(kāi)源免費(fèi)的tesseract的精度太低,需要訓(xùn)練詞庫(kù),訓(xùn)練詞庫(kù)的方法可以通過(guò)下面這個(gè)博客學(xué)習(xí)
https://www.cnblogs.com/wzben/p/5930538.html
4.搜索引擎的搭建
技術(shù)實(shí)現(xiàn)
利用solr框架搭建一個(gè)針對(duì)題目title的搜索引擎
通過(guò)下面鏈接下載solr相關(guān)文件
http://mirror.bit.edu.cn/apache/lucene/solr/8.1.0/solr-8.1.0-src.tgz
配置要點(diǎn):可查看微博https://www.cnblogs.com/xuyiqing/p/8707966.html
通過(guò)官網(wǎng)下載的文件,可直接通過(guò)終端啟動(dòng)solr,有幾個(gè)重要的jar包需要添加,極其重要缺一不可
建立核心,在核心內(nèi)有兩個(gè)配置文件需要修改,data-config.xml solrconfig.xml
需要加入ik詞庫(kù),需要配置scheme文件來(lái)修改詞庫(kù)內(nèi)容
接下來(lái):在剛才提到的schema.xml中配置:加上這一段
新建的這兩個(gè)域支持IK分析器
啟動(dòng)前得提高solr服務(wù)器啟動(dòng)對(duì)應(yīng)的jvm大小,防止因?yàn)閿?shù)據(jù)量過(guò)大導(dǎo)致內(nèi)存溢出問(wèn)題
./solr -m 2gcmd輸入 為虛擬機(jī)分配2g大小的內(nèi)存
導(dǎo)入數(shù)據(jù)的時(shí)候盡量將少量字段導(dǎo)入減少solr讀取建立索引的消耗,導(dǎo)入id,title字段通過(guò)圖片轉(zhuǎn)義的文字對(duì)應(yīng)title,來(lái)找到對(duì)應(yīng)id并返回
java調(diào)用只需要先建立對(duì)solr服務(wù)器對(duì)應(yīng)核心的連接然后定義關(guān)鍵詞再獲得結(jié)果響應(yīng)
5.實(shí)現(xiàn)
把爬取的題庫(kù)資源上傳id和題目?jī)蓚€(gè)字段到solr服務(wù)器中,
用戶把圖片資源上傳后,通過(guò)百度ocr接口把圖片轉(zhuǎn)換為文字,
對(duì)應(yīng)文字上傳到solr提供的接口返回相似度最高的前五個(gè)題目的id和題目,
返回用戶這五個(gè)id和題目,用戶自己點(diǎn)擊選擇最想看的題目,在上傳id到服務(wù)器然后服務(wù)器查詢數(shù)據(jù)庫(kù)返回對(duì)應(yīng)的h5和答案給用戶
總結(jié)
以上是生活随笔為你收集整理的如何实现一个拍照搜题功能的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux学习之一
- 下一篇: 【maven3学习之三】maven构建一