Assignment
Python & LLM Assignment: Article Analyzer &
Structured Categorizer
Abstract
This assignment focuses on building a robust Python script that integrates web content
acquisition and Large Language Model (LLM) capabilities. The script will automatically fetch,
process, and analyze web articles to identify multiple content categories within a single page,
extract relevant text snippets specifically for each category, and associate internal links. It will
also determine the general type of website (e.g., news, blog, company website). The primary
goal is to produce a structured JSON output that provides a detailed thematic breakdown of the
article's content and its website context, making it suitable for sophisticated content analysis
and knowledge management workflows. The project emphasizes handling dynamic web
content, filtering irrelevant elements, and efficiently processing multiple URLs.
Objective
The goal of this assignment is to build a robust Python script that leverages a Large Language
Model (LLM) to automatically fetch, process, identify multiple content categories within a
single web page, extract specific text content and relevant links for each identified category,
and determine the overall website type. This task will test your ability to integrate web content
acquisition (including JavaScript-rendered content), sophisticated LLM interaction (for multi-
faceted identification), concurrent processing, and precise structured output generation in
Python.
Scenario
You are tasked with creating an efficient and intelligent tool for a specialized content analysis
and knowledge management team. They encounter many websites where a single page (e.g., a
company's "About Us" page) contains multiple distinct sections such as "Our Team," "Products
& Services," and "Contact Information." They need a granular breakdown: for each identified
category, they want to see the specific text snippet pertaining to that category and any internal
links related to it. They also need to understand the fundamental nature of the website itself
(e.g., is it primarily a news site, a company's main presence, or a blog?). This granular,
structured output is crucial for their complex analytical workflows. The tool must also be able to
handle dynamic web content and exclude irrelevant elements from the analysis.
Requirements
Your Python script should perform the following steps:
1. Input Handling:
The script must accept URLs from two sources:
A hardcoded list for default testing.
A command-line argument that specifies a path to a text file, where each line is a
URL. The script should prioritize the file input if provided.
Implement robust URL validation (e.g., check if it's a valid HTTP/HTTPS URL and if the
domain is reachable).
2. Web Content Acquisition & Link Identification:
For each valid URL, fetch the HTML content after JavaScript rendering has
completed. This means you need to use a tool that can execute JavaScript on the page
(e.g., a headless browser).
Focus on Main Article Content: After fetching, the extracted content for analysis must
be free from unwanted elements like:
Advertisements
Cookie consent banners
Navigation menus, footers, sidebars (unless they are part of the core article
content).
Pop-ups or overlays.
Handle Redirects: If the initial URL redirects, ensure the content is fetched from the
final URL, and this final URL is reported in the output.
Primary Text Extraction: Utilize a robust method for effective extraction of the main,
human-readable text content from the JavaScript-rendered DOM, aiming to minimize
boilerplate. This extracted content will be referred to as extracted_web_content for
later use in the final output.
Fallback Text Extraction: If the primary method fails or returns insufficient content,
implement a fallback mechanism to try and extract content from common article-like
elements (e.g., <article> , <main> , <div class="post-content"> ) from the
rendered HTML.
Comprehensive Link Extraction: Parse the entire HTML content (from the JavaScript-
rendered page) to identify and extract all <a> (anchor) tags.
Filter these links to identify internal links (links within the same domain as the
article's final URL).
Clean and resolve relative URLs to absolute URLs.
Store these extracted internal links for later association with categories.
Handle potential network request and headless browser automation exceptions (e.g.,
connection errors, timeouts, browser issues).
3. LLM Interaction (Multiple Invocations & Complex Output):
Real API Integration (Mandatory): You must integrate with a real LLM API.
Recommended: Use the Gemini API ( gemini-2.0-flash ) for text generation.
You will use the fetch call pattern provided in the environment.
API Key Handling: The API key should be loaded securely from an environment
variable (e.g., GEMINI_API_KEY ). Provide instructions on how to set this
environment variable. Do not hardcode the API key.
LLM Call 1: Multi-Category Identification:
Make an LLM call for detailed content categorization. Craft a detailed prompt that
instructs the LLM to analyze the main extracted article text and identify ALL
relevant categories from the following predefined list that are discussed in the
article. If a category is not present, it should not be included in the output.
About Us
Products & Services
Leadership/Team
Blog/News/Press Release
Contact/Support
Privacy/Legal
Careers/Jobs
Other (Use this only if significant content exists that doesn't fit the other
categories).
The LLM should return this information in a JSON array format, where each
element represents an identified category, with a placeholder for text :
[
{
"category_name": "Blog/News/Press Release",
"text": ""
},
{
"category_name": "Products & Services",
"text": ""
}
// ... potentially more categories
]
Ensure the prompt explicitly lists these categories for the LLM to choose from and
clearly asks for the corresponding text field (which Python will then populate).
Note: For efficiency and cost management, sending the entire
extracted_web_content to the LLM for this task is inefficient. The candidate
should determine how to send only the necessary portions or a highly
condensed representation for effective category identification.
LLM Call 2: Website Type Identification:
Make a separate LLM call to identify the general type of website based on the
overall extracted content.
The LLM should return the website type in JSON format:
{
"site_type": "news/blog/e-commerce/company
website/educational/forum/portfolio/other"
}
The site type should be one of: news , blog , e-commerce , company website ,
educational , forum , portfolio , other . Note: For efficiency and cost
management, the candidate should optimize the input content sent to the
LLM for website type identification.
Structured Response Parsing: Parse all LLM JSON responses. Implement robust
error handling for cases where the LLM's output is not valid JSON or doesn't conform to
the expected schemas.
Rate Limiting/Error Backoff: Implement a basic rate-limiting or exponential backoff
strategy for API calls to avoid hitting API limits, especially if processing many URLs.
4. Python Logic for Content Splitting, Link Association, & Text Population (Heuristic):
After receiving the LLM's identified categories and having the
extracted_web_content , the Python script must perform the following:
Content Splitting: For each category_name identified by the LLM, the Python
script must intelligently extract a specific text snippet from the
extracted_web_content that pertains only to that category. This requires careful
heuristic logic (e.g., identifying subheadings, sections, or paragraphs semantically
related to the category). This extracted snippet will populate the "text" field
within each category object in the final output.
Link Association: Implement a heuristic to associate internal links with the
identified categories. For each identified category_name , iterate through the
overall list of internal links. Check if the URL string of an internal link, or its visible
anchor text (if retrievable), contains keywords related to the category_name or
terms found within the category's extracted text snippet. Add the matching links to
the links array for that specific category in the final output. If no specific links can
be confidently associated, the links array for that category can be empty. This
heuristic should be acknowledged in the [Link] .
5. Output & Reporting (Exact User-Specified JSON):
For each processed URL, construct a single JSON object that strictly adheres to the
requested output format:
{
"URL": "[Link]
"site_type": "news", // The determined website type
"extracted_web_content": "Full text content extracted from the web
page after JS rendering and filtering of boilerplate. This is the
complete clean text of the main article.",
"content": [
{"about-us": {"links": [], "text": ""}},
{"leadership": {"links": [], "text": ""}}
// ... dynamically include only the categories identified by the
LLM
// Each category will have its associated text (from Python's
content splitting heuristic) and links (from Python's link association
heuristic)
],
"errors": "..." // Only if errors occurred
}
Print this complete JSON object for each processed URL to the console in a readable
(e.g., pretty-printed) format.
Additionally, save a list of these complete JSON objects for all processed URLs to a
single output JSON file.
Deliverables
A single Python script ( [Link] ).
Extensive and clear comments throughout the code, explaining every major function, class,
and complex logic block, especially the LLM prompting, the content splitting, and the link
association logic.
A [Link] file listing all Python dependencies (e.g., for headless browser
automation, web parsing, and LLM interaction).
A comprehensive [Link] file detailing:
How to install dependencies.
How to set up the headless browser environment (e.g., installing a browser and its
driver).
How to set up the GEMINI_API_KEY environment variable.
How to run the script (with both hardcoded URLs and file input examples).
Clear explanation of the heuristic used for content splitting and link association, along
with their potential limitations.
Cost Consideration: The user will be responsible for managing and optimizing LLM
API usage to ensure minimal cost. Be mindful that multiple LLM calls per URL and
processing large amounts of text can incur significant costs.
Any other known limitations or assumptions.
Example Usage (Expected Output Structure - Console &
File)
[
{
"URL": "[Link]
deepmind-ai-gemini-gpt-4-openai",
"site_type": "news",
"extracted_web_content": "Google's DeepMind division is set to unveil
Gemini, its next-generation AI model, designed to compete directly with
OpenAI's GPT-4. This marks a significant development in the rapidly evolving
landscape of artificial intelligence research and deployment. The article
then goes into detail about Gemini's capabilities, its multimodal nature,
and the competitive landscape with other major AI players. It discusses the
challenges of AI development and the ethical considerations involved...",
"content": [
{
"Blog/News/Press Release": {
"links": [
"[Link]
"[Link]
],
"text": "Google's DeepMind division is set to unveil Gemini, its
next-generation AI model, designed to compete directly with OpenAI's GPT-4.
This marks a significant development in the rapidly evolving landscape of
artificial intelligence research and deployment."
}
}
// Note: Only categories identified by LLM and processed will be
present
],
"errors": null
},
{
"URL": "[Link]
[Link]",
"site_type": "news",
"extracted_web_content": "Israeli forces have initiated a ground
operation within the Gaza Strip, intensifying their military campaign. This
action marks a new phase in the protracted conflict, with significant
implications for the region. The article proceeds to describe the details of
the military movements, humanitarian concerns, and international reactions.
It covers historical context and potential future scenarios...",
"content": [
{
"Blog/News/Press Release": {
"links": [
"[Link]
"[Link]
[Link]"
],
"text": "Israeli forces have initiated a ground operation within
the Gaza Strip, intensifying their military campaign. This action marks a
new phase in the protracted conflict, with significant implications for the
region."
}
}
],
"errors": null
},
{
"URL": "[Link]
"site_type": "company website",
"extracted_web_content": "Kelp Global is a leading provider of
innovative solutions in the XYZ sector. Our mission is to empower businesses
with cutting-edge technology. Learn more about our products and services,
including AI-powered analytics and cloud integration. Meet our leadership
team: Jane Doe, CEO; John Smith, CTO. We are committed to sustainability and
client success. Contact us at info@[Link].",
"content": [
{
"About Us": {
"links": ["[Link]
"text": "Kelp Global is a leading provider of innovative solutions
in the XYZ sector. Our mission is to empower businesses with cutting-edge
technology."
}
},
{
"Products & Services": {
"links": ["[Link]
"[Link]
"text": "Learn more about our products and services, including AI-
powered analytics and cloud integration."
}
},
{
"Leadership/Team": {
"links": ["[Link]
"text": "Meet our leadership team: Jane Doe, CEO; John Smith,
CTO."
}
},
{
"Contact/Support": {
"links": ["[Link]
"text": "Contact us at info@[Link]."
}
}
],
"errors": null
},
{
"URL": "[Link]
"site_type": "other",
"extracted_web_content": "",
"content": [],
"errors": "Failed to fetch URL: Error: Unable to load page (e.g., DNS
error, connection refused, or no content after JS render)."
}
]
Evaluation Criteria
Strict Adherence to Output Format: Is the final JSON output exactly as specified,
including dynamic inclusion of categories, correct nesting, the site_type field, and the
extracted_web_content field?
Code Correctness & Robustness: Does the script execute flawlessly, even with varying
inputs and network conditions? Does it handle errors gracefully without crashing, providing
informative error messages that are reflected in the output JSON?
Web Content Acquisition (JS Rendering & Filtering):
Does the script successfully acquire content from JavaScript-rendered pages?
Is the extracted main article content demonstrably free from ads, cookie banners,
navigation, and other boilerplate?
Are URL redirects handled correctly, and is the final URL reported?
Comprehensive Link Extraction: Are internal links accurately extracted from the rendered
HTML and resolved?
LLM API Integration (Complex & Multiple Invocations):
Are all LLM API calls (for categories/names, and site type) correctly implemented with
distinct prompts?
Is the API key handled securely?
Is the prompt engineering for multi-category identification and site type effective in
consistently getting the desired structured JSON?
Structured Output & Parsing: Does the script consistently retrieve and correctly parse the
complex JSON output from all LLM invocations? Is robust error handling for malformed
JSON present?
Heuristic Content Splitting & Link Association: Is the Python logic for splitting
extracted_web_content into category-specific text and associating links implemented
effectively? Is the heuristic reasonable and its limitations acknowledged?
Concurrency Implementation: Are Python's concurrency mechanisms used effectively to
parallelize the tasks, demonstrating performance benefits? Is the worker limit respected?
Code Quality & Modularity: Is the code exceptionally clean, modular (well-defined
functions/classes), readable, and thoroughly commented, especially for the complex LLM,
headless browser, content splitting, and link logic? Adherence to PEP 8 standards is crucial.
Error Reporting & Logging: Is the error reporting comprehensive, informative, and easy to
debug from both console output and the final JSON structure?
Documentation: Is the [Link] complete, accurate, and easy to follow for setup and
execution, including the headless browser setup, the explanation of the content splitting and
link association heuristics, and the cost consideration?
This assignment is designed to be challenging, requiring a deep understanding of Python, web
interaction, LLMs, and structured data processing. Good luck!