我正在使用 Scrapy,特别是 Scrapy 的 CrawlSpider
类来抓取包含某些关键字的 Web 链接。我有一个很长的start_urls
从连接到 Django 项目的 SQLite 数据库中获取其条目的列表。我想将抓取的 Web 链接保存在此数据库中。
我有两个 Django 模型,一个用于启动 url,例如 http://example.com
一个用于抓取的网络链接,例如 http://example.com/website1
, http://example.com/website2
等等。所有抓取的 Web 链接都是 start_urls
中起始网址之一的子站点。列表。
网络链接模型与起始 url 模型具有多对一关系,即网络链接模型具有指向起始 url 模型的外键。为了将我抓取的 Web 链接正确保存到数据库中,我需要告诉 CrawlSpider
的 parse_item()
抓取的 web 链接所属的开始 url 的方法。我怎样才能做到这一点? Scrapy的DjangoItem
class 在这方面没有帮助,因为我仍然必须明确定义使用的起始 url。
换句话说,我如何将当前使用的开始 url 传递给 parse_item()
方法,以便我可以将它与适当的抓取的 Web 链接一起保存到数据库?有任何想法吗?提前致谢!
最佳答案
默认情况下,您无法访问原始起始网址。
但是你可以覆盖make_requests_from_url
方法并将开始 url 放入 meta
.然后在解析中,您可以从那里提取它(如果您在该解析方法中产生后续请求,请不要忘记在其中转发该起始 url)。
我没有使用过 CrawlSpider
,也许 Maxim 的建议对你有用,但请记住 response.url
有可能重定向后的 url。
这是我将如何做的一个例子,但这只是一个例子(取自 scrapy 教程)并且没有经过测试:
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(SgmlLinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),
# Extract links matching 'item.php' and parse them with the spider's method parse_item
Rule(SgmlLinkExtractor(allow=('item\.php', )), callback='parse_item'),
)
def parse(self, response): # When writing crawl spider rules, avoid using parse as callback, since the CrawlSpider uses the parse method itself to implement its logic. So if you override the parse method, the crawl spider will no longer work.
for request_or_item in CrawlSpider.parse(self, response):
if isinstance(request_or_item, Request):
request_or_item = request_or_item.replace(meta = {'start_url': response.meta['start_url']})
yield request_or_item
def make_requests_from_url(self, url):
"""A method that receives a URL and returns a Request object (or a list of Request objects) to scrape.
This method is used to construct the initial requests in the start_requests() method,
and is typically used to convert urls to requests.
"""
return Request(url, dont_filter=True, meta = {'start_url': url})
def parse_item(self, response):
self.log('Hi, this is an item page! %s' % response.url)
hxs = HtmlXPathSelector(response)
item = Item()
item['id'] = hxs.select('//td[@id="item_id"]/text()').re(r'ID: (\d+)')
item['name'] = hxs.select('//td[@id="item_name"]/text()').extract()
item['description'] = hxs.select('//td[@id="item_description"]/text()').extract()
item['start_url'] = response.meta['start_url']
return item
有问题就问。顺便说一句,使用 PyDev 的“转到定义”功能,您可以查看 scrapy 源并了解 Request
、make_requests_from_url
和其他类和方法期望的参数。深入了解代码有助于并节省您的时间,尽管一开始可能看起来很困难。
关于python - 如何访问 Scrapy CrawlSpider 中的特定 start_url?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10598691/