python通过调用OPENAI API(ChatGPT)快速提取参考文献的标题信息

1.假定我们现在有一个参考文献列表,该如何从这些参考文献中快速提取参考文献的论文标题呢?

一开始,我想通过正则表达式的方法从参考文献中提取标题信息,例如:

1.对于中文参考文献,可以遍历每一个字符,从出现一个“.”开始,到出现下一个“."或者“[”符号结束,则中间的内容为该参考文献的标题,代码如下:

# 判断是否为中文参考文献或英文参考文献
                for char in f:
                    if '\u4e00' <= char <= '\u9fff':  # 中文字符范围
                        # 提取第一个 . 号后的部分
                        part = f.split('.', 1)[1]
                        # 提取标题,直到出现 [ 符号或者 . 符号
                        title = re.split(r'\[|\.', part)[0].strip()
                        break

 2.对于英文标题,一开始想的是遍历该条参考文献的字符,找到三个连续的英文单词,如果存在,则从找到的第一个单词开始向左直到遇到 `.` 或 `]`,向右直到遇到 `.` 或 `[` 结束。

  elif 'A' <= char <= 'Z' or 'a' <= char <= 'z':  # 英文字母范围
                        words_and_symbols = re.findall(r'\b\w+\b|\S', f)
                        print(words_and_symbols)
                        title = 'Null'
                        for i in range(len(words_and_symbols) - 2):
                            if (re.match(r'[a-z]', words_and_symbols[i]) and
                                    re.match(r'[a-z]', words_and_symbols[i + 1]) and
                                    re.match(r'[a-z]', words_and_symbols[i + 2])):
                                # 从找到的第一个单词开始向左直到遇到 `.` 或 `]`,向右直到遇到 `.` 或 `[`
                                start_idx = i
                                while start_idx > 0 and words_and_symbols[start_idx - 1] not in ['.', ']']:
                                    start_idx -= 1
                                end_idx = i + 3
                                while end_idx < len(words_and_symbols) and words_and_symbols[end_idx] not in ['.', '[']:
                                    end_idx += 1
                                title = ' '.join(words_and_symbols[start_idx:end_idx]).strip()
                                break

奈何英文参考文献的格式千奇百怪,例如有的作者名字可能是4个英文单词组成,而有的标题可能只有三个连续的英文单词组成,就会导致标题被错误提取,想了两天也没有想到比较完美的判断方法。

2.通过chatgpt获取参考文献的标题

将参考文献列表输入到chatgpt中,并让他提取文献标题,它能够快速、准确的帮我提取参考文献的信息。

于是,我通过调用api的方法,实现了参考文献的信息提取,参考代码如下:

import csv
import json
import re
import requests
import pandas as pd

API_KEY = "你的openai key"
API_URL = "你的api网址"



def extract_title_from_references(references_content, prompt):
    """
    使用 OpenAI API 提取参考文献中的信息。
    """
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {API_KEY}"
    }

    data = {
        "model": "gpt-4o-mini-2024-07-18",
        "messages": [
            {"role": "system", "content": "你是一个可以提取文献信息的助手。"},
            {"role": "user", "content": prompt + references_content}
        ],
        "max_tokens": 2000,
        "temperature": 0.5
    }

    response = requests.post(f"{API_URL}/chat/completions", headers=headers, data=json.dumps(data))
    response_json = response.json()
    info = response_json['choices'][0]['message']['content'].strip().split('\n')
    return info


def GetInfo(references_content):
    """
    提取参考文献中的标题、DOI 和 arXiv 信息,并判断文献类型。
    """
    # 将 references_content 拆分为每组 60 行
    lines = references_content.split('\n')
    grouped_content = ['\n'.join(lines[i:i+60]) for i in range(0, len(lines), 60)]

    all_titles = []
    for group in grouped_content:
        title_prompt = "请你帮我将每一个参考文献的标题提取出来,注意,输出结果只要参考文献的标题,如果找不到标题,输出NULL,每个输出结果占一行\n"
        titles = extract_title_from_references(group, title_prompt)
        all_titles.extend(titles)

    # 清除标题前后的空白字符串
    all_titles = [title.strip() for title in all_titles]

    doilist = []
    arxivlist = []

    for f in references_content.split('\n'):
        # DOI
        try:
            if 'doi.org' in f:
                DOI = f.split('org/')[1].strip()
            elif 'doi:' in f:
                DOI = f.split('doi:')[1].strip()
            else:
                DOI = 'Null'
        except:
            DOI = 'Null'
        doilist.append(DOI)

        # arXiv
        try:
            if 'arXiv' in f:
                arxiv_match = re.search(r'arXiv.*?(\d{4}\.\d{5})', f)
                if arxiv_match:
                    arxiv = arxiv_match.group(1).strip()
                else:
                    arxiv = 'Null'
            else:
                arxiv = 'Null'
        except:
            arxiv = 'Null'
        arxivlist.append(arxiv)

    # Debugging output
    print(f"Total titles: {len(all_titles)}")
    print(f"Total DOIs: {len(doilist)}")
    print(f"Total arXiv IDs: {len(arxivlist)}")

    # 判断文献类型
    typelist = []
    for title in all_titles:
        if re.search(r'[\u4e00-\u9fff]', title):
            typelist.append('中文文献')
        else:
            typelist.append('英文文献')

    refdata = {
        'Title': all_titles,
        'DOI': doilist,
        'arXiv': arxivlist,
        'Type': typelist
    }
    refdata = pd.DataFrame(refdata)
    return refdata

通过这种方式,能够高效的提取参考文献的信息,我还提取了参考文献的doi/arxiv号,当然这部分可以通过表达式去获取。

本代码采用pt-4o-mini-2024-07-18模型,api价格是openai开发的api中价格最低的,经过测试,提取300条参考文献消耗约0.06美元的额度,精度在98%以上,除了一些特别特殊的参考文献除外。例如:

或许通过增强prompt可以进一步提高识别率。

识别完每条参考文献之后,我们就可以通过爬取百度学术,获取每条参考文献的doi号,在scihub中进行批量下载。(开发中)

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值