现代 Scrapy 开发者指南(第 3 部分):使用 Web Scraping Co-pilot 自动生成页面对象
I’m ready to translate the article for you, but I’ll need the text you’d like translated. Could you please paste the content (excluding the source line you’ve already provided) here? Once I have the article text, I’ll translate it into Simplified Chinese while preserving the formatting, markdown, and code blocks.
先决条件与设置
本教程假设您已具备以下条件:
- 已完成第 1 部分(请参阅上面的链接)。
- 已安装 Visual Studio Code。
- 已安装 Web Scraping Co‑pilot 扩展(我们将在此后进行安装)。
第一步:Installing Web Scraping Co‑pilot
-
打开 VS Code 并前往 Extensions 选项卡。
-
搜索 Web Scraping Co‑pilot(由 Zyte 发布)并进行安装。
-
安装后你会在侧边栏看到一个新图标。点击它,扩展会自动检测你的 Scrapy 项目。
-
如有提示,请允许它安装一些依赖(例如
pytest)。这可确保你的环境已准备好用于 AI 驱动的生成。
第2步:自动生成我们的 BookItem
我们将从第 1 部分的 spider 开始,让 Co‑pilot 为 BookItem 创建一个页面对象,添加比第 2 部分更多的字段。
-
打开 Co‑pilot 聊天窗口。
-
选择 “Web Scraping”。
-
输入类似下面的提示:
Create a page object for the item BookItem using the sample URL https://books.toscrape.com/catalogue/the-host_979/index.html
Co‑pilot 将会:
- 检查你的项目——确认已安装
scrapy‑poet和pytest(如果未安装会提供添加)。 - 添加
scrapy‑poet设置——自动在settings.py中插入ADDONS和SCRAPY_POET_DISCOVER条目。 - 创建
items.py——生成一个新的BookItem类,包含它在页面上能发现的所有字段。
# tutorial/items.py (Auto‑Generated!)
import attrs
@attrs.define
class BookItem:
"""
The structured data we extract from a book *detail* page.
"""
name: str
price: str
url: str
availability: str # str:
return self.response.css("h1::text").get()
@field
def price(self) -> str:
return self.response.css("p.price_color::text").get()
@field
def url(self) -> str:
return self.response.url
@field
def availability(self) -> str:
# The second element contains the actual text
return self.response.css("p.availability::text").getall()[1].strip()
@field
def number_of_reviews(self) -> int:
return int(self.response.css("table tr:last-child td::text").get())
@field
def upc(self) -> str:
return self.response.css("table tr:first-child td::text").get()
大约 30 秒后,Co‑pilot 已完成我们在第 2 部分手动完成的所有工作——并且还添加了额外的字段。
第 3 步:运行 AI‑生成的测试
Co‑pilot 也为你编写了单元测试。tests 文件夹中现在包含 test_bookstoscrape_com.py。
通过 Co‑pilot UI(“Run Tests”)或在终端运行测试:
$ pytest
=================== test session starts ===================
...
tests/test_bookstoscrape_com.py::test_book_detail[book_0] PASSED
tests/test_bookstoscrape_com.py::test_book_detail[book_1] PASSED
...
=================== 8 passed in 0.10s ====================
你的解析逻辑已被完整测试,而且你没有编写任何测试代码。
第4步:重构爬虫(简易方式)
现在更新 tutorial/spiders/books.py 以使用新架构,就像我们在第 2 部分所做的那样。
# tutorial/spiders/books.py
import scrapy
# Import our new, auto‑generated Item class
from tutorial.items import BookItem
class BooksSpider(scrapy.Spider):
name = "books"
# ... (rest of spider from Part 1) ...
async def parse_listpage(self, response):
product_urls = response.css("article.product_pod h3 a::attr(href)").getall()
for url in product_urls:
# We just tell Scrapy to call parse_book
yield response.follow(url, callback=self.parse_book)
async def parse_book(self, response):
# Let the Page Object do the heavy lifting
page = BookDetailPage(response)
item = await page.to_item()
yield item
有了自动生成的 BookDetailPage 处理所有解析,爬虫变得极其简洁。
🎉 就是这样!
在短短几分钟内,Web Scraping Co‑pilot 已经:
- 创建了包含所有相关字段的
BookItem模式。 - 生成了功能完整的页面对象(
BookDetailPage)。 - 生成了夹具和全面的单元测试。
- 将爬虫代码简化为干净、支持异步的实现。
现在你可以专注于爬取策略、数据管道和扩展——让 AI 处理重复的样板代码。祝爬取愉快!
t_page_url = response.css("li.next a::attr(href)").get()
if next_page_url:
yield response.follow(next_page_url, callback=self.parse_listpage)
# We ask for the BookItem, and scrapy‑poet does the rest!
async def parse_book(self, response, book: BookItem):
yield book
第5步:自动生成我们的 BookListPage
我们可以对列表页重复完全相同的过程,以完成重构。
提示 Co‑pilot:
Create a page object for the list item BookListPage using the sample URL
结果
- Co‑pilot 在
items.py中创建了BookListPage条目。 - 它在
bookstoscrape_com.py中创建了BookListPageObject,并为book_urls和next_page_url添加了解析器。 - 它编写并通过了测试。
现在我们可以最后一次更新爬虫,使其 完全 架构化。
# tutorial/spiders/books.py (FINAL VERSION)
import scrapy
from tutorial.items import BookItem, BookListPage # Import both
class BooksSpider(scrapy.Spider):
# ... (name, allowed_domains, url) ...
async def start(self):
yield scrapy.Request(self.url, callback=self.parse_listpage)
# 我们现在请求 BookListPage 条目!
async def parse_listpage(self, response, page: BookListPage):
# 所有解析逻辑已从爬虫中移除。
for url in page.book_urls:
yield response.follow(url, callback=self.parse_book)
if page.next_page_url:
yield response.follow(page.next_page_url, callback=self.parse_listpage)
async def parse_book(self, response, book: BookItem):
yield book
我们的爬虫现在只是一个 爬取器。它没有任何解析逻辑。所有寻找选择器和编写解析器的繁重工作都已由 Co‑pilot 自动完成。
结论:“混合开发者”
Web Scraping Co‑pilot 并不会取代你。它 加速 你的工作。它会自动化 90 % 的“繁琐工作”(寻找选择器、编写样板代码、创建测试),让你能够专注于那关键的 10 %:爬取逻辑、策略以及处理复杂站点。
这就是我们——Scrapy 维护者——专业构建爬虫的方式。
接下来怎么办?加入社区
💬 在 Discord 上交流 – 在 Scrapy 代码上卡住了?在我们的 Discord 中向维护者和 5k+ 开发者求助。
▶️ 在 YouTube 上观看 – 本文基于我们的视频!在频道上观看完整演示。
📩 了解更多 – 想要获取更多内容?在第 2 部分我们将介绍 Scrapy Items 和 Pipelines。订阅 Extract 新闻通讯,别错过。
