日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

如何实现一个拍照搜题功能

發(fā)布時(shí)間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何实现一个拍照搜题功能 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

如何實(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ù)

WebClient webClient = new WebClient(BrowserVersion.FIREFOX_52);//選擇模擬瀏覽器型號(hào)//屏蔽日志信息LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log","org.apache.commons.logging.impl.NoOpLog");Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);//支持JavaScriptwebClient.getOptions().setJavaScriptEnabled(true);webClient.getOptions().setCssEnabled(false);webClient.getOptions().setActiveXNative(false);webClient.getOptions().setCssEnabled(false);webClient.getOptions().setThrowExceptionOnScriptError(false);webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);webClient.getOptions().setTimeout(10000);webClient.waitForBackgroundJavaScript(10000);url="https://passport.zujuan.com/login";URL link=new URL(url);WebRequest webRequest=new WebRequest(link);HtmlPage rootPage = webClient.getPage(webRequest);//獲得要抓取的頁(yè)面

需要登陸:

有些網(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("&lt;","<"); str= str.replace("&quot;","\""); str= str.replace("&gt;",">"); str= str.replace("&amp;","&"); str= str.replace("&apos;","'"); str= str.replace("&quot","");

3.OCR技術(shù)(文字識(shí)別)

名稱api來(lái)源來(lái)源網(wǎng)址是否開(kāi)源限制次數(shù)技術(shù)問(wèn)題
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中配置:加上這一段

<fieldType name="text_ik" class="solr.TextField"><analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/> </fieldType><field name="title_ik" type="text_ik" indexed="true" stored="true"/> <field name="content_ik" type="text_ik" indexed="true" stored="false" multiValued="true"/>

新建的這兩個(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 2g

cmd輸入 為虛擬機(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)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。