import requests
from bs4 import BeautifulSoup
resp = requests.get("https://example-shop.test/reviews", timeout=15)soup = BeautifulSoup(resp.text,"html.parser")items = soup.select("div.quote")records =[]for item in items: records.append({"author": item.select_one("small.author").get_text(strip=True),"text": item.select_one("span.text").get_text(strip=True),"tags":[t.get_text(strip=True)for t in item.select("div.tags a.tag")],})print(f"status={resp.status_code} records_found={len(records)}")
Run against the fixture, this printed status=200 records_found=2 and correctly extracted both records' author, text, and tag list. Nothing in this script retries a failed request, follows a "next page" link, or runs a second page concurrently — you would add that logic by hand, one while loop and one requests.get() at a time.
Scrapy 实际做什么
Scrapy's PyPI listing describes it as "a high-level Web Crawling and Web Scraping framework." Rather than a library you call from a script, Scrapy is a project you scaffold with scrapy startproject, inside which you define spiders (classes that describe which URLs to start from and how to parse each response) and let Scrapy's engine handle scheduling, retries, and concurrency across all of them. The official documentation covers version 2.18.0, distributed under the BSD-3-Clause license shown on the project's GitHub repository, and requires Python 3.10 or newer.
The functional equivalent of the BeautifulSoup script above, expressed as a Scrapy spider using CSS selectors directly on the response object, needs no separate HTTP client call and no manual result list:
import scrapy
classQuotesSpider(scrapy.Spider): name ="quotes" start_urls =["https://example-shop.test/reviews"]defparse(self, response):for item in response.css("div.quote"):yield{"author": item.css("small.author::text").get(),"text": item.css("span.text::text").get(),"tags": item.css("div.tags a.tag::text").getall(),}
Run with scrapy crawl quotes -o output.json against the same local fixture used for the BeautifulSoup example above, this spider produced a JSON file with both records, matching the BeautifulSoup script's output field-for-field. That parity is the point: for extracting data from one already-known page, the two tools land on the same result through different amounts of surrounding scaffolding.
Where Scrapy pulls ahead is everything the single-page example doesn't show. response.follow() turns a link on the current page into a new scheduled request without you writing a queue. Item Pipelines post-process and validate each yielded record (deduplicating, writing to a database, or dropping incomplete items) before it reaches the output file. Downloader and Spider middleware let you rotate user agents, retry failed requests, or route specific requests through a proxy without touching spider logic. Feed exports write directly to JSON, CSV, or XML, locally or to remote storage, from a single -o flag.