Turn Topics into RSS with Desearch

Build a Python tool that turns search results into a dated RSS feed.

Introduction

30 Second Summary

The stories you care about are often scattered across different websites. Keeping up means repeating the same search whenever you want an update.

In this project, you will turn any topic into a live RSS feed using Python and the Desearch API. You will also serve the feed from a local endpoint that reports each refresh's cost.

What You'll Build

You'll watch a fresh RSS feed appear in your browser for a topic you choose.

By the end of this project, you'll have:

  • A topic-powered feed generator that writes dated search results to feed.xml in newest-first order.
  • A duplicate-free feed that removes repeated links before they reach your RSS reader.
  • A cost-aware cache that shows cache_hit=True with zero cost when you repeat the same search.
  • A live local endpoint at /feed?topic=... that creates a fresh feed for any topic you enter.
  • Secret Mission: An optional challenge to push your skills further.

Are there any prerequisites?

You'll need Python 3.10 or newer plus a Desearch API key.

Uncached searches use paid credit, so plan to fund your Desearch account with a small amount.

Before We Start

Your topic feed needs a supported Python runtime before it can search for results or write XML. It also needs the starter script with its mocked tests.

In this step, you will confirm Python 3.10 or newer is available. You will also open the supplied project workspace without configuring a Desearch API key or making a network request.

In this step, get ready to:
  • Open a terminal and confirm your Python version.
  • Make the supplied RSS feed generator workspace available.
  • Confirm the workspace has no generated feed or running server.
Check your Python version

The generator uses only the Python standard library. A supported Python runtime gives you everything the project needs without installing packages.

  • Press Cmd+Space on macOS or the Windows key on Windows to open your search bar.
  • Type Terminal on macOS or PowerShell on Windows.
  • Press Enter to open the terminal.
  • Choose your platform below to check the installed Python version.

macOS

  • Print your installed Python version by running this command:
python3 --version

What does this command do?

The python3 command selects Python 3. The version option prints the interpreter version without starting a Python session.

Windows

  • Print your installed Python version by running this command in PowerShell:
py -3 --version

What does this command do?

The py -3 command selects an installed Python 3 interpreter. The version option prints its version without starting a Python session.

Compare the printed version with the project minimum of 3.10.

✔️ I see version 3.10 or higher

Your Python runtime is ready for the RSS generator. Continue to the starter workspace below.

ⓧ I see an older version

Your current interpreter is below the project minimum. The official Python download page provides a supported installer for your operating system.

  • Visit the official Python download page.
  • Install Python 3.10 or newer using the installer for your operating system.
  • Return to the platform tab above after the installation finishes.
  • Run the version check again.

ⓧ Command not found

Your terminal cannot currently find a Python 3 interpreter. Installing Python from its official download page adds the runtime this project needs.

  • Visit the official Python download page.
  • Install Python 3.10 or newer using the installer for your operating system.
  • Close your terminal after the installation finishes.
  • Open a new terminal using your operating system search bar.
  • Return to the platform tab above.
  • Run the version check again.

Still unable to run Python?

A newly installed runtime may only become available in a fresh terminal session. Close every terminal window before opening a new one.

If the check still fails, help me troubleshoot my Python installation.

Open the starter workspace

The supplied project workspace contains the RSS feed generator script and mocked unit tests. The tests replace the live Desearch request with controlled data so the first test run can stay offline.

  • Load the starter workspace supplied with this project in your editor.
  • Expand the project directory in the editor's file panel.
  • Locate the Python script that generates the RSS feed.
  • Locate the mocked unit tests in the same project directory.

Why start with mocked tests?

Mocked tests check the generator with predictable search results. They do not need the DESEARCH_API_KEY environment variable or a billed API call.

This gives you a clean way to prove the starter project works before credentials enter the picture.

Confirm the clean starting state

Before you check the workspace, do you expect to find a generated feed or an active local server at this point?

  • Check the project file panel for feed.xml.
  • Confirm feed.xml is absent.
  • Return to the terminal you opened earlier.
  • Confirm the terminal is waiting for your next command.

You should see the generator script and mocked unit tests in the project directory. You should not see feed.xml or a running local server.

✔️ Awesome, I've got everything!

Your supported Python runtime and starter workspace are ready. You have kept the initial state clean for the first offline test run.

ⓧ I'd like to double check the full code

RSS feed generator script and mocked unit tests are available in the project directory. No generated feed or running server exists.

Can't find the starter files?

Make sure you loaded the starter workspace supplied with this project. The file panel should show both the generator script and its mocked unit tests.

If the workspace still looks empty, help me locate the supplied project files.

Your local foundation is ready. Next up, you will configure your Desearch API key and run the mocked tests without making a network request.

Configure API Access and Run Tests

Your RSS generator needs permission to search the Desearch API. An API key gives it that permission.

This step keeps the key in your current shell so your project files stay free of secrets. You will then prove the supplied test suite passes entirely offline.

In this step, get ready to:
  • Create a Desearch API key and store it securely.
  • Export the key as DESEARCH_API_KEY in your current shell.
  • Run the mocked unit tests without making network requests.
Create a Desearch API key

The Desearch Console creates credentials for your account. The full key may only be visible when you create it.

Keep Your Key Private

Your API key authorizes requests against your Desearch account. Treat it like a password.

The mocked tests in this step stay offline. Your API balance remains untouched.

  • Open the Desearch Console in your browser.
  • Sign up or log in.
  • Open the API Keys section.
  • Click Generate API Key.
  • Enter local-dev as the key name.
  • Copy the generated key immediately.
  • Store the copied key in a password manager.

Good progress. Your Desearch credential is ready for the shell without touching your project files.

Export the key in your shell

An environment variable gives programs a value from the current shell session. DESEARCH_API_KEY is the only environment variable the RSS generator reads.

  • Switch back to the terminal from earlier.
  • Export your copied key by replacing your-key-here in this command:
export DESEARCH_API_KEY='your-key-here'

What Does This Command Do?

  • The export command makes the key available to programs launched from this shell.
  • The DESEARCH_API_KEY name matches the value expected by the RSS generator.
  • The single quotes keep the credential together as one value.
  • Keep this terminal session open so the exported value remains available.

That is the sensitive setup complete. The current shell can now supply your credential when the RSS generator needs it.

Key Unavailable Later?

  • Run the export command again in the same terminal used for the project.
  • Confirm that you replaced your-key-here with the complete copied key.

Ask for help without sharing the key itself: help me check why DESEARCH_API_KEY is unavailable in my current shell.

Run the mocked unit tests

The tests replace the upstream HTTP layer with controlled responses. They exercise the generator and request handlers without leaving your computer.

Before you run the tests, do you expect your API balance or feed.xml to change?

  • Run the supplied tests from the project directory by running:
python3 -m unittest discover -s tests

What Does This Command Do?

  • The python3 -m unittest portion starts the standard library test runner.
  • The discover -s tests portion finds the supplied tests inside the test directory.
  • The project mocks intercept the upstream API calls with in-memory responses.

You should see the test summary end with OK. This confirms the supplied code passes its offline checks.

That is your clean baseline: every test passes without a network request. Your API balance remains unchanged.

The test run leaves feed.xml uncreated. No local server is running.

Tests Not Passing?

  • Return to the project directory that contains the supplied test directory.
  • Run the tests with Python 3.10 or newer.
  • Compare the test command with the command above for missing spaces.

For targeted support, help me diagnose why the mocked unit tests are not passing.

Your API access is configured safely. Your offline tests also pass. Next, you will run the RSS generator on a topic and create feed.xml.

Generate Your RSS Feed

Your Desearch API key is ready. The mocked tests proved the generator's local logic without spending any API credit.

A mocked response cannot fill your feed with live results about a topic you care about. This step sends one live request through the Desearch API.

The generator keeps dated results from that request. It turns them into an RSS file you can inspect.

In this step, get ready to:
  • Choose a focused topic for your feed.
  • Generate feed.xml from live Desearch results.
  • Confirm the new feed file exists in your project directory.
Choose a topic for your feed

A focused topic gives the search a clear target. Pick something you would genuinely want to follow through regular feed updates.

  • Record your chosen topic here: your RSS topic.
Create feed.xml

This Run Uses API Credit

This live search uses API credit. You make one request in this step, so the spend stays contained.

The script prints the exact charge after the request finishes. You will examine that report in the next step.

Before you run this, do you expect the RSS XML to stay in the terminal or appear in a file?

  • Send your saved topic to the generator from the current terminal by running this command:
python3 topic_rss.py '[[RSS_TOPIC="your RSS topic"]]' -o feed.xml

What Does This Command Do?

  • The python3 topic_rss.py command starts the RSS generator.
  • Your chosen topic becomes the live Desearch query.
  • The -o feed.xml option writes the generated feed to feed.xml.
  • The generator drops undated pages. It removes duplicate URLs and titles before building the feed.

The command prints a short run report before returning to the prompt. The feed content is stored in feed.xml.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Finder (macOS) or File Explorer (Windows) to open your file browser.
  • Return to the project directory you used for the mocked test run.

You should see feed.xml listed inside the project directory. This confirms the live request produced a saved feed.

You have turned your chosen topic into a feed backed by live search results. Your project now has its first generated RSS file.

Cannot Find feed.xml?

  • Check the terminal output for a problem involving the API key, account funding, or network connection.
  • Confirm you are still using the terminal session where DESEARCH_API_KEY is exported.
  • Confirm your Desearch account has enough funding for one live request.

Help me diagnose why the RSS generator did not create feed.xml.

Your chosen topic now has a real RSS file. Next, you will inspect feed.xml to prove every item is dated and ordered newest first.

Check the Feed Items

Your Desearch search has already produced feed.xml for your chosen topic. This step checks whether that file behaves like a useful feed.

An RSS reader depends on dated entries. A clean feed presents the newest unique results first.

In this step, get ready to:
  • Inspect the RSS item structure in feed.xml.
  • Confirm that every item includes a publication date.
  • Verify a deduplicated newest-first result list.
Open the generated feed

The feed stores its data as XML. Every search result lives inside its own item block.

  • In Finder on macOS or File Explorer on Windows, navigate to the directory containing feed.xml plus the generator script.
  • Double-click feed.xml.

You should see the feed's XML structure. The result entries appear inside repeated <item> blocks.

How is the feed structured?

  • Each <item> block contains one search result.
  • The <pubDate> field records when that result was published.
  • The <title> field names the result.
  • The <link> field stores the result's destination.

Can't read the XML?

The collapsed tree can be fiddly because some browsers hide item details behind small disclosure controls.

  • Use the browser's expand controls to reveal the collapsed item blocks.
  • Reopen feed.xml in a plain-text editor if the structure remains hidden.

help me inspect an RSS XML file that appears collapsed or unreadable.

Check every date and its order

This generator keeps only dated search results. Your inspection confirms that every exported item carries the date an RSS reader needs.

  • Press Cmd+F on macOS or Ctrl+F on Windows to open the find bar.
  • Enter <item> in the find field.
  • Move through every matching item block.
  • Inspect each item block for a <pubDate> field.

Every <item> should contain one <pubDate> value. This confirms that undated search results stayed out of the feed.

Before you compare the sequence, do you think the dates will move toward newer or older results as you read downward?

  • Start with the <pubDate> inside the first <item> block.
  • Read each following publication date from top to bottom.
  • Compare each date with the date immediately above it.

You should see the newest publication date first. Each later item should have the same date or an older date.

That is a key quality check complete. Your feed now leads with the freshest results.

Confirm duplicate results are absent

Deduplication keeps one copy of each result in the feed. The generator catches repeats through normalized URL comparison.

Before this final check, do you expect any search result to appear twice?

  • Scan the <title> values from top to bottom.
  • Scan the <link> values from top to bottom.
  • Check that no result appears twice under the same title or destination.

You should find no repeated result titles or destination URLs.

What have you confirmed?

  • Every <item> includes a <pubDate> value.
  • The first item carries the newest publication date.
  • Every later item is no newer than the item above it.
  • No result title or destination repeats.

You have completed the careful quality check. Your RSS feed now contains dated results in newest-first order without duplicates.

Your feed contains public search results. Keep the terminal outside your checkpoint screenshot.

Your feed.xml is clean enough for a feed reader. Next, you will measure a refresh and see how caching changes its cost.

Verify Cost and Cache Behavior

You already proved that feed.xml contains dated results in newest-first order without duplicates. Now you need to understand what each refresh costs before you rely on the feed regularly.

The generator prints request metrics to stderr so every refresh has a visible record. Repeating the identical topic tests whether a cache can serve the result without another paid search.

In this step, get ready to:
  • Read the initial refresh cost from the generator's stderr report.
  • Repeat the exact generator request to confirm its cache behavior.
Read the initial refresh metrics

The first live request gives you a cost baseline. Its stderr report also records response time plus cache status.

  • Switch back to the terminal from your earlier feed generation.
  • Scroll to the output printed when you generated feed.xml.
  • Find the metrics line containing cost_usd.
  • Read the full metrics line to establish your baseline.

How to Read the Cost Line

  • cost_usd reports the refresh cost in US dollars.
  • latency_s reports how long the request took in seconds.
  • cache_hit reports whether the generator reused a saved result.

Refresh costs can vary. Treat the displayed cost_usd value as the source of truth for that request.

Repeat the identical topic request

A cached result can be reused when the generator receives the same topic request. Shell history restores the original command without retyping it.

A repeated live request can cost money if it bypasses the saved result. Restoring the exact command keeps the input unchanged.

  • Press the Up Arrow key in the terminal until the original generator command appears.
  • Confirm the restored command contains the same topic you used to produce feed.xml.

Before you rerun it, what do you think will happen to the cost when the topic matches a saved cache entry?

  • Press Enter to repeat the generator request.

You should see cache_hit=True in the new metrics line. The cost_usd value should be zero.

You have closed the cost loop. Your repeated feed refresh now uses the saved result without another search charge.

Your feed.xml file remains available after the repeat run.

Cache Still Missing?

  • Confirm the topic text in the repeated command matches the first request exactly.
  • Look for --no-cache in the restored command.
  • Remove --no-cache before repeating the normal cache check because this flag forces a billed call.

Help me diagnose why my repeated topic request is not producing a cache hit.

You can now measure each refresh. Next, you'll serve the RSS XML from a local endpoint.

Serve Feeds Locally

Your second run proved the cache can return your selected topic with zero refresh cost. The feed still lives in feed.xml, which only changes when you generate it again.

In this step, you start the script's local server. A browser request then turns your selected topic into live RSS XML at a reusable URL.

In this step, get ready to:
  • Start the script's local server on port 8000.
  • Open your selected topic as live RSS XML in your browser.
Prepare the feed endpoint

The local server keeps topic_rss.py active so it can respond whenever a feed URL is requested. The running process stays attached to your current terminal.

  • Launch the local server on port 8000 by running this command:
python3 topic_rss.py --serve --port 8000

What does this command do?

  • The --serve option tells topic_rss.py to answer feed requests through a local endpoint.
  • The --port 8000 option selects the local port that receives those requests.
  • The process occupies this terminal while the server is running.
  • Leave the terminal from earlier running while you test the feed.

That's the server running. Your script is ready to answer a feed request from your browser.

Does the server exit immediately?

  • Confirm the terminal is still in the project directory that contains topic_rss.py.
  • Confirm DESEARCH_API_KEY remains exported in this terminal session.
  • Stop any other local process that is already using port 8000.

Help me diagnose why the local RSS server exits as soon as I start it.

Open the live topic feed

The topic query parameter carries your selected topic in the feed URL. The server uses that value to produce the corresponding RSS response.

  • Store the exact topic you used earlier here: your-topic.
  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type the name of your web browser into the search bar.
  • Press Enter to open your browser.
  • Select the address bar.
  • Enter http://127.0.0.1:8000/feed?topic=bittensor as the local feed address.
  • Replace bittensor with your-topic.

Before you load the address, predict whether the browser shows a designed web page or raw XML.

  • Press Enter to request the live feed.

Your browser shows live RSS XML for your-topic. The feed items reflect your selected topic.

  • Scan the item dates from the top of the feed to the bottom.
  • Compare the visible titles for repeated entries.

Every item has a date. The dates run from newest to oldest.

You should not find repeated normalized URLs or titles. This confirms the live endpoint preserves the generator's filtering.

Why does the browser show XML?

An RSS reader consumes structured XML instead of a designed web page. The endpoint returns application/rss+xml so compatible clients recognize the response as a feed.

Your browser displays the feed source directly. That raw document is the live output an RSS reader subscribes to.

Does the feed fail to load?

  • Keep the terminal running the server open.
  • Check that the address begins with http://127.0.0.1:8000/feed?topic=.
  • Confirm your selected topic appears after the final equals sign.

Help me troubleshoot why my local RSS feed does not load in the browser.

Your selected topic now has a live local feed URL. Next, you'll test the blank-topic guard before adding the feed to an RSS reader.

Validate Requests and Subscribe

Your local server already serves dated results for your chosen topic. The final gap is proving that it handles incomplete requests cleanly.

You will send a blank topic to inspect its HTTP response. You will then add the valid local URL to an RSS reader.

In this step, get ready to:
  • Test how the local endpoint responds to a blank topic.
  • Subscribe to the valid local feed in an RSS reader.
Send a blank topic request

Request validation stops the server from running a search without a usable topic. An HTTP status code tells the client whether its input was accepted.

  • Switch back to the browser tab that shows your live feed from earlier.
  • Click the browser's address bar.
  • Edit the address so it ends with /feed.

Before you send this request, do you expect the endpoint to serve an empty feed or reject it? The next request tests your prediction.

  • Press Enter to send the blank-topic request.

You should see a page reporting an HTTP 400 response. This confirms the server rejects a missing topic before it tries to generate a feed.

That is the request guardrail working. Your endpoint now refuses an incomplete feed request.

Still seeing the live feed?

  • Check that the browser address ends with /feed.
  • Remove any topic query still present after /feed.
  • Reload the edited address once.

Ask for help if the blank request still returns feed items: help me check why my blank local feed request is not returning HTTP 400

Subscribe to the local feed

An RSS reader turns XML feed items into a readable list. A reader on this computer can reach the feed while your local server remains running.

  • Use your browser's back control to return to the valid live feed.

You should see the live RSS XML for your selected topic again.

  • Click the browser's address bar.
  • Record the full address here: your full local feed URL.
  • Leave the server terminal running.
  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your app search.
  • Type the name of your RSS reader into the search bar.
  • Press Enter to open the reader.
  • Choose the reader's control for adding a feed.
  • Paste your full local feed URL into the feed address field.

Before you confirm the subscription, do you expect the reader to accept a feed served from your computer? The subscription result tests your prediction.

  • Confirm the new subscription.

You should see a list of items from your selected topic in the reader. The item titles should match the content served by your local feed.

Your selected topic now appears in a reader you can return to whenever the local server is running.

Reader cannot load the feed?

  • Confirm that the local server terminal is still running.
  • Check that your recorded URL includes the selected topic after ?topic=.
  • Use a reader installed on the same computer if a browser-based reader cannot reach the local address.

Get help checking the local connection: help me connect my RSS reader to the local feed

Secret mission

Audit Your Feed Before Publishing

Review the five newest items in your existing RSS subscription. Judge whether they match your topic. Decide whether the feed is ready to share.

Clean Up Your Resources

Clean Up Your Resources

Your local RSS server has no hosting charge. Uncached Desearch searches can cost money, so choose whether to keep the project active, pause it, or delete it.

Cost warning

Desearch can charge for uncached refreshes. Cached refreshes report zero cost, but the price of a new search can vary.

Stop the local server when you finish using the feed. This prevents your RSS reader from triggering more refreshes through the local endpoint.

Resources you used:

  • Local RSS server running from the project directory.
  • Desearch API key exported as DESEARCH_API_KEY in the current terminal session.
  • Desearch API key stored in your Desearch account.
  • Local project directory containing the RSS feed generator script, mocked unit tests, topic cache, and feed.xml.
  • Local feed subscription saved in your RSS reader.

Keep everything running

No action is needed. Choose this option while you are actively using the generated feed or testing new topics.

  • Leave the local RSS server running while your reader needs access to the feed.
  • Keep the current terminal session open while the server needs access to DESEARCH_API_KEY.
  • Keep the project directory so that the script, mocked tests, cached topic, and feed.xml remain available.
  • Leave the local feed subscription in your RSS reader while the server is running.
  • Check the reported refresh cost before requesting an uncached topic.

Keep Refresh Costs Visible

Repeat requests for your cached topic report zero refresh cost. New topics can trigger another paid search.

Pause - I'll come back to this later

Stop the running process to free local resources. Your files, cached topic, API key, and reader subscription remain available for your return.

  • Switch back to the terminal running the local RSS server.
  • Press Ctrl+C to stop the server.
  • Close the terminal to clear DESEARCH_API_KEY from that session.
  • Keep the project directory so that feed.xml and the cached learner-selected topic remain available.
  • Leave the local feed subscription in your RSS reader for when you restart the server.

Your local feed stops refreshing while the server is offline. Restarting the project later makes the endpoint available again.

Delete - I don't want to use this again

Deleting the project directory and API key is permanent. You can recreate the feed later by setting up the project again.

  • Switch back to the terminal running the local RSS server.
  • Press Ctrl+C to stop the server.
  • Close the terminal to clear DESEARCH_API_KEY from that session.
  • Switch back to the RSS reader from earlier.
  • Select the local feed subscription.
  • Remove it using the reader's subscription removal control.

Your exported environment variable disappears with the terminal session. The API key itself remains valid until you remove it from your Desearch account.

  • Sign in to the Desearch account that issued your API key.
  • Open the page where that account manages API keys.
  • Delete the API key used for this project.

The project directory holds the generator, mocked tests, cached topic, and generated feed. Delete that directory to remove all local project artifacts together.

macOS

  • Search for this project's feed.xml in Finder.
  • Select the containing project directory.
  • Move the selected project directory to the Trash.
  • Empty the Trash to complete the deletion.

Windows

  • Search for this project's feed.xml in File Explorer.
  • Select the containing project directory.
  • Delete the selected project directory.
  • Empty the Recycle Bin to complete the deletion.

Nice Work!

Nice Work!

You made it! You built a Python generator that converts Desearch API search results into an RSS feed. Your local endpoint now serves that feed to an RSS reader.

You've learned how to:

  • Proved the feed logic with mocked unit tests that pass without network access. Generated a dated feed.xml file. Confirmed its deduplicated results run newest first.
  • Read the refresh cost from a live request. Repeated the same topic to prove the cache returns the result at zero refresh cost.
  • Served live XML from /feed?topic=... through a local RSS server. Confirmed /feed rejects a blank topic with an HTTP 400 response. Subscribed through an RSS reader to see the feed items appear.
  • Completed an optional Secret Mission to push your feed-building skills further.

Ready to quiz yourself?