我正在尝试使用Scrapy从数据库加载一些XPATH规则。
到目前为止我编写的代码工作正常,但是经过一些调试我已经意识到Scrapy正在异步解析每个项目,这意味着我无法控制正在解析哪个项目的顺序。
我想要做的是确定当列表中的哪个项目在点击parse()
函数时被解析,因此我可以将该索引引用到我的数据库中的行并获取正确的XPATH查询。我现在这样做的方法是使用一个名为item_index
的变量,并在每次迭代后递增它。现在我意识到这还不够,我希望有一些内部功能可以帮助我实现这一目标。
有谁知道跟踪这个的正确方法?我查看了文档,但找不到任何关于它的信息。我还查看了Scrapy source code,但我似乎无法弄清楚URL的列表是如何实际存储的。
这是我的代码,可以进一步解释我的问题:
# -*- coding: utf-8 -*-
from scrapy.spider import Spider
from scrapy.selector import Selector
from dirbot.items import Product
from dirbot.database import DatabaseConnection
# Create a database connection object so we can execute queries
connection = DatabaseConnection()
class DmozSpider(Spider):
name = "dmoz"
start_urls = []
item_index = 0
# Query for all products sold by a merchant
rows = connection.query("SELECT * FROM products_merchant WHERE 1=1")
def start_requests(self):
for row in self.rows:
yield self.make_requests_from_url(row["product_url"])
def parse(self, response):
sel = Selector(response)
item = Product()
item['product_id'] = self.rows[self.item_index]['product_id']
item['merchant_id'] = self.rows[self.item_index]['merchant_id']
item['price'] = sel.xpath(self.rows[self.item_index]['xpath_rule']).extract()
self.item_index+=1
return item
非常感谢任何指导!
由于
答案 0 :(得分:3)
这是我提出的解决方案,以防万一有需要。
正如@toothrot建议的那样,您需要重载Request
类中的方法才能访问meta
信息。
希望这有助于某人。
# -*- coding: utf-8 -*-
from scrapy.spider import Spider
from scrapy.selector import Selector
from scrapy.http import Request
from dirbot.items import Product
from dirbot.database import DatabaseConnection
# Create a database connection object so we can execute queries
connection = DatabaseConnection()
class DmozSpider(Spider):
name = "dmoz"
start_urls = []
# Query for all products sold by a merchant
rows = connection.query("SELECT * FROM products_merchant WHERE 1=1")
def start_requests(self):
for indx, row in enumerate(self.rows):
self.start_urls.append( row["product_url"] )
yield self.make_requests_from_url(row["product_url"], {'index': indx})
def make_requests_from_url(self, url, meta):
return Request(url, callback=self.parse, dont_filter=True, meta=meta)
def parse(self, response):
item_index = response.meta['index']
sel = Selector(response)
item = Product()
item['product_id'] = self.rows[item_index]['product_id']
item['merchant_id'] = self.rows[item_index]['merchant_id']
item['price'] = sel.xpath(self.rows[item_index]['xpath_rule']).extract()
return item
答案 1 :(得分:1)
您可以使用Request.meta将索引(或数据库中的行ID)与请求一起传递。它是您可以从处理程序中的Response.meta访问的字典。
例如,当您构建请求时:
Request(url, callback=self.some_handler, meta={'row_id': row['id']})
使用像您这样的计数器尝试不起作用,因为您无法保证处理响应的顺序。