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

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

主要分4步数据抓取,数据处理 ,图文转换,搜索引擎

1.数据抓取

主要抓取网页网站题库数据

可抓取题库网,无忧网,新东方题库

技术实现:

利用jsoup抓取相应网站的数据,利用htmlunit模拟客户端抓取数据
通过下面链接可下载Jsoup的jar包
http://central.maven.org/maven2/org/jsoup/jsoup/1.12.1/jsoup-1.12.1.jar
通过下面链接可下载htmlunit的jar包
http://central.maven.org/maven2/net/sourceforge/htmlunit/htmlunit/2.35.0/htmlunit-2.35.0.jar

遇到问题:

js异步加载 :

如组卷网会通过js异步加载导致jsoup第一步抓取的只是一个网站空壳,抓不到想要的数据
可以通过htmlunit技术去模拟浏览器,把js异步加载过程也模拟完成后能获得正确数据

        WebClient webClient = new WebClient(BrowserVersion.FIREFOX_52);//选择模拟浏览器型号
       //屏蔽日志信息
        LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log",
                "org.apache.commons.logging.impl.NoOpLog");
        Logger.getLogger("com.gargoylesoftware").setLevel(Level.OFF);
       //支持JavaScript
        webClient.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);//获得要抓取的页面
需要登陆:

有些网站一些页面需要登陆操作

可以通过设置hander cookie来跳过登陆,但是cookie部分数据会动态发生改变需要时时注意,

    public static Document setHeader(String url) throws IOException {//设置header返回doc
    Map<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");//题库网的PHPSESSID会动态改变的得实时更新
    conn.header("Referer","http://www.tiku.cn/");//设置header的参数
    conn.execute();
    return conn.get();
}

或者通过htmlunit取模拟登陆

        CookieManager cm=webClient.getCookieManager();//得到当前分配得到的cookie
        Set<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);//获取当前页面的表单
        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();//获得登陆后的页面
访问频率限制:

某些网站对于一个ip有访问次数限制,所以需要正确线程池大小,而且尽量减少一次抓取所需要的访问次数

而且访问次数过多会导致网站连接延迟增加所以要提高连接超时限制

锁账户和ip机制

有些网站会有个动态黑名单,封锁异常多次访问的ip和账户

2.抓取数据的处理

遇到问题

抓取的数据可能是xml代码,json代码,其中可能带有html特殊字符,所以需要对其去转义,图片地址有可能是不带域名的所以处理的时候得加上域名

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技术(文字识别)

名称api来源来源网址是否开源限制次数技术问题
iocr百度http://ai.baidu.com/tech/ocr/iocr每个账户50000次/天
tesseract谷歌作为开源项目发布在Google Project上无限制官方字库准确率过低,需要自己训练字库

百度ocr调用实现

将图片文件进行转码获得一个处理后的字符串

byte[] imgData = FileUtil.readFileByBytes(filePath);//需要自定义两个工具类
String imgStr = Base64Util.encode(imgData);
String params = URLEncoder.encode("image", "UTF-8") + "=" + URLEncoder.encode(imgStr, "UTF-8");//Base64Util,FileUtil这两个是自定义的工具类将图片文件转码

利用百度对每个账户分配的 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为固定参数
        + "grant_type=client_credentials"
        // 2. 官网获取的 API Key
        + "&client_id=" + ak
        // 3. 官网获取的 Secret Key
        + "&client_secret=" + sk;
   try {
    URL realUrl = new URL(getAccessTokenUrl);
    // 打开和URL之间的连接
    HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
    connection.setRequestMethod("GET");
    connection.connect();
    // 获取所有响应头字段
    Map<String, List<String>> map = connection.getHeaderFields();
    // 遍历所有的响应头字段
    for (String key : map.keySet()) {
        System.err.println(key + "--->" + map.get(key));
    }
    // 定义 BufferedReader输入流来读取URL的响应
    BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    String result = "";
    String line;
    while ((line = in.readLine()) != null) {
        result += line;
    }
    /**
     * 返回结果示例
     */
    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;

}

通过访问这个url可以得到通行证码

再通过http访问百度给的接口,需要在url地址带上通行证信息和图像处理后的字符串

String result = HttpUtil.post(otherHost, accessToken, params);//HttpUtil是一个自定义的连接类

最后获得百度传回的json文件,获得的文件格式为识别的每一行的字,所以好得处理下把每行字取出来合并

遇到问题

百度ocr api有账户次数限制 每个账户5w次/日

开源免费的tesseract的精度太低,需要训练词库,训练词库的方法可以通过下面这个博客学习
https://www.cnblogs.com/wzben/p/5930538.html

4.搜索引擎的搭建

技术实现

利用solr框架搭建一个针对题目title的搜索引擎
通过下面链接下载solr相关文件
http://mirror.bit.edu.cn/apache/lucene/solr/8.1.0/solr-8.1.0-src.tgz

配置要点:可查看微博https://www.cnblogs.com/xuyiqing/p/8707966.html

通过官网下载的文件,可直接通过终端启动solr,有几个重要的jar包需要添加,极其重要缺一不可

建立核心,在核心内有两个配置文件需要修改,data-config.xml solrconfig.xml

需要加入ik词库,需要配置scheme文件来修改词库内容
接下来:在刚才提到的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"/>

新建的这两个域支持IK分析器

启动前得提高solr服务器启动对应的jvm大小,防止因为数据量过大导致内存溢出问题

./solr -m 2g

cmd输入 为虚拟机分配2g大小的内存

导入数据的时候尽量将少量字段导入减少solr读取建立索引的消耗,导入id,title字段通过图片转义的文字对应title,来找到对应id并返回

java调用只需要先建立对solr服务器对应核心的连接然后定义关键词再获得结果响应

5.实现

把爬取的题库资源上传id和题目两个字段到solr服务器中,

用户把图片资源上传后,通过百度ocr接口把图片转换为文字,

对应文字上传到solr提供的接口返回相似度最高的前五个题目的id和题目,

返回用户这五个id和题目,用户自己点击选择最想看的题目,在上传id到服务器然后服务器查询数据库返回对应的h5和答案给用户

  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android功能是指通过在Android设备上使用特定的应用程序或索引擎,帮助用户解决问或寻找答案的一种功能。这个功能可以帮助用户在手机上快速目并找到相关的答案。Android功能具有以下几个特点。 首先,Android功能提供了广泛的库和知识库,涵盖了各个学科的问和答案。用户可以通过输入关键词或目的描述,系统会自动索相关的目和答案,提供给用户参考。这帮助用户快速找到所需的信息,提升了问解答的效率。 其次,Android功能还具有智能化的特点。系统会根据用户输入的问进行分析和理解,并给出相应的回答或建议。例如,对于数学问,系统可以计算和解析数学公式,并给出详细的步骤和答案。对于其他学科的问,系统也可以根据集的大量数据和知识库进行分析和回答。这种智能化的功能提升了用户的体验和满意度。 此外,Android功能还提供了多种索方式和功能扩展。用户可以通过拍照、语音输入、手写等方式来进行索,方便用户快速输入和索。同时,一些应用程序还提供了在线交流和讨论的功能,用户可以与其他用户交流问和答案,共同解决问。 总之,Android功能是一种方便快捷的功能,通过在Android设备上使用特定应用程序或索引擎,帮助用户解决问和寻找答案。它具有广泛的库和知识库、智能化的特点,以及多种索方式和功能扩展的优势。它为用户提供了一个便捷的问解决方案,提升了学习和工作效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值