VMware ESXi and vSphere Cluster Management
Bootstrapping a Python Web Crawler
Learn how to initialize a file-based Python web crawler by creating project storage, seeding URL state, and loading queue and crawled sets.
Before a crawler downloads a page, it needs a known starting state. Bootstrapping, or boot, is the startup operation that establishes the folders, files, and in-memory collections required for crawling.
A boot routine does not download HTML, parse links, or discover new URLs. It prepares the crawler so a later crawling operation can safely process a URL from the initialized queue.
What crawler bootstrapping does
A file-based crawler normally stores its progress in two places:
- Persistent storage: files that survive when the program stops.
- In-memory state: Python collections used while the program is running.
The startup routine should perform these operations in order:
- Create a project directory for this crawl.
- Create or preserve the queue and crawled state files.
- Seed the queue with the base URL when the project is new.
- Load both files into Python sets.
- Leave the crawler ready for the next stage: fetching a page from the queue.
Core crawler terms
| Term | Meaning |
|---|---|
| Spider class | The class that holds crawler configuration and state, including URL collections and file locations. |
| Project name | The configured identifier for one crawl project and its output folder. |
| Project directory | A folder dedicated to the data and state of one crawler project. |
| Base URL | The initial homepage or starting address from which the crawler begins discovery. |
| Queue file | A persistent text file containing URLs that remain to be crawled. |
| Crawled file | A persistent text file containing URLs that have already been processed. |
| URL queue | The in-memory collection of pending URLs loaded from the queue file. |
| Crawled set | The in-memory collection of completed URLs loaded from the crawled file. |
Class-level crawler configuration
The Spider class can keep configuration and state as class attributes. This is suitable for a simple crawler that operates on one project at a time.
The important configuration values are:
project_name: identifies the crawl directory.base_url: supplies the first URL for a new crawl.queue_file: points to the persistent pending-URL file.crawled_file: points to the persistent completed-URL file.
The project name determines the directory, and the directory determines where the state files live. For example, a project named example-site can use example-site/queue.txt and example-site/crawled.txt.
Helper functions for project storage
The boot method is easier to understand when directory and file operations are placed in helper functions. The required helpers are:
create_project_dir(project_name): creates the project folder.create_data_files(project_name, base_url): creates state files and seeds a new queue.file_to_set(file_path): reads one URL per line into a Python set.
Creating the project directory
Use exist_ok=True so starting the crawler again does not fail when the directory already exists.
import os
def create_project_dir(project_name):
os.makedirs(project_name, exist_ok=True)
Creating or preserving state files
The queue file and crawled file should be created only when they do not exist. The queue is seeded with the base URL only during first-time setup. Opening an existing file with write mode would erase saved progress, so this code uses existence checks.
def create_data_files(project_name, base_url):
queue_file = os.path.join(project_name, "queue.txt")
crawled_file = os.path.join(project_name, "crawled.txt")
if not os.path.exists(queue_file):
with open(queue_file, "w", encoding="utf-8") as file:
file.write(base_url + "\n")
if not os.path.exists(crawled_file):
open(crawled_file, "w", encoding="utf-8").close()
This function is idempotent: running it repeatedly produces the same valid storage state without discarding existing URLs.
Loading a file into a set
The file_to_set helper reads line-based URL storage. strip() removes the line ending and surrounding whitespace, while the set automatically removes duplicate entries.
def file_to_set(file_path):
with open(file_path, "r", encoding="utf-8") as file:
return {
line.strip()
for line in file
if line.strip()
}
Sets are appropriate for crawler state because membership testing is efficient and duplicate URLs are represented only once. For example, url in Spider.crawled can determine whether a URL has already been processed.
The Spider boot method
A static method is a method attached to a class that can be called without constructing an object instance. Marking the startup routine with @staticmethod communicates that booting uses class-level configuration rather than instance-specific data.
import os
class Spider:
project_name = "example-site"
base_url = "https://example.com/"
queue_file = os.path.join(project_name, "queue.txt")
crawled_file = os.path.join(project_name, "crawled.txt")
queue = set()
crawled = set()
@staticmethod
def boot():
create_project_dir(Spider.project_name)
create_data_files(Spider.project_name, Spider.base_url)
Spider.queue = file_to_set(Spider.queue_file)
Spider.crawled = file_to_set(Spider.crawled_file)
The method follows the required sequence:
create_project_dirmakes sure the project folder exists.create_data_filescreates missing files and writes the base URL for a new project.file_to_setloads pending URLs intoSpider.queue.file_to_setloads completed URLs intoSpider.crawled.
Calling boot during startup
Call the static method before calling any page-crawling method.
if __name__ == "__main__":
Spider.boot()
print("Pending URLs:", Spider.queue)
print("Completed URLs:", Spider.crawled)
# The next stage can now crawl a URL from Spider.queue.
Because boot is static, both Spider.boot() and an instance-free startup design are possible. No Spider() object is required for this class-level version.
Crawler startup sequence
| Step | Operation | Input | Output or State Change |
|---|---|---|---|
| 1 | Create project directory | project_name | The dedicated project folder exists. |
| 2 | Create or preserve state files | Project name and file names | Queue and crawled files exist without overwriting saved data. |
| 3 | Seed initial URL for a new project | base_url | The base URL is written as a line in the new queue file. |
| 4 | Load pending URLs into queue set | Queue file | Spider.queue contains pending URLs. |
| 5 | Load completed URLs into crawled set | Crawled file | Spider.crawled contains processed URLs. |
How the data flows
For a new project, the base URL progresses through three representations:
- Configuration:
Spider.base_urlcontainshttps://example.com/. - Persistent state:
create_data_fileswrites that URL toexample-site/queue.txt. - Runtime state:
file_to_setreads the file and assigns the URL toSpider.queue.
The crawled file follows the same storage pattern, except it starts empty and is later updated as pages are processed.
| State Item | Persistent Representation | In-Memory Representation | Purpose |
|---|---|---|---|
| Pending URLs | queue.txt | Spider.queue, a set | Tracks URLs waiting to be crawled. |
| Completed URLs | crawled.txt | Spider.crawled, a set | Prevents already processed URLs from being crawled again. |
| Crawler project identity | Directory named from project_name | Spider.project_name | Separates one crawl's data from another crawl's data. |
| Starting URL | First line of a new queue file | Member of Spider.queue | Provides the first page for discovery. |
First startup example
With this configuration:
Spider.project_name = "example-site"
Spider.base_url = "https://example.com/"
the first call to Spider.boot() produces the following logical result:
- An
example-sitedirectory is created. example-site/queue.txtcontainshttps://example.com/.example-site/crawled.txtexists and is empty.Spider.queuecontains the starting URL.Spider.crawledis an empty set.
Restarting an existing crawler
Suppose the crawler has already discovered several URLs and recorded completed pages. On the next startup, create_project_dir sees the existing folder, and create_data_files leaves both files unchanged.
The boot method then restores the saved state:
- Previously pending URLs return to
Spider.queue. - Previously visited URLs return to
Spider.crawled. - The base URL is not added again merely because the crawler restarted.
- Saved progress is not discarded.
Duplicate URL protection
If a queue file contains the same URL more than once, loading it into a set creates one in-memory entry:
# queue.txt
https://example.com/about
https://example.com/about
https://example.com/contact
queue = file_to_set("queue.txt")
print(queue)
# {'https://example.com/about', 'https://example.com/contact'}
Sets do not by themselves implement the complete crawl algorithm, but they provide the foundation for checks such as:
if url not in Spider.crawled:
Spider.queue.add(url)
A crawler should also keep pending and completed state distinct. A URL in the queue is waiting; a URL in the crawled set has already been processed.
Booting versus crawling
Boot code and crawl code have separate responsibilities:
| Booting | Crawling |
|---|---|
| Creates directories and state files. | Downloads a page. |
| Seeds the initial queue for a new project. | Parses HTML. |
| Restores queue and crawled sets. | Discovers and normalizes links. |
| Does not fetch a page. | Moves URLs between pending and completed state. |
After boot completes, the next stage is to select a URL from the initialized queue, fetch its page, and update persistent state as crawling proceeds.
Troubleshooting startup problems
The queue is empty for a new project
- Check that
base_urlis passed tocreate_data_files. - Confirm that a newly created queue file is seeded with the base URL.
- Make sure the queue file is initialized before
file_to_setreads it. - Reload
Spider.queueafter file initialization.
A restart loses crawl progress
- Do not open existing state files in write mode during every startup.
- Keep the project name and file names stable between runs.
- Load both the queue file and crawled file during boot.
The same URL is crawled repeatedly
- Use sets for the in-memory queue and crawled collections.
- Restore completed URLs from the crawled file.
- Check membership before adding or processing a URL.
- Keep queue and crawled files separate.
The boot method cannot find a helper
- Import
create_project_dir,create_data_files, andfile_to_setinto the module containingSpider. - Check that function names match their definitions exactly.
- Confirm that the helpers are defined in an accessible module or scope.
- Verify that the arguments passed by
bootmatch the helper signatures.
Exam-relevant checklist
- Booting prepares crawler state before any page is fetched.
- The project name identifies the project directory.
- The base URL seeds a new queue file.
- Existing queue and crawled files must be preserved.
file_to_setconverts line-based files into sets.Spider.queuestores pending URLs in memory.Spider.crawledstores completed URLs in memory.- A static
bootmethod can initialize class-level crawler configuration without an instance. - The required order is directory, files, then in-memory sets.
- Booting prepares the next operation; it does not download or parse pages.
Once this startup process is reliable, the crawler has a durable project location, initialized state files, and restored URL collections. Page-fetching and link-discovery logic can now operate on that prepared state.
Continue with crawler bootstrapping concepts when reviewing the complete initialization flow.