Project 2: Scraping eBay
Due: Wednesday, October 21 at 11:59pm · Worth: 23 points (+1 extra credit; maximum 24/23)
ebay-dl.py is a command-line program that scrapes eBay search results. Given a search term, it downloads the first pages of results, extracts fields such as name, price, and shipping, and saves the listings as structured JSON.
Like the Markdown compiler, this program converts data from one format to another. The input is eBay’s HTML, and the output is JSON that another program can use.
An optional roughly two-hour pair-programming video builds most of the code and demonstrates debugging and writing doctests.
Start
Create an empty GitHub repository named ebay-scraper under your account, clone it, and do all project work inside it. In this repository, set up its Python environment, then install the two libraries:
$ python -m pip install requests beautifulsoup4Learning Objectives
Build the Scraper
Start with a scraper that can save one search, then use it to collect three searches someone else can reproduce.
The scraper. Create a Python file named ebay-dl.py. It should:
Note: Not every eBay listing has every field above. For a missing field, keep the associated key and set its value to
None.
Start with one page before adding the ten-page loop. Pass the search term in the _nkw query parameter and the page number in _pgn, for example https://www.ebay.com/sch/i.html?_nkw=garden+tools&_pgn=1. Set a browser-like User-Agent header and a timeout on each request, and pause between pages. Inspect both the HTTP status and the returned HTML: a successful HTTP response can still contain a robot check instead of listings. If you receive HTTP 403, HTTP 429, a robot check, or HTML without listing cards, stop live requests and use the practice pages below. An empty list does not establish that your extraction works.
Practice Pages When eBay Blocks Requests
Download practice-pages.zip into your repository and extract it:
$ python -m zipfile -e practice-pages.zip .The practice-pages folder contains page-1.html through page-10.html. These are artificial listings, with known prices, missing fields, and distinct items on every page. Open page-1.html in your browser and editor to inspect the listing structure.
Separate downloading a page from extracting its listings. Your extraction function should take an HTML string so you can give it either response.text or the contents of a saved file. Add an optional --pages-dir argument (the named-argument example shows how argparse handles flags): when supplied, read page-1.html through page-10.html from that folder as UTF-8 instead of making requests. When omitted, keep the normal ten-page requests download; Gradescope exercises that default interface with its own offline responses.
$ python ebay-dl.py "garden tools" --pages-dir practice-pagesThe practice output should contain 30 listings. The first trowel costs 1195 cents and ships free; the first planter costs 1250 or 1800 cents, with 425-cent shipping. The mystery-seed listings retain every key with None for missing values, which JSON writes as null. Check that names from page 10 appear too. Live eBay can change its HTML; keep support for this published practice structure when experimenting with other selectors.
Three saved searches. Run your ebay-dl.py file on three search terms of your choice, generating three different JSON files. At least one of these search terms must contain a space (for example, drill press, stuffed animal, or claremont mckenna). If live access is blocked, run each search with --pages-dir practice-pages and save the resulting practice output instead. The practice listings stay the same for every search term; the filename still comes from the supplied term. State in your README which outputs use artificial practice data and include the exact commands you ran. For an optional investigation, choose a budget and use the saved prices and shipping costs to compare which practice listings fit it. Keep that exploration separate from the required output schema.
A reproducible collection. Your GitHub repository must contain:
Grading Rubric
This project is worth 23 points. Gradescope checks each item separately and adds the points earned.
The three saved searches and README let someone else try your program. The points above come from running your submitted scraper and checking the JSON it produces.
Gradescope runs the scraper against ten instructor-owned HTML fixtures and replaces requests.get with an offline fake. That means everyone receives the same listings, eBay is not contacted during grading, and a temporary robot-check page cannot change your score. The tests check the command-line search term (4 points), requests for result pages 1 through 10 and their User-Agent (4 points), Beautiful Soup extraction (4 points), JSON schema and types (4 points), and evidence that every downloaded page contributed listings (7 points). The fixtures include multiple listings per page, missing fields, free shipping, and a price range, following the rules above. The saved search files and README are self-checks and do not change the 23-point rubric.
Extra Credit
- Modify
ebay-dl.pyso that it accepts a new command-line flag,--csv. Whenever this flag is specified, the output file should be saved in CSV format instead of JSON format. - Generate three CSV files in addition to the three JSON files, and include them in your repo.
- Update your
README.mdfile to include instructions and examples for using the--csvflag.
Automatic Grading
All 23 base points and the 1-point CSV bonus are automatic. The grader checks command-line behavior, so either sys.argv or argparse can earn the CLI points. Support python ebay-dl.py "search term" with one positional search term, or a single clearly named --search, --query, or --term option. Do not require subcommands for the graded interface. The grader substitutes ten local HTML pages for network responses. Saved searches and README examples remain practice; their historical provenance is not graded.
Submit
If you completed the CSV extra credit, add this file at the repository root:
# submission.toml
[features]
csv = trueThe CSV test runs only when you claim it.
Commit and sync ebay-dl.py, README.md, and the three JSON files. On Gradescope, choose GitHub and submit your ebay-scraper repository and the branch containing your commit.