爬虫
爬虫是定义如何抓取特定网站(或一组网站)的类,包括如何执行抓取(即跟踪链接)以及如何从其页面中提取结构化数据(即抓取 Item)。换句话说,爬虫是您定义特定网站(或在某些情况下是一组网站)爬取和解析页面的自定义行为的地方。
对于爬虫,抓取周期大致如下:
- 您首先生成抓取初始 URL 的请求,并指定一个回调函数,该函数将在从这些请求下载响应后调用。
- 要执行的第一个请求是通过迭代
start()方法获得的,该方法默认会为start_urls爬虫属性中的每个 URL 生成一个Request对象,并将parse方法设置为回调函数来处理每个Response。 - 在回调函数中,您解析响应(网页)并返回 item 对象、
Request对象或这些对象的可迭代对象。这些 Request 也将包含一个回调(可能是同一个),然后将由 Scrapy 下载,然后由指定的回调处理其响应。 - 在回调函数中,您解析页面内容,通常使用 Selectors(但您也可以使用 BeautifulSoup、lxml 或您喜欢的任何机制),并使用解析的数据生成 Item。
- 最后,从爬虫返回的 Item 通常会持久化到数据库(在某个 Item Pipeline 中)或 使用 Feed 导出 写入文件。
尽管此周期(或多或少)适用于任何类型的爬虫,但 Scrapy 中捆绑了不同类型的默认爬虫,用于不同的目的。我们将在此处讨论这些类型。
scrapy.Spider
class scrapy.spiders.Spider
class scrapy.Spider(*args: Any, **kwargs: Any)[source]
任何爬虫都必须继承的基类。
它提供了一个默认的 start() 实现,该实现根据 start_urls 类属性发送请求,并为每个响应调用 parse() 方法。
name
一个字符串,定义此爬虫的名称。爬虫名称是 Scrapy 定位(和实例化)爬虫的方式,因此它必须是唯一的。但是,没有什么能阻止您实例化同一爬虫的多个实例。这是最重要的爬虫属性,并且是必需的。
如果爬虫抓取单个域,常见的做法是根据域名命名爬虫,无论是否带 TLD。因此,例如,一个抓取 mywebsite.com 的爬虫通常被称为 mywebsite。
allowed_domains
一个可选的字符串列表,包含此爬虫允许抓取的域。如果启用了 OffsiteMiddleware,则不属于此列表中指定域名(或其子域)的 URL 请求将不会被跟踪。
假设您的目标 URL 是 https://www.example.com/1.html,那么将 'example.com' 添加到列表中。
start_urls: list[str]
起始 URL。参见 start()。
custom_settings
一个字典,其中包含在运行此爬虫时将覆盖项目范围配置的设置。它必须定义为类属性,因为设置在实例化之前更新。
有关可用内置设置的列表,请参见:内置设置参考。
crawler
此属性由 from_crawler() 类方法在初始化类后设置,并链接到此爬虫实例绑定的 Crawler 对象。
爬虫封装了项目中许多组件,以便进行单一入口访问(例如扩展、中间件、信号管理器等)。请参阅 Crawler API 了解更多信息。
settings
运行此爬虫的配置。这是一个 Settings 实例,有关此主题的详细介绍,请参见设置主题。
logger
使用爬虫的 name 创建的 Python 日志器。您可以使用它来发送日志消息,如 从爬虫记录日志 中所述。
state
一个字典,您可以用于在批处理之间保留一些爬虫状态。有关详细信息,请参阅保持批处理之间的持久状态。
from_crawler(crawler, *args, **kwargs)[source]
这是 Scrapy 用于创建爬虫的类方法。
您可能不需要直接重写此方法,因为默认实现充当 __init__() 方法的代理,使用给定的参数 args 和命名参数 kwargs 调用它。
尽管如此,此方法会在新实例中设置 crawler 和 settings 属性,以便以后可以在爬虫代码中访问它们。
版本 2.11 中的变化:现在可以在此方法中修改 crawler.settings 中的设置,如果您想根据参数修改它们,这会很方便。因此,这些设置不是最终值,因为它们以后可能会被附加组件等修改。出于同样的原因,大多数 Crawler 属性此时未初始化。
最终设置和已初始化的 Crawler 属性可在 start() 方法、engine_started 信号的处理程序以及之后使用。
参数:
crawler(Crawler 实例)——爬虫将绑定的爬虫args(list)——传递给__init__()方法的参数kwargs(dict)——传递给__init__()方法的关键字参数
classmethod update_settings(settings)[source]
update_settings() 方法用于修改爬虫的设置,并在爬虫实例初始化期间调用。
它将一个 Settings 对象作为参数,可以添加或更新爬虫的配置值。此方法是类方法,这意味着它在 Spider 类上调用,并允许爬虫的所有实例共享相同的配置。
虽然可以在 custom_settings 中设置每个爬虫的设置,但使用 update_settings() 允许您根据其他设置、爬虫属性或其他因素动态添加、删除或更改设置,并使用除 'spider' 之外的设置优先级。此外,通过重写它很容易在子类中扩展 update_settings(),而使用 custom_settings 做到这一点可能会很困难。
例如,假设爬虫需要修改 FEEDS:
import scrapy
class MySpider(scrapy.Spider):
name = "myspider"
custom_feed = {
"/home/user/documents/items.json": {
"format": "json",
"indent": 4,
}
}
@classmethod
def update_settings(cls, settings):
super().update_settings(settings)
settings.setdefault("FEEDS", {}).update(cls.custom_feed)
async start() -> AsyncIterator[Any][source]
生成要发送的初始 Request 对象。
版本 2.13 新增。
例如:
from scrapy import Request, Spider
class MySpider(Spider):
name = "myspider"
async def start(self):
yield Request("https://toscrape.com/")
默认实现从 start_urls 读取 URL,并为每个 URL 生成一个 dont_filter 启用的请求。它在功能上等同于:
async def start(self):
for url in self.start_urls:
yield Request(url, dont_filter=True)
您还可以生成 Item。例如:
async def start(self):
yield {"foo": "bar"}
为了编写在低于 2.13 的 Scrapy 版本上工作的爬虫,还需要定义一个返回可迭代对象的同步 start_requests() 方法。例如:
def start_requests(self):
yield Request("https://toscrape.com/")
另请参阅
起始请求
parse(response)[source]
这是 Scrapy 用于处理下载响应的默认回调,当它们的请求未指定回调时。
parse 方法负责处理响应并返回抓取的数据和/或要跟踪的更多 URL。其他 Request 回调与 Spider 类具有相同的要求。
此方法以及任何其他 Request 回调都必须返回一个 Request 对象、一个 item 对象、一个 Request 对象和/或 item 对象的可迭代对象,或者 None。
参数:
response(Response)——要解析的响应
log(message[, level, component])[source]
通过爬虫的 logger 发送日志消息的包装器,保留用于向后兼容。有关详细信息,请参阅从爬虫记录日志。
closed(reason)
当爬虫关闭时调用。此方法为 spider_closed 信号提供了 signals.connect() 的快捷方式。
让我们看一个例子:
import scrapy
class MySpider(scrapy.Spider):
name = "example.com"
allowed_domains = ["example.com"]
start_urls = [
"http://www.example.com/1.html",
"http://www.example.com/2.html",
"http://www.example.com/3.html",
]
def parse(self, response):
self.logger.info("A response from %s just arrived!", response.url)
从单个回调返回多个请求和 Item:
import scrapy
class MySpider(scrapy.Spider):
name = "example.com"
allowed_domains = ["example.com"]
start_urls = [
"http://www.example.com/1.html",
"http://www.example.com/2.html",
"http://www.example.com/3.html",
]
def parse(self, response):
for h3 in response.xpath("//h3").getall():
yield {"title": h3}
for href in response.xpath("//a/@href").getall():
yield scrapy.Request(response.urljoin(href), self.parse)
除了 start_urls,您还可以直接使用 start();为了使数据更具结构化,您可以使用 Item 对象:
import scrapy
from myproject.items import MyItem
class MySpider(scrapy.Spider):
name = "example.com"
allowed_domains = ["example.com"]
async def start(self):
yield scrapy.Request("http://www.example.com/1.html", self.parse)
yield scrapy.Request("http://www.example.com/2.html", self.parse)
yield scrapy.Request("http://www.example.com/3.html", self.parse)
def parse(self, response):
for h3 in response.xpath("//h3").getall():
yield MyItem(title=h3)
for href in response.xpath("//a/@href").getall():
yield scrapy.Request(response.urljoin(href), self.parse)
爬虫参数
爬虫可以接收修改其行为的参数。爬虫参数的一些常见用途是定义起始 URL 或将抓取限制到网站的特定部分,但它们可用于配置爬虫的任何功能。
爬虫参数通过 crawl 命令使用 -a 选项传递。例如:
scrapy crawl myspider -a category=electronics
爬虫可以在它们的 __init__ 方法中访问参数:
import scrapy
class MySpider(scrapy.Spider):
name = "myspider"
def __init__(self, category=None, *args, **kwargs):
super(MySpider, self).__init__(*args, **kwargs)
self.start_urls = [f"http://www.example.com/categories/{category}"]
# ...
默认的 __init__ 方法将获取任何爬虫参数并将其复制到爬虫作为属性。上面的示例也可以写成如下:
import scrapy
class MySpider(scrapy.Spider):
name = "myspider"
async def start(self):
yield scrapy.Request(f"http://www.example.com/categories/{self.category}")
如果您从脚本运行 Scrapy,您可以在调用 CrawlerProcess.crawl 或 CrawlerRunner.crawl 时指定爬虫参数:
process = CrawlerProcess()
process.crawl(MySpider, category="electronics")
请记住,爬虫参数只是字符串。爬虫不会自行进行任何解析。如果您要从命令行设置 start_urls 属性,则必须使用 ast.literal_eval() 或 json.loads() 之类的工具将其解析为列表,然后将其设置为属性。否则,您将导致迭代 start_urls 字符串(一个非常常见的 Python 陷阱),导致每个字符被视为单独的 URL。
一个有效的用例是设置 HttpAuthMiddleware 使用的 HTTP 认证凭据或 UserAgentMiddleware 使用的用户代理:
scrapy crawl myspider -a http_user=myuser -a http_pass=mypassword -a user_agent=mybot
爬虫参数也可以通过 Scrapyd 的 schedule.json API 传递。请参阅 Scrapyd 文档。
起始请求
起始请求是从爬虫的 start() 方法或爬虫中间件的 process_start() 方法生成的 Request 对象。
另请参阅
起始请求顺序
延迟起始请求迭代
您可以按如下方式重写 start() 方法,以便在有计划请求时暂停其迭代:
async def start(self):
async for item_or_request in super().start():
if self.crawler.engine.needs_backout():
await self.crawler.signals.wait_for(signals.scheduler_empty)
yield item_or_request
这有助于最大限度地减少调度程序中任何给定时间的请求数量,从而最大限度地减少资源使用(内存或磁盘,具体取决于 JOBDIR)。
通用爬虫
Scrapy 附带了一些有用的通用爬虫,您可以从中继承您的爬虫。它们旨在为一些常见的抓取情况提供便捷的功能,例如根据某些规则跟踪站点上的所有链接,从 Sitemaps 爬取,或解析 XML/CSV 源。
对于以下爬虫中使用的示例,我们假设您有一个项目,其中在 myproject.items 模块中声明了一个 TestItem:
import scrapy
class TestItem(scrapy.Item):
id = scrapy.Field()
name = scrapy.Field()
description = scrapy.Field()
CrawlSpider
class scrapy.spiders.CrawlSpider[source]
这是用于爬取常规网站最常用的爬虫,因为它通过定义一组规则提供了方便的跟踪链接机制。它可能不是最适合您的特定网站或项目,但它对于多种情况来说足够通用,因此您可以从它开始,并根据需要覆盖它以实现更多自定义功能,或者只是实现您自己的爬虫。
除了从 Spider 继承的属性(您必须指定)之外,此类别支持一个新属性:
rules
这是一个包含一个(或多个)Rule 对象的列表。每个 Rule 都定义了爬取站点的特定行为。Rule 对象如下所述。如果多个规则匹配同一个链接,将使用第一个匹配的规则,根据它们在此属性中定义的顺序。
此爬虫还公开了一个可重写的方法:
parse_start_url(response, **kwargs)[source]
此方法为爬虫 start_urls 属性中为 URL 生成的每个响应调用。它允许解析初始响应,并且必须返回一个 item 对象、一个 Request 对象或包含其中任何一个的可迭代对象。
爬取规则
class scrapy.spiders.Rule(link_extractor: LinkExtractor | None = None, callback: CallbackT | str | None = None, cb_kwargs: dict[str, Any] | None = None, follow: bool | None = None, process_links: ProcessLinksT | str | None = None, process_request: ProcessRequestT | str | None = None, errback: Callable[[Failure], Any] | str | None = None)[source]
link_extractor是一个 Link Extractor 对象,它定义了如何从每个爬取的页面中提取链接。每个生成的链接将用于生成一个 Request 对象,该对象将在其meta字典(在link_text键下)中包含链接的文本。如果省略,将使用不带参数创建的默认链接提取器,导致所有链接都被提取。callback是一个可调用对象或一个字符串(在这种情况下将使用爬虫对象中同名的方法),用于为使用指定链接提取器提取的每个链接调用。此回调接收一个 Response 作为其第一个参数,并且必须返回一个或多个 item 对象和/或 Request 对象(或它们的任何子类)的单个实例或可迭代对象。如上所述,接收到的 Response 对象将在其meta字典(在link_text键下)中包含生成 Request 的链接的文本。cb_kwargs是一个字典,包含要传递给回调函数的关键字参数。follow是一个布尔值,指定是否应从此规则提取的每个响应中跟踪链接。如果callback为None,则follow默认为True,否则默认为False。process_links是一个可调用对象,或一个字符串(在这种情况下将使用爬虫对象中同名的方法),它将用于处理使用指定的link_extractor从每个响应中提取的每个链接列表。这主要用于过滤目的。process_request是一个可调用对象(或一个字符串,在这种情况下将使用爬虫对象中同名的方法),它将为此规则提取的每个 Request 调用。此可调用对象应将所述请求作为第一个参数,并将生成请求的 Response 作为第二个参数。它必须返回一个 Request 对象或None(以过滤掉请求)。errback是一个可调用对象或一个字符串(在这种情况下将使用爬虫对象中同名的方法),如果处理此规则生成的请求时引发任何异常,则调用它。它接收一个 Twisted Failure 实例作为第一个参数。
警告
由于其内部实现,在编写基于 CrawlSpider 的爬虫时,您必须显式地为新请求设置回调;否则可能会出现意外行为。
版本 2.0 新增:errback 参数。
CrawlSpider 示例
现在让我们看一个带有规则的 CrawlSpider 示例:
import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
class MySpider(CrawlSpider):
name = "example.com"
allowed_domains = ["example.com"]
start_urls = ["http://www.example.com"]
rules = (
# Extract links matching 'category.php' (but not matching 'subsection.php')
# and follow links from them (since no callback means follow=True by default).
Rule(LinkExtractor(allow=(r"category\.php",), deny=(r"subsection\.php",))),
# Extract links matching 'item.php' and parse them with the spider's method parse_item
Rule(LinkExtractor(allow=(r"item\.php",)), callback="parse_item"),
)
def parse_item(self, response):
self.logger.info("Hi, this is an item page! %s", response.url)
item = scrapy.Item()
item["id"] = response.xpath('//td[@id="item_id"]/text()').re(r"ID: (\d+)")
item["name"] = response.xpath('//td[@id="item_name"]/text()').get()
item["description"] = response.xpath(
'//td[@id="item_description"]/text()'
).get()
item["link_text"] = response.meta["link_text"]
url = response.xpath('//td[@id="additional_data"]/@href').get()
return response.follow(
url, self.parse_additional_page, cb_kwargs=dict(item=item)
)
def parse_additional_page(self, response, item):
item["additional_data"] = response.xpath(
'//p[@id="additional_data"]/text()'
).get()
return item
这个爬虫将开始抓取 example.com 的主页,收集类别链接和 Item 链接,并使用 parse_item 方法解析后者。对于每个 Item 响应,将使用 XPath 从 HTML 中提取一些数据,并用它填充一个 Item。
XMLFeedSpider
class scrapy.spiders.XMLFeedSpider[source]
XMLFeedSpider 旨在通过按特定节点名称迭代 XML 源来解析它们。迭代器可以从 iternodes、xml 和 html 中选择。建议使用 iternodes 迭代器以提高性能,因为 xml 和 html 迭代器会一次性生成整个 DOM 以进行解析。但是,在解析包含不良标记的 XML 时,使用 html 作为迭代器可能会很有用。
要设置迭代器和标签名称,您必须定义以下类属性:
iterator
一个字符串,定义要使用的迭代器。它可以是以下之一:
'iternodes'- 基于正则表达式的快速迭代器'html'- 使用 Selector 的迭代器。请记住,这使用 DOM 解析,并且必须将所有 DOM 加载到内存中,这对于大型源来说可能是一个问题'xml'- 使用 Selector 的迭代器。请记住,这使用 DOM 解析,并且必须将所有 DOM 加载到内存中,这对于大型源来说可能是一个问题
默认为:'iternodes'。
itertag
一个字符串,包含要迭代的节点(或元素)的名称。例如:
itertag = 'product'
namespaces
一个由 (prefix, uri) 元组组成的列表,用于定义该文档中可用的命名空间,这些命名空间将由该爬虫处理。prefix 和 uri 将用于使用 register_namespace() 方法自动注册命名空间。
然后,您可以在 itertag 属性中指定带有命名空间的节点。
示例:
class YourSpider(XMLFeedSpider):
namespaces = [('n', 'http://www.sitemaps.org/schemas/sitemap/0.9')]
itertag = 'n:url'
# ...
除了这些新属性之外,此爬虫还具有以下可重写方法:
adapt_response(response)[source]
一个方法,在响应从爬虫中间件到达后立即接收响应,在爬虫开始解析它之前。它可以用于在解析响应体之前修改它。此方法接收一个响应并返回一个响应(可以是同一个或另一个)。
parse_node(response, selector)[source]
此方法为与提供的标签名称 (itertag) 匹配的节点调用。接收响应和每个节点的 Selector。覆盖此方法是强制性的。否则,您的爬虫将无法工作。此方法必须返回一个 item 对象、一个 Request 对象或包含其中任何一个的可迭代对象。
process_results(response, results)[source]
此方法为爬虫返回的每个结果(Item 或 Request)调用,旨在在将结果返回给框架核心之前执行任何最后的处理,例如设置 Item ID。它接收结果列表和生成这些结果的响应。它必须返回结果列表(Item 或 Request)。
警告
由于其内部实现,在编写基于 XMLFeedSpider 的爬虫时,您必须显式地为新请求设置回调;否则可能会出现意外行为。
XMLFeedSpider 示例
这些爬虫非常易于使用,让我们看一个例子:
from scrapy.spiders import XMLFeedSpider
from myproject.items import TestItem
class MySpider(XMLFeedSpider):
name = "example.com"
allowed_domains = ["example.com"]
start_urls = ["http://www.example.com/feed.xml"]
iterator = "iternodes" # This is actually unnecessary, since it's the default value
itertag = "item"
def parse_node(self, response, node):
self.logger.info(
"Hi, this is a <%s> node!: %s", self.itertag, "".join(node.getall())
)
item = TestItem()
item["id"] = node.xpath("@id").get()
item["name"] = node.xpath("name").get()
item["description"] = node.xpath("description").get()
return item
基本上,我们上面所做的是创建一个爬虫,从给定的 start_urls 下载一个 feed,然后迭代它的每个 item 标签,打印它们,并将一些随机数据存储在 Item 中。
CSVFeedSpider
class scrapy.spiders.CSVFeedSpider[source]
此爬虫与 XMLFeedSpider 非常相似,不同之处在于它迭代的是行而不是节点。每次迭代中调用的方法是 parse_row()。
delimiter
一个字符串,表示 CSV 文件中每个字段的分隔符。默认为 ','(逗号)。
quotechar
一个字符串,表示 CSV 文件中每个字段的包围字符。默认为 '"'(引号)。
headers
CSV 文件中列名的列表。
parse_row(response, row)[source]
接收一个响应和一个字典(表示每行),其中包含 CSV 文件中每个提供(或检测到)的标题的键。此爬虫还提供了重写 adapt_response 和 process_results 方法的机会,用于预处理和后处理。
CSVFeedSpider 示例
让我们看一个与上一个类似的示例,但使用 CSVFeedSpider:
from scrapy.spiders import CSVFeedSpider
from myproject.items import TestItem
class MySpider(CSVFeedSpider):
name = "example.com"
allowed_domains = ["example.com"]
start_urls = ["http://www.example.com/feed.csv"]
delimiter = ";"
quotechar = "'"
headers = ["id", "name", "description"]
def parse_row(self, response, row):
self.logger.info("Hi, this is a row!: %r", row)
item = TestItem()
item["id"] = row["id"]
item["name"] = row["name"]
item["description"] = row["description"]
return item
SitemapSpider
class scrapy.spiders.SitemapSpider[source]
SitemapSpider 允许您通过使用 Sitemaps 发现 URL 来抓取网站。
它支持嵌套站点地图和从 robots.txt 发现站点地图 URL。
sitemap_urls
指向您要抓取其 URL 的站点地图的 URL 列表。
您还可以指向 robots.txt,它将被解析以从中提取站点地图 URL。
sitemap_rules
一个元组列表 (regex, callback),其中:
regex是一个正则表达式,用于匹配从站点地图中提取的 URL。regex可以是字符串或编译后的正则表达式对象。callback是用于处理匹配正则表达式的 URL 的回调。callback可以是字符串(表示爬虫方法的名称)或可调用对象。
例如:
sitemap_rules = [('/product/', 'parse_product')]
规则按顺序应用,只有第一个匹配的规则将被使用。
如果您省略此属性,则站点地图中找到的所有 URL 都将使用 parse 回调进行处理。
sitemap_follow
应跟踪的站点地图的正则表达式列表。这仅适用于使用站点地图索引文件指向其他站点地图文件的网站。
默认情况下,所有站点地图都会被跟踪。
sitemap_alternate_links
指定是否应跟踪同一 URL 的备用链接。这些是同一网站中不同语言的链接,在同一 url 块中传递。
例如:
<url>
<loc>http://example.com/</loc>
<xhtml:link rel="alternate" hreflang="de" href="http://example.com/de"/>
</url>
设置 sitemap_alternate_links 后,这将检索两个 URL。禁用 sitemap_alternate_links 后,将只检索 http://example.com/。
默认情况下 sitemap_alternate_links 是禁用的。
sitemap_filter(entries)[source]
这是一个过滤函数,可以重写它以根据其属性选择站点地图条目。
例如:
<url>
<loc>http://example.com/</loc>
<lastmod>2005-01-01</lastmod>
</url>
我们可以定义一个 sitemap_filter 函数来按日期过滤 entries:
from datetime import datetime
from scrapy.spiders import SitemapSpider
class FilteredSitemapSpider(SitemapSpider):
name = "filtered_sitemap_spider"
allowed_domains = ["example.com"]
sitemap_urls = ["http://example.com/sitemap.xml"]
def sitemap_filter(self, entries):
for entry in entries:
date_time = datetime.strptime(entry["lastmod"], "%Y-%m-%d")
if date_time.year >= 2005:
yield entry
这将只检索在 2005 年及以后修改的 entries。
Entries 是从站点地图文档中提取的字典对象。通常,键是标签名称,值是其中的文本。
需要注意的重要事项是:
- 由于
loc属性是必需的,因此没有此标签的条目将被丢弃 - 备用链接存储在一个名为
alternate的键的列表中(参见sitemap_alternate_links) - 命名空间被移除,因此名为
{namespace}tagname的 lxml 标签只变为tagname
如果您省略此方法,则站点地图中找到的所有条目都将被处理,并遵守其他属性及其设置。
SitemapSpider 示例
最简单的示例:使用 parse 回调处理通过站点地图发现的所有 URL:
from scrapy.spiders import SitemapSpider
class MySpider(SitemapSpider):
sitemap_urls = ["http://www.example.com/sitemap.xml"]
def parse(self, response):
pass # ... scrape item here ...
使用特定回调处理某些 URL,并使用不同回调处理其他 URL:
from scrapy.spiders import SitemapSpider
class MySpider(SitemapSpider):
sitemap_urls = ["http://www.example.com/sitemap.xml"]
sitemap_rules = [
("/product/", "parse_product"),
("/category/", "parse_category"),
]
def parse_product(self, response):
pass # ... scrape product ...
def parse_category(self, response):
pass # ... scrape category ...
跟踪 robots.txt 文件中定义的站点地图,并且只跟踪 URL 包含 /sitemap_shop 的站点地图:
from scrapy.spiders import SitemapSpider
class MySpider(SitemapSpider):
sitemap_urls = ["http://www.example.com/robots.txt"]
sitemap_rules = [
("/shop/", "parse_shop"),
]
sitemap_follow = ["/sitemap_shops"]
def parse_shop(self, response):
pass # ... scrape shop here ...
将 SitemapSpider 与其他 URL 源结合使用:
from scrapy.spiders import SitemapSpider
class MySpider(SitemapSpider):
sitemap_urls = ["http://www.example.com/robots.txt"]
sitemap_rules = [
("/shop/", "parse_shop"),
]
other_urls = ["http://www.example.com/about"]
async def start(self):
async for item_or_request in super().start():
yield item_or_request
for url in self.other_urls:
yield Request(url, self.parse_other)
def parse_shop(self, response):
pass # ... scrape shop here ...
def parse_other(self, response):
pass # ... scrape other here ...