-
Notifications
You must be signed in to change notification settings - Fork 5
Improve scrapers content extraction #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mikesiez
wants to merge
8
commits into
main
Choose a base branch
from
improve-scrapers-content-extraction
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
8ebe583
Completed scraping, meets all requirements
mikesiez b61e058
better nav identification to be removed
mikesiez 69b7f5b
Added bs4, fixed scraper, added offline testing
b6feb41
linter fixes
89af866
more linter fixes:
6394893
linter fixes fixes
0077be6
Various adjustments made. [Checkpoint]
eeb2107
fixed all issues
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| This page will help you plan your courses and academic career as you complete your Bachelor of Cybersecurity degree program. | ||
|
|
||
| When selecting your courses for the term, it is helpful to review the Program Requirements [Link: https://calendar.carleton.ca/undergrad/undergradprograms/computerscience/] and your academic audit [Link: https://carleton.ca/academicadvising/how-to-read-your-audit/] . If you have questions regarding course selection, please contact our undergraduate advisor [Link: https://carleton.ca/scs/our-people/#ug-advisors] team. | ||
|
|
||
| At any time you can build a sample timetable within Carleton Central or through the Public Class Schedule [Link: http://central.carleton.ca/prod/bwysched.p_select_term?wsea_code=EXT] . | ||
|
|
||
| Course Descriptions and Outlines | ||
|
|
||
| Registration | ||
|
|
||
| First Year Registration Guide | ||
|
|
||
| Academic Audit | ||
|
|
||
| Prerequisites | ||
|
|
||
| Before you Register | ||
|
|
||
| After you Register | ||
|
|
||
| Course Patterns | ||
|
|
||
| Electives and Prohibited Courses | ||
|
|
||
| Course Selection FAQs | ||
|
|
||
| Course Descriptions and Outlines | ||
|
|
||
| Course Descriptions [Link: https://carleton.ca/scs/current-students/undergraduate-students/courses-and-registration/] | ||
|
|
||
| Course Outlines [Link: https://outline.scs.carleton.ca] | ||
|
|
||
| Registration | ||
|
|
||
| First Year Registration Guide | ||
|
|
||
| Welcome to Carleton and your Bachelor of Cybersecurity degree program! Please read this degree guide prior to registering. | ||
|
|
||
| First Year Registration Guide [Link: https://carleton.ca/registration/course-selection-guide/bcyber/] | ||
|
|
||
| Academic Audit | ||
|
|
||
| The academic audit is the ‘road map’ to academic success. It lists which courses you are required to take in order to complete your degree at Carleton. The audit will inform you of the progress you have already made, as well as show you the courses that you will need to take in the future. Remember to check your audit regularly to ensure you are fulfilling your degree requirements. | ||
|
|
||
| Understanding your Academic Audit ↗ [Link: https://carleton.ca/academicadvising/how-to-read-your-audit/] | ||
|
|
||
| Prerequisites and Restrictions | ||
|
|
||
| A prerequisite is a course that must be successfully completed (with a minimum grade of D- or above unless otherwise noted) before you are able to register into the course. A course may also have additional restrictions that require students be in a particular program, and/or have a specific year standing (first, second, third of fourth) in order to register. | ||
|
|
||
| The School of Computer Science strictly enforces calendar prerequisites . If you do not meet the prerequisite(s) of a COMP or CSEC course , you will be deregistered. More information on deregistration can be found in Section 2.1.7 of the Undergraduate Calendar [Link: https://calendar.carleton.ca/undergrad/regulations/academicregulationsoftheuniversity/registration-evaluation-records/#deregistration] . This also applies to DEF (deferred final exam); once the final grade for that course is posted, you will be deregistered from any current course if the prerequisite(s) is not met. As deferred exams are always held after the registration period closes, if you are deregistered you will not be able to add more courses to your class schedule. Please be aware that deregistration can happen at anytime during the term which may affect your status as a full-time student. Please see this link [Link: https://carleton.ca/academicadvising/reduced-course-load/] to determine who you should speak with if your student status changes. Please note that students with a GNA (grade not available) in a course may also be affected by this policy. | ||
|
|
||
| Before you register | ||
|
|
||
| Course registration is done online through Carleton Central [Link: http://central.carleton.ca/] . It is your one-stop service for registration, student records, admission, and fee information. | ||
|
|
||
| Refer to the Registrar’s Office website [Link: https://carleton.ca/registration/] for how-to videos to assist you in navigating the Carleton Central registration system. You can view the registration open and deadline dates on the Registration Dates and Deadlines webpage [Link: https://students.carleton.ca/academic-dates/] . | ||
|
|
||
| After You Register | ||
|
|
||
| Pay your tuition by the payment deadline each term to avoid penalties or late fees. The Student Accounts office has information on how to make a payment [Link: https://carleton.ca/studentaccounts/fee-payment/] . | ||
|
|
||
| Course Patterns | ||
|
|
||
| It is recommended that all B.Cyber. students register in courses each term according to the course pattern listed below. | ||
|
|
||
| Students should refer to the course pattern of their Catalog Year. In most cases, a student’s Catalog Year will match the term a student was admitted to the B.Cyber. program, but should be confirmed by reviewing your audit. [Link: https://carleton.ca/academicadvising/how-to-read-your-audit/] The Catalog Year is listed in the upper-right hand corner of the audit. | ||
|
|
||
| BCYBER Course Map 202630 (pdf) [PDF: https://carleton.ca/scs/wp-content/uploads/sites/260/BCyber-Course-Map-202630-3.pdf] – (admit term Fall 2026) | ||
|
|
||
| BCYBER Course Map 202530 (pdf) [PDF: https://carleton.ca/scs/wp-content/uploads/sites/260/FINAL2-BCyber-Course-Map-202530.pdf] – (admit term Fall 2025) | ||
|
|
||
|
|
||
|
|
||
| Electives and Prohibited Courses | ||
|
|
||
| Electives are courses required for completion of your 20.0 credit degree program. Many first year students find it difficult to choose electives. Our best advice is to choose a topic you enjoyed in high school or are generally interested in studying. | ||
|
|
||
| Find course titles and descriptions in the courses [Link: https://calendar.carleton.ca/undergrad/courses/] section of the undergraduate calendar. | ||
|
|
||
| Read the course descriptions to ensure you have the prerequisites , and then check the Public Class Schedule in Carleton Central to see when the course is offered. | ||
|
|
||
| Be aware of preclusions in the course descriptions. If a course precludes additional credit for another course, that means you cannot get credit for both of those courses. Please note that preclusion does not mean equivalent , though in some cases it may be. Please contact your undergraduate advisor for further clarification. | ||
|
|
||
| If you encounter a restriction when trying to register, please submit a Registration Override Request on Carleton Central, and the department owning the course will get back to you. | ||
|
|
||
| Free Electives | ||
|
|
||
| Free Electives are all courses offered by the Faculty of Arts and Social Sciences, the Faculty of Public Affairs, the Sprott School of Business, the Faculty of Science and the Faculty of Engineering and Design except for courses in the Prohibited Courses category. Free electives can include COMP, CSEC, DATA, MATH and STAT courses. | ||
|
|
||
| Prohibited Courses | ||
|
|
||
| Prohibited courses cannot be used for credit towards any program requirement (ie. electives, minors, etc.) for students enrolled in a B.Cyber. program. Please always refer to the most recent Undergraduate Calendar [Link: https://calendar.carleton.ca/undergrad/undergradprograms/computerscience/] for the most up-to-date list of prohibited courses , and for all prerequisites and preclusions. | ||
|
|
||
| IMPORTANT: Maximum Number of Credits Below the 2000-level. | ||
|
|
||
| A student may count a maximum of 7.0 credits below the 2000-level toward fulfillment of graduation requirements. | ||
|
|
||
| Credits in excess of this limit will be set aside as Extra to the Degree (ETD), No Credit for the Degree (NCD), or Forfeit. This allows students to increase their CGPA by pushing out low grades below the 2000-level through replacement by higher grades at the same level. | ||
|
|
||
| Course Selection FAQs | ||
|
|
||
| Here are some frequently asked questions regarding course selection: | ||
|
|
||
| What is a prerequisite? | ||
|
|
||
| Some courses require you to take one or more prerequisite s in order to get into the course. A prerequisite is a course that must be successfully completed (with a minimum grade of D- or above unless otherwise noted) BEFORE you are able to register into the course. By first taking all of the required prerequisite course(s), this will ensure that your knowledge level is adequate for you to understand the material in the course that you are trying to register into. Always look at the most current Undergraduate Calendar [Link: http://calendar.carleton.ca/undergrad/] in order to determine which prerequisites are required for the course that you are trying to take. Some COMP courses will require a prerequisite grade that is higher than D-. The School of Computer Science strictly enforces prerequisites as outlined in the calendar. | ||
|
|
||
| What is a preclusion? | ||
|
|
||
| When two courses have very similar (or overlapping) material, the calendar often indicates that the courses will preclude one another. This means that you cannot have both of these courses count as credit towards your degree requirements. Precluded courses are not necessarily equivalent. Do not assume that one course can substitute for another simply because it precludes the other course. You should always check with your Undergraduate Advisors to be sure. Note that if you take a course that precludes another course that you have already taken, the most recent grade will count. Preclusions are listed in the course description in the Undergraduate Calendar [Link: http://calendar.carleton.ca/undergrad/] . | ||
|
|
||
| Where are the CSEC courses on the Public Class Schedule? | ||
|
|
||
| The Bachelor of Cybersecurity is introducing all new CSEC courses as part of the curriculum. These courses will be developed, and released, as the first cohort of students progress through their program. 2000-level CSEC courses will be released in the 2026-27 Academic Year, 3000-level CSEC courses will be released in the 2027-28 Academic Year, and finally the remaining 4000-level CSEC courses will be released in the 2028-29 Academic Year. As of May 2025 all core CSEC courses will be listed in the Undergraduate Calendar [Link: http://calendar.carleton.ca/undergrad/] , but will not appear on the public class schedule until they are offered for the first time. | ||
|
|
||
| Do I have to follow the course pattern for my admit year? | ||
|
|
||
| Students are encouraged to follow the provided course pattern towards graduation, as it will guarantee a conflict free schedule each year in addition to ensuring you will meet all prerequisite requirements each term. If you are off pattern (or plan to deviate) from your provided course pattern, you should check in with one of your Undergraduate Advisors [Link: https://carleton.ca/scs/our-people/school-of-computer-science-administration/administrative-staff/undergraduate-advisor/] to discuss some considerations for planning your courses towards graduation.Courses and Registration (B.Cyber.) - School of Computer Science |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,43 +1,88 @@ | ||
| import httpx | ||
| import trafilatura | ||
|
|
||
| from src.config.logger import get_logger | ||
|
|
||
| log = get_logger(__name__) | ||
|
|
||
|
|
||
| def scrape(url: str) -> tuple[str, str | None]: | ||
| """Fetch a URL and extract clean text + title. | ||
|
|
||
| Returns (text, title). Title may be None if not found. Text may be empty | ||
| if trafilatura couldn't extract anything; the caller should check and skip. | ||
| """ | ||
| log.info("scrape_started", url=url) | ||
| with httpx.Client(timeout=30, follow_redirects=True) as client: | ||
| response = client.get(url) | ||
| response.raise_for_status() | ||
|
|
||
| # Known limitations (tracked as a separate ticket): | ||
| # - Misses content inside aria-hidden="true" accordions (common on FAQ pages) | ||
| # - Misses question text but gets answer text on other FAQ pages, we should get both | ||
| # - Link formatting is markdown-style and may need cleanup downstream | ||
| # Improving extraction quality is a tuning ticket, not a blocker for development. | ||
| text = ( | ||
| trafilatura.extract( | ||
| response.text, | ||
| favor_recall=True, | ||
| include_links=True, | ||
| include_tables=True, | ||
| include_formatting=False, | ||
| include_comments=False, | ||
| deduplicate=True, | ||
| output_format="txt", | ||
| ) | ||
| or "" | ||
| ) | ||
|
|
||
| metadata = trafilatura.extract_metadata(response.text) | ||
| title = metadata.title if metadata else None | ||
|
|
||
| log.info("scrape_complete", url=url, chars=len(text), title=title) | ||
| return text, title | ||
| from urllib.parse import urlsplit | ||
| import httpx | ||
| from bs4 import BeautifulSoup | ||
| import re | ||
|
|
||
| from src.config.logger import get_logger | ||
|
|
||
| log = get_logger(__name__) | ||
|
|
||
| _BOILERPLATE_TAGS = ["header", "footer", "nav", "script", "style", "noscript"] | ||
| _BOILERPLATE_SELECTORS = ( | ||
| ".navbar-container, .navbar, .footer, .global-nav, " | ||
| ".navigation, .topbar, .content__meta, .visuallyhidden, " | ||
| ".resource__contributors-list, #on-this-page, .resource__sources__heading" | ||
| ) | ||
| _BLOCK_TAGS = ["p", "div", "li", "h1", "h2", "h3", "h4", "h5", "h6", | ||
| "tr", "section", "article", "ul", "ol", "table", "br", "blockquote"] | ||
|
|
||
| def _extract_from_html(html: str) -> tuple[str, str | None]: | ||
| log.info("html_extract_start", html_len=len(html)) | ||
|
|
||
| cut_marker = "<!-- close main-wrapper" | ||
| if cut_marker in html: | ||
| html = html.split(cut_marker)[0] | ||
|
mikesiez marked this conversation as resolved.
|
||
|
|
||
| soup = BeautifulSoup(html, "html.parser") | ||
|
|
||
| root = soup.select_one("main, [role=main], #main-content") | ||
| if root is None: # CCSS-style pages have no <main> | ||
| root = soup.body or soup | ||
|
|
||
| # still might need to clean some things up | ||
| for t in soup(_BOILERPLATE_TAGS): | ||
| t.decompose() | ||
| for el in soup.select(_BOILERPLATE_SELECTORS): | ||
| el.decompose() | ||
|
|
||
| log.info("boilerplate_removed") | ||
|
|
||
| # formatting links after clearing having cleared clutter | ||
| for link in root.find_all("a"): | ||
| href = (link.get("href") or "").strip() | ||
| if href and not href.startswith("#"): | ||
| text = link.get_text(" ", strip=True) | ||
| is_pdf = urlsplit(href).path.lower().endswith(".pdf") | ||
| marker = "PDF" if is_pdf else "Link" | ||
| link.replace_with(f"{text} [{marker}: {href}] ") | ||
|
|
||
| log.info("links_parsed") | ||
|
|
||
| for tag in root.find_all(_BLOCK_TAGS): | ||
| tag.append("\n") | ||
|
|
||
| text = root.get_text(" ", strip=False) | ||
| text = re.sub(r"[ \t]+", " ", text) | ||
| text = re.sub(r" *\n *", "\n", text) | ||
| text = re.sub(r"\n{3,}", "\n\n", text) | ||
| text = text.strip() | ||
|
|
||
| title = soup.title.get_text(strip=True) if soup.title else None | ||
|
|
||
| log.info("html_extract_complete", text_len=len(text), has_title=title is not None) | ||
| return text, title | ||
|
|
||
|
|
||
| def scrape(url: str) -> tuple[str, str | None]: | ||
| """Fetch a URL and extract clean text + title. | ||
|
|
||
| Returns (text, title). Title may be None if not found. | ||
| """ | ||
| log.info("scrape_called", url=url) | ||
|
|
||
| log.info("http_request_start", url=url) | ||
| with httpx.Client(timeout=30, follow_redirects=True) as client: | ||
| response = client.get(url) | ||
| response.raise_for_status() | ||
|
|
||
| log.info( | ||
| "http_request_success", | ||
| url=url, | ||
| status_code=response.status_code, | ||
| bytes=len(response.text), | ||
| ) | ||
|
|
||
| log.info("html_parsing_start", url=url) | ||
| text, title = _extract_from_html(response.text) | ||
| log.info("scrape_complete", url=url, chars=len(text), title=title) | ||
| return text, title | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.