research paper renamer

2025-05-07 06:58 Note Type: completed Tags: python, research-papers, productivity

import os

import subprocess

import re

import google.generativeai as genai

from pdf2image import convert_from_path

import pytesseract

๐Ÿ” Load Gemini API key from env var

genai.configure(api_key="AIzaSyAj8iiaCcSYEMAVhB_E2se14P2WR9eNkP0")

โšก๏ธ Use the faster Gemini 2.0 Flash model

model = genai.GenerativeModel("gemini-2.0-flash")

def extract_text_with_fallback(pdf_path, max_chars=3000):

"""Try pdftotext first; fallback to OCR if the result looks empty or unhelpful."""

try:

result = subprocess.run(

['pdftotext', pdf_path, '-'],

stdout=subprocess.PIPE,

stderr=subprocess.PIPE,

check=True

)

text = result.stdout.decode('utf-8').strip()

๐Ÿ’ก Check if the text looks real (not boilerplate or junk)

if len(text) >= 100 and "All Rights Reserved" not in text:

return text[:max_chars]

else:

print(f"โš ๏ธ pdftotext returned low-value text, falling back to OCR for: {os.path.basename(pdf_path)}")

except Exception as e:

print(f"โŒ pdftotext failed: {e}")

Fallback to OCR

try:

images = convert_from_path(pdf_path, dpi=400, first_page=1, last_page=3)

text = ""

for i, img in enumerate(images):

ocr_text = pytesseract.image_to_string(img, lang="eng")

print(f"--- OCR Page {i+1} ---\n{ocr_text[:300]}\n")

text += ocr_text

if len(text) > max_chars:

break

return text.strip()[:max_chars]

except Exception as e:

print(f"โŒ OCR failed for {pdf_path}: {e}")

return ""

def ask_gpt_to_name(text):

"""Send PDF text to Gemini and return a filename."""

prompt = f"""

Extract the following from the academic paper text below:

  1. The full title of the paper

  2. The last names of all authors (in order)

  3. The year of publication

Then return a filename in the format:

{{Paper title in sentence case}} - {{Author1, Author2, ..., AuthorN}} - {{Year}}.pdf

Rules:

  • Authors must be comma-separated

  • Use ' - ' as the separator

  • Only return the filename. No commentary, no quotes.

  • Remove double quotes ' " ' if present in title

  • In case the paper has both a title and subtitle, in place of {{Paper title in sentence case}}, use {{Paper title in sentence case}} - {{Paper subtitle in sentence case}}, using ' - ' as the separator

TEXT:

{text}

"""

try:

response = model.generate_content(prompt)

filename = response.text.strip()

filename = re.sub(r'[\/*?:"<>|]', '', filename) # Clean illegal filename chars

return filename

except Exception as e:

print(f"โŒ Gemini API error: {e}")

return None

def rename_pdfs(folder_path):

"""Rename PDFs in folder based on AI-generated filename."""

for file in os.listdir(folder_path):

if file.lower().endswith(".pdf"):

full_path = os.path.join(folder_path, file)

print(f"๐Ÿ“„ Processing: {file}")

text = extract_text_with_fallback(full_path)

if not text:

print(f"โš ๏ธ Skipping (no extractable text): {file}")

continue

new_name = ask_gpt_to_name(text)

if new_name:

new_path = os.path.join(folder_path, new_name)

try:

os.rename(full_path, new_path)

print(f"โœ… Renamed: {file} โ†’ {new_name}")

except Exception as e:

print(f"โŒ Failed to rename {file}: {e}")

else:

print(f"โš ๏ธ Skipping (Gemini failed): {file}")

๐Ÿ Entry point

if name == "main":

import sys

if len(sys.argv) < 2:

print("Usage: python3 rename_with_gemini_ocr.py /path/to/pdf/folder")

sys.exit(1)

folder = sys.argv[1]

rename_pdfs(folder)

Back to Vault