跟沐神学读论文-论文阅读管理

摘要

近期有读论文的需求,就需要去了解一下论文到底要怎么读,同一个系列之间的论文如何作整理和归纳,之前也有了解过市面上有成熟的论文阅读工具,但是对于学生党来讲没什么性价比,在B站上看到沐神有讲解他的思路Typora作为工作中的md生产工具,我有一点浅显的认识希望和大家交流学习。Typora可以作为编辑工具,之前有被同事安利过,但是那个时候md格式还并不了解,今天重拾起,简单来讲我的做法就是Typora+gitee形成云端存储的一套方案,配套使用我自己的一些脚本,可以很好的实现论文阅读的功能。

一:Typora的安装

Typora 是一个所见即所得的 Markdown 跨平台写作工具,目前已经发布正式版,并且更改为付费模式,0.11.18_beta 是最后一个免费的测试版,有需要的可以选择下载。

Windows 用户

下载地址: [https://github.com/iuxt/src/releases/download/2.0/typora-0-11-18.exe](https://github.com/iuxt/src/releases/download/2.0/typora-0-11-18.exe)

0.11.18 现在被远程施法了,会提示过期无法使用,可以使用 0.9.96 版

下载地址:https://github.com/iuxt/src/releases/download/2.0/typora-setup-x64_0.9.96.exe

Mac 用户

下载地址: https://github.com/iuxt/src/releases/download/2.0/typora-0-11-18.dmg

Ubuntu 用户

下载地址:https://github.com/iuxt/src/releases/download/2.0/Typora_Linux_0.11.18_amd64.deb

安装方法

使用 apt 安装:

sudo apt install ./Typora_Linux_0.11.18_amd64.deb

如此你就完成了笔记编辑器的安装。

二:Gitee的配置

https://gitee.com在这里去作账户注册和登陆,新建仓库
在这里插入图片描述在这里插入图片描述在本地新建立一个文件夹,在该文件下开命令行



#Git 全局设置:

git config --global user.name "YourName"
git config --global user.email "YourInfo@user.noreply.gitee.com"

#创建 git 仓库:

mkdir paper
cd paper
git init 
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/YourName/paper.git
git push -u origin "master"

#已有仓库?

cd existing_git_repo
git remote add origin https://gitee.com/YourName/paper.git
git push -u origin "master"

如此每次更改后可以配合gitee去作同步。

三:脚本

脚本一:通过arxiv自动下载论文,提取论文标题,作者,日期,索引数等

arxiv_2_md.py

#!/usr/bin/env python3
import os
import re
import requests
import arxiv
from urllib.parse import urlparse, quote

def extract_arxiv_id(url: str) -> str:
    """
    从arXiv链接中提取arXiv ID。
    形如:https://arxiv.org/abs/1605.08386
    则返回:1605.08386
    """
    parsed = urlparse(url)
    if 'arxiv.org' not in parsed.netloc:
        raise ValueError("这不是一个有效的arXiv链接。")
    match = re.search(r'/abs/([0-9]+\.[0-9]+)', parsed.path)
    if not match:
        match = re.search(r'/pdf/([0-9]+\.[0-9]+)', parsed.path)
    if not match:
        raise ValueError("未能从链接中提取到arXiv ID。")
    return match.group(1)

def fetch_arxiv_metadata(arxiv_id: str):
    """
    使用arxiv Python包从arxiv获取元数据
    返回字典包含:title, authors, year, journal_ref, pdf_url
    """
    search = arxiv.Search(id_list=[arxiv_id])
    paper = next(search.results(), None)
    if paper is None:
        raise ValueError("未能在arXiv找到对应论文信息。")
    journal_ref = paper.journal_ref if paper.journal_ref else "N/A"
    authors = [au.name for au in paper.authors]
    year = paper.published.year
    return {
        "title": paper.title.strip(),
        "authors": authors,
        "year": year,
        "journal": journal_ref,
        "pdf_url": paper.pdf_url
    }

def download_pdf(pdf_url: str, save_dir: str = "./pdfs") -> str:
    """
    下载pdf文件到本地save_dir中,并返回本地文件相对路径。
    """
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)
    # 尝试从pdf_url中提取文件名
    basename = os.path.basename(pdf_url)
    if not basename.endswith(".pdf"):
        basename += ".pdf"
    local_filename = os.path.join(save_dir, basename)
    r = requests.get(pdf_url)
    r.raise_for_status()
    with open(local_filename, 'wb') as f:
        f.write(r.content)
    return local_filename

def fetch_citation_count_by_arxiv_id(arxiv_id: str) -> int:
    """
    调用 Semantic Scholar API 使用 ArXiv:<arxiv_id> 获取引用数。
    """
    url = f"https://api.semanticscholar.org/graph/v1/paper/ArXiv:{arxiv_id}?fields=citationCount"
    r = requests.get(url)
    if r.status_code == 200:
        data = r.json()
        return data.get("citationCount", 0)
    return 0

def fetch_citation_count_by_title(title: str) -> int:
    """
    如果直接使用ArXiv ID获取不到合适引用数,则通过标题在 Semantic Scholar 搜索。
    取搜索结果中匹配度最高(即第一个结果)的citationCount作为参考。
    """
    query = quote(title)
    url = f"https://api.semanticscholar.org/graph/v1/paper/search?query={query}&fields=title,citationCount"
    r = requests.get(url)
    if r.status_code == 200:
        data = r.json()
        papers = data.get("data", [])
        if papers:
            best_match = papers[0]
            if best_match["title"].lower().strip() == title.lower().strip():
                return best_match.get("citationCount", 0)
    return 0

def fetch_citation_count(arxiv_id: str, title: str) -> int:
    """
    尝试通过arxiv_id获取citationCount,如果为0则尝试通过标题获取。
    """
    count = fetch_citation_count_by_arxiv_id(arxiv_id)
    if count == 0:
        # 如果通过arxiv_id获取不到或为0,尝试通过标题搜索
        count = fetch_citation_count_by_title(title)
    return count

def generate_markdown(md_filename: str, title: str, authors: list, journal: str, year: int, local_pdf_path: str, citation_count: int, arxiv_url: str):
    """
    生成Markdown文件:
    包含标题、作者、期刊/会议信息、年份、本地PDF链接、原始arxiv链接和引用次数。
    """
    authors_str = ", ".join(authors)
    rel_pdf_path = os.path.relpath(local_pdf_path)
    with open(md_filename, 'w', encoding='utf-8') as f:
        f.write(f"# {title}\n\n")
        f.write(f"- **Authors:** {authors_str}\n")
        f.write(f"- **Venue/Journal:** {journal}\n")
        f.write(f"- **Year:** {year}\n")
        f.write(f"- **Local PDF:** [{rel_pdf_path}]({rel_pdf_path})\n")
        f.write(f"- **ArXiv Link:** [{arxiv_url}]({arxiv_url})\n\n")
        f.write(f"**Citations:** {citation_count}\n")

def main():
    # 输入 arxiv 链接
    arxiv_url = input("请输入arXiv链接:").strip()
    arxiv_id = extract_arxiv_id(arxiv_url)

    # 获取arxiv元数据
    meta = fetch_arxiv_metadata(arxiv_id)

    # 下载PDF
    local_pdf = download_pdf(meta["pdf_url"])

    # 获取引用数
    citation_count = fetch_citation_count(arxiv_id, meta["title"])

    # 询问用户md文件名
    default_md_name = f"{arxiv_id}.md"
    md_name_input = input(f"请输入要保存的Markdown文件名(不需扩展名,留空则使用 {default_md_name[:-3]}): ").strip()
    if md_name_input == "":
        md_filename = default_md_name
    else:
        md_filename = f"{md_name_input}.md"

    # 生成markdown文件
    generate_markdown(md_filename,
                      meta["title"],
                      meta["authors"],
                      meta["journal"],
                      meta["year"],
                      local_pdf,
                      citation_count,
                      arxiv_url)
    print(f"Markdown文件已生成:{md_filename}")

if __name__ == "__main__":
    main()

运行:

python ./arxiv_2_md.py

如果在输入arXiv后报错:

python ./arxiv_to_md_1.2.py 
请输入arXiv链接:https://arxiv.org/abs/2410.24207
/home/crist/WorkSpace/3D-reconstruction-paper/./arxiv_to_md_1.2.py:30: DeprecationWarning: The 'Search.results' method is deprecated, use 'Client.results' instead
  paper = next(search.results(), None)
Traceback (most recent call last):
  File "/home/crist/WorkSpace/3D-reconstruction-paper/./arxiv_to_md_1.2.py", line 150, in <module>
    main()
  File "/home/crist/WorkSpace/3D-reconstruction-paper/./arxiv_to_md_1.2.py", line 125, in main
    local_pdf = download_pdf(meta["pdf_url"])
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/crist/WorkSpace/3D-reconstruction-paper/./arxiv_to_md_1.2.py", line 56, in download_pdf
    r = requests.get(pdf_url)
        ^^^^^^^^^^^^^^^^^^^^^
  File "/home/crist/miniconda3/lib/python3.12/site-packages/requests/api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/crist/miniconda3/lib/python3.12/site-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/crist/miniconda3/lib/python3.12/site-packages/requests/sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/crist/miniconda3/lib/python3.12/site-packages/requests/sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/crist/miniconda3/lib/python3.12/site-packages/requests/adapters.py", line 633, in send
    conn = self.get_connection_with_tls_context(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/crist/miniconda3/lib/python3.12/site-packages/requests/adapters.py", line 483, in get_connection_with_tls_context
    proxy_manager = self.proxy_manager_for(proxy)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/crist/miniconda3/lib/python3.12/site-packages/requests/adapters.py", line 282, in proxy_manager_for
    manager = self.proxy_manager[proxy] = SOCKSProxyManager(
                                          ^^^^^^^^^^^^^^^^^^
  File "/home/crist/miniconda3/lib/python3.12/site-packages/urllib3/contrib/socks.py", line 212, in __init__
    raise ValueError(f"Unable to determine SOCKS version from {proxy_url}")
ValueError: Unable to determine SOCKS version from socks://127.0.0.1:7890/

解决办法:

export ALL_PROXY=socks5://127.0.0.1:7890
export HTTP_PROXY=socks5://127.0.0.1:7890
export HTTPS_PROXY=socks5://127.0.0.1:7890

脚本二:
提取PDF中的图片,将我的脚本和pdf文件放到一起:

#!/usr/bin/env python3
import os
import subprocess
import tkinter as tk
from tkinter import messagebox, font

def list_pdfs(directory="."):
    """列出指定目录中的所有PDF文件并返回列表。"""
    pdfs = [f for f in os.listdir(directory) if f.lower().endswith('.pdf')]
    return pdfs

def extract_images(pdf_path, output_dir="images"):
    """使用pdfimages从指定PDF中提取图片。"""
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    base_name = os.path.splitext(os.path.basename(pdf_path))[0]
    output_prefix = os.path.join(output_dir, base_name)
    cmd = ["pdfimages", "-j", pdf_path, output_prefix]
    try:
        subprocess.run(cmd, check=True)
        return True, f"图片已提取到 {output_dir} 目录中,以 {base_name}-xxx 的形式命名。"
    except subprocess.CalledProcessError:
        return False, "提取图片失败,请确保已安装pdfimages工具。"

def on_extract():
    selection = listbox.curselection()
    if not selection:
        messagebox.showwarning("警告", "请先选择一个PDF文件")
        return
    index = selection[0]
    pdf_file = pdfs[index]
    success, msg = extract_images(pdf_file)
    if success:
        messagebox.showinfo("提取完成", msg)
    else:
        messagebox.showerror("错误", msg)

root = tk.Tk()
root.title("PDF图片提取器")

# 设置全局字体
root.option_add("*Font", "Helvetica 12")

pdfs = list_pdfs(".")

frame = tk.Frame(root)
frame.pack(padx=10, pady=10, fill="both", expand=True)

label = tk.Label(frame, text="请选择一个PDF文件:", font=("Helvetica", 12, "bold"))
label.pack(anchor="w")

listbox = tk.Listbox(frame, height=10)
listbox.pack(fill="both", expand=True)

for pdf in pdfs:
    listbox.insert(tk.END, pdf)

if not pdfs:
    listbox.insert(tk.END, "当前目录未找到PDF文件")

btn_frame = tk.Frame(root)
btn_frame.pack(pady=5)
extract_btn = tk.Button(btn_frame, text="提取图片", font=("Helvetica", 12))
extract_btn.config(command=on_extract)
extract_btn.pack()

root.mainloop()

这样就可以把图片保存到img文件夹下了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/939069.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java_断点调试(debug)

按照如下配置好后&#xff0c;即可点击“F7”,进入相应的方法&#xff0c;查看源码 package com.hspedu.debug_;//debug对象创建的过程&#xff0c;加深对调试的理解 public class Debug01 {public static void main(String[] args) {//创建对象的流程//&#xff08;1&#xff…

c++数据结构算法复习基础--13--基数算法

基数排序 - 桶排序 时间复杂度 O(n*d) – d为数据的长度 每次比较一位&#xff08;个位、十位。。。&#xff09;&#xff0c;所以取值范围就为0-9。 根据该特点&#xff0c;设计桶的概念 – 0号桶、1号桶… 1、思想 1&#xff09;找出最长的数字&#xff0c;确定要处理的…

微信小程序TTS解决方案

微信小程序原生语音合成 API&#xff08;基础且简单&#xff09; 介绍&#xff1a;微信小程序提供了基础的语音合成能力。通过wx.createInnerAudioContext()等相关API&#xff0c;可以实现简单的语音播放功能。不过它主要是用于音频播放&#xff0c;对于完整的文本到语音&#…

matlab绘图时设置左、右坐标轴为不同颜色

目录 一、需求描述 二、实现方法 一、需求描述 当图中存在两条曲线&#xff0c;需要对两条曲线进行分别描述时&#xff0c;应设置左、右坐标轴为不同颜色&#xff0c;并设置刻度线&#xff0c;且坐标轴颜色需要和曲线颜色相同。 二、实现方法 1.1、可以实现&#xff1a; 1…

Vue3动态表单实现

实现方法&#xff1a;通过<component />标签动实现动态表单渲染 component标签&#xff1a; 在vue中 component 标签用于动态组件标签的渲染。它允许在同一个挂载点上条件渲染不同的组件&#xff0c;通过is属性可以渲染指定的属性 在上面的例子中&#xff0c;通过调用…

[C++]C++工具之对异常情况的处理(throw、catch、try)以及用命名空间避免同名冲突

一、C 异常处理&#x1f60a; 1.1 定义 C 中的异常处理用于应对程序运行中的异常情况&#xff08;如除零、数组越界等&#xff09;&#xff0c;通过 try-catch 机制捕获和处理错误&#xff0c;防止程序崩溃。 异常是程序运行时意外发生的事件&#xff0c;可以通过抛出&#xf…

游戏引擎学习第53天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾 现在我们正进行游戏结构的重构&#xff0c;目的是为了更合理地安排游戏的组织方式&#xff0c;模拟玩家周围的实体。我们将这些实体分为两类&#xff1a;一类是当前正在屏幕上显示的实体&#xff0c;另一类是被映射到低频更…

【六足机器人】04上位机开发

图&#xff1a;QT界面效果图 一、主要功能介绍 1.1 登录界面 登录界面&#xff0c;用来判断是否账号密码输入正确&#xff0c;错误将会弹出消息框。 void first::on_enroll_clicked(){if(ui->account->text()"共创芯未来"&&ui->password->text…

RockyLinux9编译安装MySQL5.7

原文链接&#xff1a;RockyLinux9编译安装MySQL5.7 - Liu Zijians Blog | 刘子健的博客 本文最后更新于 2024年12月15日 使用源码编译安装MySQL5.7 1.下载 打开MySQL-Community-Server官方下载页面:https://downloads.mysql.com/archives/community/ 筛选出要下载的版本&…

什么是3DEXPERIENCE SOLIDWORKS,它有哪些角色和功能?

将业界领先的 SOLIDWORKS 3D CAD 解决方案连接到基于单一云端产品开发环境 3DEXPERIENCE 平台。您的团队、数据和流程全部连接到一个平台进行高效的协作工作&#xff0c;从而能快速的做出更好的决策。 目 录&#xff1a; ★ 1 什么是3DEXPERIENCE SOLIDWORKS ★ 2 3DEXPERIE…

OpenCVE:一款自动收集NVD、MITRE等多源知名漏洞库的开源工具,累计收录CVE 27万+

漏洞库在企业中扮演着至关重要的角色&#xff0c;不仅提升了企业的安全防护能力&#xff0c;还支持了安全决策、合规性要求的满足以及智能化管理的发展。前期博文《业界十大知名权威安全漏洞库介绍》介绍了主流漏洞库&#xff0c;今天给大家介绍一款集成了多款漏洞库的开源漏洞…

《Redis设计与实现》读书笔记-客户端

目录 1.Client简介 2.客户端属性 1&#xff09;&#xff08;本文重点&#xff09;比较通用的属性 2&#xff09;&#xff08;后续分享&#xff09;另外一类是和特定功能相关的属性 2.1套接字文件描述符 2.2名字 2.3标志&#xff08;flag&#xff09; 2.4输入缓冲区 2.…

Oracle Database 21c Express Edition数据库 和 Sqlplus客户端安装配置

目录 一. 前置条件二. Win10安装配置Oracle数据库2.1 数据库获取2.2 数据库安装2.3 数据库配置确认2.4 数据库访问 三. Win10配置Oracle数据库可对外访问3.1 打开文件和打印机共享3.2 开放1521端口 四. 端口与地址确认4.1 查看监听器的状态4.2 Win10查看1521端口是否被监听4.3 …

10篇--图像噪点消除

概念 何为噪点&#xff1f; 噪点&#xff1a;指图像收到的一些干扰因素&#xff0c;通常是由图像采集设备、传输信道等因素造成的&#xff0c;表现为图像中随机的亮度&#xff0c;也可以理解为有那么一些点的像素值与周围的像素值格格不入。 常见的噪声类型 高斯噪声&#…

【开源免费】基于Vue和SpringBoot的渔具租赁系统(附论文)

本文项目编号 T 005 &#xff0c;文末自助获取源码 \color{red}{T005&#xff0c;文末自助获取源码} T005&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 渔…

Linux网络基础-----传输层UDP协议

目录 端口号&#xff1a; 查询各类服务的端口号 加深理解端口号&#xff1a; UDP协议 UDP协议特点&#xff1a; 关于缓冲区&#xff1a; 内核层面理解UDP报文 端口号&#xff1a; 知名端口号&#xff1a;0 ~ 1023&#xff1a;被HTTP、SSH等应用层协议广泛使用的端口号&…

XXE靶场

XXE-lab 靶场 靶场网址&#xff1a;http://172.16.0.87/ 第一步我们看到网站有登录框我们试着用 bp 去抓一下包 将抓到的包发到重放器中 然后我们构建palody <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "php://filter/readconvert.base64-encode/resourceC:/flag/fla…

ubuntu+ros新手笔记(三):21讲没讲到的MoveIt2

1 安装MoveIt2 安装参照在ROS2中&#xff0c;通过MoveIt2控制Gazebo中的自定义机械手 安装 MoveIt2可以选择自己编译源码安装&#xff0c;或者直接从二进制安装。 个人建议直接二进制安装&#xff0c;可以省很多事。 sudo apt install ros-humble-moveitmoveit-setup-assistan…

运维 mysql、redis 、RocketMQ性能排查

MySQL查看数据库连接数 1. SHOW STATUS命令-查询当前的连接数 MySQL 提供了一个 SHOW STATUS 命令&#xff0c;可以用来查看服务器的状态信息&#xff0c;包括当前的连接数。 SHOW STATUS LIKE Threads_connected;这个命令会返回当前连接到服务器的线程数&#xff0c;即当前…

jmeter连接mysql

查询mysql数据库版本 SELECT VERSION(); 下载jmeter mysql 驱动jar包&#xff0c;版本低于mysql版本&#xff0c;放在jmeter的lib 路径下 MySQL :: Download MySQL Connector/J (Archived Versions) 添加JDBC Connection Configuration 填写 variable name 及数据库信息 注意…