搜索引擎优化pdf( 如何使用Python构建自己的答案查找系统?|AI科技大本营)
优采云 发布时间: 2021-12-25 19:15搜索引擎优化pdf(
如何使用Python构建自己的答案查找系统?|AI科技大本营)
来源 | 黑客中午
编译| 吴明丽,主编| 颂歌
生产 | AI科技大本营(ID:rgznai100)
在本文中,我将向您展示如何使用 Python 构建自己的答案查找系统。基本上,这种自动化可以从图片中找到多项选择题的答案。
有一点我们要明确的是,考试期间无法在网上搜索题,但是当考官转身时,我可以快速拍照。这是算法的第一部分。我必须想办法从图片中提取这个问题。
似乎有很多服务可以提供文本提取工具,但是我需要某种API来解决这个问题。最后,Google 的 VisionAPI 正是我正在寻找的工具。很棒的是,每月前 1000 次 API 调用是免费的,这足以让我测试和使用 API。
视觉人工智能
首先创建一个谷歌云账号,然后在服务中搜索Vision AI。使用 VisionAI,您可以执行诸如为图像分配标签以组织图像、获取推荐的裁剪顶点、检测著名风景或地点以及提取文本等任务。
查看文档以启用和设置 API。配置后,您必须创建一个 JSON 文件,其中收录
您下载到计算机的密钥。
运行以下命令安装客户端库:
pip install google-cloud-vision
然后设置环境变量 GOOGLE_APPLICATION_CREDENTIALS 为应用程序代码提供身份验证凭据。
import os, iofrom google.cloud import visionfrom google.cloud.vision import types
# JSON file that contains your keyos.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'your_private_key.json'
# Instantiates a clientclient = vision.ImageAnnotatorClient
FILE_NAME = 'your_image_file.jpg'
# Loads the image into memorywith 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 fileresponse = client.text_detection(image=image)print(response)
# Extract descriptiontexts = response.text_annotations[0]print(texts.description)
运行代码时,您将看到 JSON 格式的响应,其中包括检测到的文本的规范。但是我们只需要一个纯粹的描述,所以我从响应中提取了这部分。
在 Google 上搜索问题
下一步是在 Google 上搜索问题部分以获取一些信息。我使用正则表达式(regex)库从描述(响应)中提取问题部分。然后我们必须混淆提取的问题部分,以便可以搜索。
import reimport urllib
# If ending with question markif '?' in texts.description: question = re.search('([^?]+)', texts.description).group(1)
# If ending with colonelif ':' in texts.description: question = re.search('([^:]+)', texts.description).group(1)# If ending with newlineelif '\n' in texts.description: question = re.search('([^\n]+)', texts.description).group(1)
# Slugify the matchslugify_keyword = urllib.parse.quote_plus(question)print(slugify_keyword)
爬取的信息
我们将使用 BeautifulSoup 抓取前 3 个结果以获取有关该问题的一些信息,因为答案可能在其中之一。
另外,如果你想从谷歌的搜索列表中抓取特定的数据,不要使用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
在我们抓取这些 URL 的内容之前,让我向您展示使用 Python 的问答系统。
问答系统
这是算法的主要部分。从前 3 个结果中获取信息后,程序应遍历文档以检测答案。首先,我认为最好使用相似度算法来检测与问题最相似的文档,但我不知道如何实现。
经过几个小时的研究,我在 Medium 上找到了一篇解释 Python 问答系统的文章。它有一个易于使用的python软件包,可以为您自己的私人数据实现一个QA系统。
让我们先安装这个包:
pip install cdqa
我正在使用下面示例代码块中收录
的下载功能来手动下载预训练的模型和数据:
它的输出应该是这样的:
它打印出确切的答案和收录
答案的段落。
基本上,当问题从图片中提取并发送到系统时,检索器将从爬取的数据中选择最有可能收录
答案的文档列表。如前所述,它计算问题与爬取数据中每个文档之间的余弦相似度。
选择最有可能的文档后,系统将每个文档分成几段,将问题一起发送给读者。这基本上是一个预训练的深度学习模型。使用的模型是著名的 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 file title = bs.find(re.compile('^h[1-6])).get_text.strip.replace('?', '').lower # Naming the pdf file filename = "/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 condition if exc.errno != errno.EEXIST: raise with open(filename, 'w') as f: # Crawl first 5 paragraphs for line in bs.find_all('p')[:5]: f.write(line.text + '\n') except AttributeError: pass except urllib.error.HTTPError: pass
def 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]
让我总结一下算法:它会从图片中提取问题,在谷歌上搜索它,抓取前3个结果,从抓取的数据中创建3个pdf文件,最后使用问答系统找到答案。
如果你想看看它是如何工作的,请检查我制作的一个机器人,它可以从图片中解决考试问题。
以下是完整代码:
import os, ioimport errnoimport urllibimport urllib.requestimport hashlibimport reimport requestsfrom time import sleepfrom google.cloud import visionfrom google.cloud.vision import typesfrom urllib.request import urlopen, Requestfrom bs4 import BeautifulSoupimport pandas as pdfrom ast import literal_evalfrom cdqa.utils.filters import filter_paragraphsfrom cdqa.utils.download import download_model, download_bnpp_datafrom cdqa.pipeline.cdqa_sklearn import QAPipelinefrom cdqa.utils.converters import pdf_converter
result_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: pass
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: title = bs.find(re.compile('^h[1-6])).get_text.strip.replace('?', '').lower # Set your path to pdf directory filename = "/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: raise with open(filename, 'w') as f: for line in bs.find_all('p')[:5]: f.write(line.text + '\n') except AttributeError: pass except urllib.error.HTTPError: pass
def find_answer: # Set your path to pdf directory df = 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_answerprint('Answer: ' + answer)
有时它可能会令人困惑,但我认为总体上是可以的。至少我能以60%的正确答案通过考试。
欢迎开发者在评论中告诉我你的看法!其实最好一次性把所有题都做一遍,但是我没有足够的时间做这个,所以我下次还要继续做。