我有一个蜘蛛,每天爬网的网页数以十万计。页面本身在发布后很少更改,但始终被删除/添加。大多数页面仅活动几个星期或几个月。
因此,我想让Spider在抓取一次之后停止抓取它们的页面,而是只要在Sitemap中找到该页面,就对我的数据库进行快速SQL更新调用(这意味着该页面仍然存在,我可以更新“ last_found_date”列)。
我想最好的方法是重写SitemapSpider
并防止蜘蛛首先在我的数据库中已经存在URL的情况下发送请求。
这该怎么做?
最佳答案
我可以通过重写start_request()
函数并基于parse_sitemap()
SitemapSpider
函数创建自己的_parse_sitemap()
函数来解决此问题。
我是通过以下方式做到的:
1)在您的__init__()
中,属于您自己的Spider。致电父母init。这是parse_sitemap函数中某些功能所必需的。
def __init__(self, *a, **kw):
super(HemnetSitemapSpider, self).__init__(*a, **kw)
2)您需要创建自己的
start_request()
。如果不是,默认的start_request()
将呼叫父母_parse_sitemap()
。def start_requests(self):
return (scrapy.Request(x, callback=self.parse_sitemap) for x in self.sitemap_urls)
3)最后,您需要创建自己的
parse_sitemap()
。进入scrapy package文件夹,打开包含父类的原始sitemap.py
文件,然后复制_parse_sitemap()
的整个函数。在该函数中,有一部分内容说:
elif s.type == 'urlset':
...
这是查找不是子站点地图的URL的部分,这是您要检查该URL是否已在数据库中或是否要执行的位置。
所以我的
parse_sitemap()
函数看起来像这样:def parse_sitemap(self, response):
if response.url.endswith('/robots.txt'):
for url in sitemap_urls_from_robots(response.body):
yield Request(url, callback=self.parse_sitemap)
else:
body = self._get_sitemap_body(response)
if body is None:
log.msg(format="Ignoring invalid sitemap: %(response)s",
level=log.WARNING, spider=self, response=response)
return
s = Sitemap(body)
if s.type == 'sitemapindex':
for loc in iterloc(s, self.sitemap_alternate_links):
if any(x.search(loc) for x in self._follow):
yield Request(loc, callback=self.parse_sitemap)
# If this is a URL Set, then check if it has been parsed before.
elif s.type == 'urlset':
for loc in iterloc(s):
for r, c in self._cbs:
if r.search(loc):
# Check here for history URL
try:
self.cursor.execute('_YOUR_SQL_QUERY_', [loc])
row = self.cursor.fetchone()
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
# If no row exist from that source, then send the request.
if row is None:
yield Request(loc, callback=c)
# Else, if this source already exists. Update the date_updated field
else:
# Update date_updated
try:
date = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
self.cursor.execute('_YOUR_UPDATE_QUERY_', [date, row[0]])
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
# Break for loop.
break
关于python - 解析前检查SitemapSpider中的网址,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29006788/