一文告诉你,如何使用Python构建一个“谷歌搜索”系统 | 内附代码
来源 | hackernoon
编译 | 武明利
责编 | Carol
出品 | AI科技大本营(ID:rgznai100)
在这篇文章中,我将向您展示如何使用Python构建自己的答案查找系统。基本上,这种自动化可以从图片中找到多项选择题的答案。
有一件事我们要清楚,在考试期间不可能在互联网上搜索问题,但是当考官转过身去的时候,我可以很快地拍一张照片。这是算法的第一部分。我得想办法把这个问题从图中提取出来。
似乎有很多服务可以提供文本提取工具,但是我需要某种API来解决此问题。最后,Google的VisionAPI正是我正在寻找的工具。很棒的事情是,每月前1000个API调用是免费的,这足以让我测试和使用该API。
Vision AI
首先,创建Google云帐户,然后在服务中搜索Vision AI。使用VisionAI,您可以执行诸如为图像分配标签来组织图像,获取推荐的裁切顶点,检测著名的风景或地方,提取文本等工作。
检查文档以启用和设置API。配置后,您必须创建JSON文件,包含您下载到计算机的密钥。
运行以下命令安装客户端库:
pip install google-cloud-vision
然后通过设置环境变量GOOGLE_APPLICATION_CREDENTIALS,为应用程序代码提供身份验证凭据。
import os, io
from google.cloud import vision
from google.cloud.vision import types# JSON file that contains your key
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'your_private_key.json'# Instantiates a client
client = vision.ImageAnnotatorClient()FILE_NAME = 'your_image_file.jpg'# Loads the image into memory
with io.open(os.path.join(FILE_NAME), 'rb') as image_file:content = image_file.read()image = vision.types.Image(content=content)# Performs text detection on the image file
response = client.text_detection(image=image)
print(response)# Extract description
texts = response.text_annotations[0]
print(texts.description)
在运行代码时,您将看到JSON格式的响应,其中包括检测到的文本的规范。但我们只需要纯描述,所以我从响应中提取了这部分。
在Google上搜索问题
下一步是在Google上搜索问题部分来获得一些信息。我使用正则表达式(regex)库从描述(响应)中提取问题部分。然后我们必须将提取出的问题部分进行模糊化,以便能够对其进行搜索。
import re
import urllib# If ending with question mark
if '?' in texts.description:question = re.search('([^?]+)', texts.description).group(1)# If ending with colon
elif ':' in texts.description:question = re.search('([^:]+)', texts.description).group(1)
# If ending with newline
elif '\n' in texts.description:question = re.search('([^\n]+)', texts.description).group(1)# Slugify the match
slugify_keyword = urllib.parse.quote_plus(question)
print(slugify_keyword)
抓取的信息
我们将使用 BeautifulSoup 抓取前3个结果,以获得关于问题的一些信息,因为答案可能位于其中之一。
另外,如果您想从Google的搜索列表中抓取特定的数据,不要使用inspect元素来查找元素的属性,而是打印整个页面来查看属性,因为它与实际的属性有所不同。
我们需要对搜索结果中的前3个链接进行抓取,但是这些链接确实被弄乱了,因此获取用于抓取的干净链接很重要。
/url?q=https://en.wikipedia.org/wiki/IAU_definition_of_planet&sa=U&ved=2ahUKEwiSmtrEsaTnAhXtwsQBHduCCO4QFjAAegQIBBAB&usg=AOvVaw0HzMKrBxdHZj5u1Yq1t0en
正如您所看到的,实际的链接位于q=和&sa之间。通过使用正则表达式Regex,我们可以获得这个特定的字段或有效的URL。
result_urls = []def crawl_result_urls():req = Request('https://google.com/search?q=' + slugify_keyword, headers={'User-Agent': 'Mozilla/5.0'}) html = urlopen(req).read()bs = BeautifulSoup(html, 'html.parser')results = bs.find_all('div', class_='ZINbbc')try:for result in results:link = result.find('a')['href']# Checking if it is url (in case)if 'url' in link:result_urls.append(re.search('q=(.*)&sa', link).group(1))except (AttributeError, IndexError) as e:pass
在我们抓取这些URLs的内容之前,让我向您展示使用Python的问答系统。
问答系统
这是算法的主要部分。从前3个结果中抓取信息后,程序应该通过迭代文档来检测答案。首先,我认为最好使用相似度算法来检测与问题最相似的文档,但是我不知道如何实现它。
经过几个小时的研究,我在Medium上找到了一篇文章,用Python解释了问答系统。它有易于使用的python软件包能够对您自己的私有数据实现一个QA系统。
让我们先安装这个包:
pip install cdqa
我正在使用下面的示例代码块中包含的下载功能来手动下载经过预训练的模型和数据:
import pandas as pd
from ast import literal_evalfrom cdqa.utils.filters import filter_paragraphs
from cdqa.utils.download import download_model, download_bnpp_data
from cdqa.pipeline.cdqa_sklearn import QAPipeline# Download data and models
download_bnpp_data(dir='./data/bnpp_newsroom_v1.1/')
download_model(model='bert-squad_1.1', dir='./models')# Loading data and filtering / preprocessing the documents
df = pd.read_csv('data/bnpp_newsroom_v1.1/bnpp_newsroom-v1.1.csv', converters={'paragraphs': literal_eval})
df = filter_paragraphs(df)# Loading QAPipeline with CPU version of BERT Reader pretrained on SQuAD 1.1
cdqa_pipeline = QAPipeline(reader='models/bert_qa.joblib')# Fitting the retriever to the list of documents in the dataframe
cdqa_pipeline.fit_retriever(df)# Sending a question to the pipeline and getting prediction
query = 'Since when does the Excellence Program of BNP Paribas exist?'
prediction = cdqa_pipeline.predict(query)print('query: {}\n'.format(query))
print('answer: {}\n'.format(prediction[0]))
print('title: {}\n'.format(prediction[1]))
print('paragraph: {}\n'.format(prediction[2]))
它的输出应该是这样的:
它打印出确切的答案和包含答案的段落。
基本上,当从图片中提取问题并将其发送到系统时,检索器将从已抓取数据中选择最有可能包含答案的文档列表。如前所述,它计算问题与抓取数据中每个文档之间的余弦相似度。
在选择了最可能的文档后,系统将每个文档分成几个段落,并将问题一起发送给读者,这基本上是一个预先训练好的深度学习模型。所使用的模型是著名的NLP模型BERT的Pytorch 版本。
然后,读者输出在每个段落中找到的最可能的答案。在阅读者之后,系统中的最后一层通过使用内部评分函数对答案进行比较,并根据分数输出最有可能的答案,这将得到我们问题的答案。
下面是系统机制的模式。
你必须在特定的结构中设置数据帧(CSV),以便将其发送到 cdQA 管道。
但是实际上我使用PDF转换器从PDF文件目录创建了一个输入数据框。因此,我要在pdf文件中保存每个结果的所有抓取数据。我们希望总共有3个pdf文件(也可以是1个或2个)。另外,我们需要命名这些pdf文件,这就是为什么我抓取每个页面的标题的原因。
def get_result_details(url):try:req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})html = urlopen(req).read()bs = BeautifulSoup(html, 'html.parser')try:# Crawl any heading in result to name pdf filetitle = bs.find(re.compile('^h[1-6]$')).get_text().strip().replace('?', '').lower()# Naming the pdf filefilename = "/home/coderasha/autoans/pdfs/" + title + ".pdf"if not os.path.exists(os.path.dirname(filename)):try:os.makedirs(os.path.dirname(filename))except OSError as exc: # Guard against race conditionif exc.errno != errno.EEXIST:raisewith open(filename, 'w') as f:# Crawl first 5 paragraphsfor line in bs.find_all('p')[:5]:f.write(line.text + '\n')except AttributeError:passexcept urllib.error.HTTPError:passdef find_answer():df = pdf_converter(directory_path='/home/coderasha/autoans/pdfs')cdqa_pipeline = QAPipeline(reader='models/bert_qa.joblib')cdqa_pipeline.fit_retriever(df)query = question + '?'prediction = cdqa_pipeline.predict(query)print('query: {}\n'.format(query))print('answer: {}\n'.format(prediction[0]))print('title: {}\n'.format(prediction[1]))print('paragraph: {}\n'.format(prediction[2]))return prediction[0]
我总结一下算法:它将从图片中提取问题,在Google上搜索它,抓取前3个结果,从抓取的数据中创建3个pdf文件,最后使用问答系统找到答案。
如果你想看看它是如何工作的,请检查我做的一个可以从图片中解决考试问题的机器人。
以下是完整的代码:
import os, io
import errno
import urllib
import urllib.request
import hashlib
import re
import requests
from time import sleep
from google.cloud import vision
from google.cloud.vision import types
from urllib.request import urlopen, Request
from bs4 import BeautifulSoup
import pandas as pd
from ast import literal_eval
from cdqa.utils.filters import filter_paragraphs
from cdqa.utils.download import download_model, download_bnpp_data
from cdqa.pipeline.cdqa_sklearn import QAPipeline
from cdqa.utils.converters import pdf_converterresult_urls = []os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'your_private_key.json'client = vision.ImageAnnotatorClient()FILE_NAME = 'your_image_file.jpg'with io.open(os.path.join(FILE_NAME), 'rb') as image_file:content = image_file.read()image = vision.types.Image(content=content)response = client.text_detection(image=image)texts = response.text_annotations[0]
# print(texts.description)if '?' in texts.description:question = re.search('([^?]+)', texts.description).group(1)elif ':' in texts.description:question = re.search('([^:]+)', texts.description).group(1)elif '\n' in texts.description:question = re.search('([^\n]+)', texts.description).group(1)slugify_keyword = urllib.parse.quote_plus(question)
# print(slugify_keyword)def crawl_result_urls():req = Request('https://google.com/search?q=' + slugify_keyword, headers={'User-Agent': 'Mozilla/5.0'}) html = urlopen(req).read()bs = BeautifulSoup(html, 'html.parser')results = bs.find_all('div', class_='ZINbbc')try:for result in results:link = result.find('a')['href']print(link)if 'url' in link:result_urls.append(re.search('q=(.*)&sa', link).group(1))except (AttributeError, IndexError) as e:passdef get_result_details(url):try:req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})html = urlopen(req).read()bs = BeautifulSoup(html, 'html.parser')try:title = bs.find(re.compile('^h[1-6]$')).get_text().strip().replace('?', '').lower()# Set your path to pdf directoryfilename = "/path/to/pdf_folder/" + title + ".pdf"if not os.path.exists(os.path.dirname(filename)):try:os.makedirs(os.path.dirname(filename))except OSError as exc:if exc.errno != errno.EEXIST:raisewith open(filename, 'w') as f:for line in bs.find_all('p')[:5]:f.write(line.text + '\n')except AttributeError:passexcept urllib.error.HTTPError:passdef find_answer():# Set your path to pdf directorydf = pdf_converter(directory_path='/path/to/pdf_folder/')cdqa_pipeline = QAPipeline(reader='models/bert_qa.joblib')cdqa_pipeline.fit_retriever(df)query = question + '?'prediction = cdqa_pipeline.predict(query)# print('query: {}\n'.format(query))# print('answer: {}\n'.format(prediction[0]))# print('title: {}\n'.format(prediction[1]))# print('paragraph: {}\n'.format(prediction[2]))return prediction[0]crawl_result_urls()for url in result_urls[:3]:get_result_details(url)sleep(5)answer = find_answer()
print('Answer: ' + answer)
有时它可能会混淆,但我认为总体来说是可以的。至少我可以用60%的正确答案通过考试。
欢迎开发者们在评论中告诉我你的看法!实际上,最好是一次遍历所有问题,但我没有足够的时间来做这件事,所以只好下次继续再做。
(*本文由AI科技大本营编译,转载请联系微信1092722531)
【end】
◆
精彩推荐
◆
推荐阅读
福利直达!CSDN技术公开课评选进行中
直播进行中 | 技术驰援抗疫一线, Python 线上峰会全天精彩呈现
分布式数据集训营,从入门到精通,从理论到实践,你不可错过的精品课程!
区块链的阴暗面
QQ 群文件紧急扩容;钟南山团队与阿里云联手推进新冠疫苗研发;PhpStorm 2019.3.3 发布
愿得一心人:硅谷亿万富豪们的婚姻怎样?有人白首相守七十年
你点的每个“在看”,我都认真当成了AI
相关文章:

WatchStor观察:思科携EMC等合作伙伴 圈地数据中心市场
早在今年3月,思科在加利福尼亚州圣何塞市展会中展示了“统一计算系统”(Unified Computing System)之后,我们就明白,数据中心市场将会发生巨大改变,传统的以IBM、惠普、戴尔和Sun为主导的服务器电脑市场,将受到以思科为…
使用BabeLua3.x在cocos2d-x中编辑和调试Lua
BabeLua是一款基于VS2012/2013的Lua集成开发环境,具有Lua语法高亮,语法检查,自动补全,快速搜索,注入宿主程序内对Lua脚本进行调试,设置断点观察变量值,查看堆栈信息等功能。 如何安装 请参考《系…

ASA与PIX的区别
很多年来,Cisco PIX一直都是Cisco确定的防火墙。但是在2005年5月,Cisco推出了一个新的产品——适应性安全产品(ASA,Adaptive Security Appliance)。不过,PIX还依旧可用。我已听到很多人在多次询问这两个产品…
C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(ubuntu g++)——遍历和查找
相关环境和说明在《C拾趣——STL容器的插入、删除、遍历和查找操作性能对比(ubuntu g)——插入》已给出。本文将分析各个容器中遍历和查找的性能。(转载请指明出于breaksoftware的csdn博客) 遍历 从前往后 元素个数>15000 t…
买不到口罩怎么办?Python爬虫帮你时刻盯着自动下单!| 原力计划
作者 | 菜园子哇编辑 | 唐小引来源 | CSDN 博客马上上班了,回来的路上,上班地铁上都是非常急需口罩的。目前也非常难买到正品、发货快的口罩,许多药店都售完了。并且,淘宝上一些新店口罩库存写着非常多,但不发货&#…

GlusterFS下如何修复裂脑文件?(续一)
关于网上一些修复GlusterFS裂脑文件的说明1、Fixing a GlusterFS split-brainhttps://inuits.eu/blog/fixing-glusterfs-split-brain在该文章中,删除无效副本时提供的方法如下:srv02$ sudo find /export/brick1/sdb1/ -samefile /export/brick1/sdb1/tes…

MySQL数据库环境使用全过程
在使用MySQL之前,需要建立数据库的环境来创建数据表,首先我们需要安装该数据库环境,即MySQL。1、下载MySQLMySQL的官方网站是http://www.mysql.org/,如图2-9所示:图2-9 MySQL官方网站当前稳定版本为5.1,我…
C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows VirtualStudio)——插入
操作系统是Windows10 64bit,编译器是 Microsoft Virtual Studio Community 10。编译产出是64位测试程序。(转载请指明出于breaksoftware的csdn博客) 因为加入测量,就会导致误差。我已经尽量将环境影响降低,但是还是难免…
“夸夸机器人”App来了:变身百万粉丝大V,48万人给你的帖子点赞
来源 | mashable译者 | Kolen出品 | AI科技大本营(ID:rgznai100)我在Botnet上的第一条帖子获得了48万个赞。一款全新的社交媒体风格的应用为用户提供了生活在一个奇特网络虚拟世界的机会。在这个世界里,你将拥有数以百万计的粉丝,…

leetcode Reverse Linked List
Reverse a singly linked list 对于这种可以修改值的,把值逆序就可以了。。。。用vector存,然后逆序读。 都忘了指针怎么赋值初始化了。*p&head; 1 /**2 * Definition for singly-linked list.3 * struct ListNode {4 * int val;5 * Lis…
抗击新冠肺炎,如何进行实时动态时序图谱建模与分析?
作者 | 闭雨哲来源 | ThutmoseAI背景介绍新冠肺炎是一种具有最长达24天潜伏期的新型突发性传染疾病,这种特性给疫情防控带来了巨大的挑战,随着感染规模的不断扩增,简单的人为治理已不太奏效,使用“大数据”技术手段来辅助人为治理…
C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows VirtualStudio)——删除
相关环境和说明在《C拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows VirtualStudio)——插入》已给出。本文将分析从头部、中间和尾部对各个容器进行删除的性能。(转载请指明出于breaksoftware的csdn博客) 删除 …

关于服务器启动慢的问题
今天去了家医院的机房,走进去一看,TMD的医院就是有钱,全是光纤和千兆网络环境,全全是思科的三层交换机和路由器,HP的服务器。我们需要安装点东西,登录一台服务器,我一看配置,呵呵&am…

python依赖包exe文件安装问题
2019独角兽企业重金招聘Python工程师标准>>> 在使用python的exe程序安装依赖包的时候,经常会出现类似于下面的错误: python version 2.7 required,which was not found in the registry 可以使用如下代码解决该问题: # # script to register …
C++拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows VirtualStudio)——遍历和删除
相关环境和说明在《C拾趣——STL容器的插入、删除、遍历和查找操作性能对比(Windows VirtualStudio)——插入》已给出。本文将分析各个容器中遍历和查找的性能。(转载请指明出于breaksoftware的csdn博客) 遍历 从前往后 travers…
技术战“疫”,贾扬清、李飞飞要给程序员直播讲AI技术!
「时势造英雄,英雄亦造时势。」在这场波及全球且看不见硝烟的疫情下,无数英雄日夜奋战,无论是身处一线的医护工作者、政府职能部门、志愿者,还是坚守在家的人民群众,都在尽自己所能,在行动!与此…

关于端口映射的一个命令
今天安装一个远程会诊的系统,由于是在不同和的地方,需要在路由器上作下映射,由于是要远程连接对方的服务器,所以要在对方的路由器上设置下Interface fastethernet0/0 Ip address 192.168.1.1 255.255.255.0 Duplex auto Speed aut…

elasticsearch简介
Elasticsearch是 面向文档型数据库,这意味着它存储的是整个对象或者 文档,它不但会存储它们,还会为他们建立索引,这样你就可以搜索他们了。你可以在 Elasticsearch 中索引、搜索、排序和过滤这些文档。不需要成行成列的数据。所以…

C++拾取——使用stl标准库生成等差、等比数列的方法
代码是思想的表达。阅读代码是一个猜测、求证的过程。这个过程非常费脑,所以人们都不喜欢啰啰嗦嗦的表达方式。于是在相同认知水平下,简洁高效的表达是喜闻乐见的。本文将抛砖引玉,通过一些案例讲解如何去简化代码。(转载请指明出…

利用NetBIOS名称与其他计算机通信
当某台计算机与网络中的其他计算机通信时,它是如何依据对方的计算机名称来得知其IP地址呢?名称解析的方法有以下几种: 检查NetBIOS名称缓存(NetBIOS name cache)广播直接向WINS服务器查询何谓NetBIOS名称:如…
编程语言性能实测,Go比Python更胜一筹?
作者 | Pawel Dziubałka, Sebastian Karasiewicz译者 | 泓技出品 | AI科技大本营(ID:rgznai100)互联网上有非常多的精彩代码,它们成了构建各种基础设施的基础。你正在阅读的这个平台同样也在致力于创建出色的代码。尽管普通用户一般不会注意…

mysql备份策略的制定
需要考虑的因素: 1. 数据库是不是都是innoDB引擎表 -》决定备份方式,热备或冷备 2. 数据量大小 -》逻辑备(量小)或物理备,全量或增量 3. 数据库本地空间是否充足 -》备份到本地或远程 4. 需要多快恢复 -》备份频率 小时…

C++拾取——使用stl标准库实现排序算法及评测
今天看了一篇文章,讲各种语言的优势和劣势。其中一个观点:haskell非常适合写算法,因为使用者不用去关心具体的计算机实现,而只要关注于操作语义。这让它在专心研究算法的人中非常受欢迎。所以很多时候,语言的争论没有太…
几行代码构建全功能的对象检测模型,他是如何做到的?
作者 | Alan Bi 译者 | 武明利,责编 | Carol 出品 | AI科技大本营(ID:rgznai100) 如今,机器学习和计算机视觉已成为一种热潮。我们都看过关于自动驾驶汽车和面部识别的新闻,可能会想象建立自己的计算机视觉模型有多酷。…

SQL操作全集
SQL操作全集 下列语句部分是Mssql语句,不可以在access中使用。 SQL分类: DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) DML—数据操纵语言(SELECT,DELETE,UPDATE,INSERT) DCL—数据…

css3媒体查询实现网站响应式布局
响应式建筑设计、响应式家具设计、响应式办公设计,这些词可能是已有的专业名词,也可能是我自己想出来的一些名词。因为在生活中,我们常常会见到很多让人惊叹的设计,为什么同一套东西经过不同的方式变化之后会给人不同的使用感受和…
流行于机器学习竞赛的Boosting,这篇文章讲的非常全了
作者 | AISHWARYA SINGH译者 | 武明利,责编 | Carol出品 | AI科技大本营(ID:rgznai100)你能说出至少两种机器学习中的 Boosting 吗?Boosting 已经存在了很多年,然而直到最近它们才成为机器学习社区的主流。那么&#x…
并行计算——OpenMP加速矩阵相乘
OpenMP是一套基于共享内存方式的多线程并发编程库。第一次接触它大概在半年前,也就是研究cuda编程的那段时间。OpenMP产生的线程运行于CPU上,这和cuda不同。由于GPU的cuda核心非常多,可以进行大量的并行计算,所以我们更多的谈论的…

JavaScript继承详解(四)
文章截图 - 更好的排版 在本章中,我们将分析Douglas Crockford关于JavaScript继承的一个实现 - Classical Inheritance in JavaScript。 Crockford是JavaScript开发社区最知名的权威,是JSON、JSLint、JSMin和ADSafe之父,是《JavaScript: The …

C语言:在屏幕上输出信息
#include<stdio.h>int main(){printf ("This is a C program.\n");printf("welcome to bit\n");return 0;}结果:This is a C program.welcome to bitPress any key to continue转载于:https://blog.51cto.com/yaoyaolx/1715542