ktu-papers-api / split_syllabus.py
GitHub Action
Deploy clean API instance with LFS and README metadata
7f6b634
Raw
History Blame Contribute Delete
5.17 kB
# Bulk KTU Syllabus Splitter & Metadata Generator
# Automatically loops through all downloaded branches!
import argparse
import fitz # PyMuPDF
import json
import os
import re
def clean_subject_name(name):
name = name.strip()
name = re.sub(r'^(COURSE NAME\s*:\s*)', '', name, flags=re.IGNORECASE)
name = re.sub(r'\s+', ' ', name)
return name
def bulk_split_ktu_syllabus(summary_file, scheme, output_dir):
pdf_dir = os.path.join(output_dir, "pdfs")
os.makedirs(pdf_dir, exist_ok=True)
# Read the summary file generated by the scraper
with open(summary_file, 'r') as f:
downloaded_files = json.load(f)
flat_db = []
print(f"Found {len(downloaded_files)} branches to process...")
for item in downloaded_files:
pdf_path = item["local_path"]
branch = item["branch_name"]
if not os.path.exists(pdf_path):
print(f" [Skip] Could not find {pdf_path}")
continue
print(f"\nProcessing: {branch}")
doc = fitz.open(pdf_path)
total_pages = len(doc)
subjects = []
current_subject = None
for page_idx in range(total_pages):
page = doc.load_page(page_idx)
text = page.get_text()
lines = [line.strip() for line in text.split("\n") if line.strip()]
is_subject_start = False
sem_tag = None
course_name = None
course_code = None
for i, line in enumerate(lines):
if line.startswith("SEMESTER S") and len(line) <= 12:
sem_tag = line
if i + 1 < len(lines):
course_name = lines[i+1]
if i + 2 < len(lines) and (lines[i+2].startswith("(") or "group" in lines[i+2].lower()):
course_name += " " + lines[i+2]
for j in range(i, min(i + 15, len(lines))):
if lines[j] == "Course Code" and j + 1 < len(lines):
course_code = lines[j+1]
break
if course_code:
is_subject_start = True
break
if is_subject_start:
if current_subject:
current_subject["end_page"] = page_idx
subjects.append(current_subject)
current_subject = {
"semester": sem_tag.replace("SEMESTER ", "").strip(),
"subject_name": clean_subject_name(course_name),
"course_code": course_code.strip(),
"start_page": page_idx + 1,
"end_page": None
}
if current_subject:
current_subject["end_page"] = total_pages
subjects.append(current_subject)
print(f" -> Discovered {len(subjects)} subjects")
for sub in subjects:
sem = sub["semester"]
code = sub["course_code"]
name = sub["subject_name"]
start = sub["start_page"]
end = sub["end_page"]
pdf_filename = f"{sem}_{code}.pdf"
pdf_relative_path = f"pdfs/{pdf_filename}"
pdf_out_path = os.path.join(pdf_dir, pdf_filename)
# Extract and save the specific pages
sub_doc = fitz.open()
sub_doc.insert_pdf(doc, from_page=start-1, to_page=end-1)
sub_doc.save(pdf_out_path)
sub_doc.close()
# Append to the massive master array
flat_db.append({
"branch": branch,
"scheme": scheme,
"semester": sem,
"course_code": code,
"subject_name": name,
"start_page": start,
"end_page": end,
"page_count": end - start + 1,
"pdf_file": pdf_relative_path
})
doc.close()
# Outside the loop: Save the combined master database
with open(os.path.join(output_dir, "syllabus_flat.json"), "w") as jf:
json.dump(flat_db, jf, indent=2)
print(f"\n=== BULK PROCESS COMPLETED ===")
print(f"Processed {len(downloaded_files)} branches.")
print(f"Generated a massive combined database with {len(flat_db)} total subjects!")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="KTU PDF Syllabus Bulk Splitter")
parser.add_argument("--summary", default="./raw_pdfs/downloaded_syllabi.json", help="Path to the JSON summary generated by scraper")
parser.add_argument("--scheme", default="B.Tech Full Time 2024 Scheme", help="Syllabus scheme name")
parser.add_argument("--outdir", default=".", help="Directory to output split PDFs and JSON")
args = parser.parse_args()
bulk_split_ktu_syllabus(args.summary, args.scheme, args.outdir)