为不同类型的项目抓取不同的蜘蛛
scrapy different spider for different type item
我认为scrapy的框架可能有点死板。而且我找不到解决问题的好方法。
这是我现在面临的问题。
假设有一个网站 http://example.com/
。我想从中删除一些信息。
它有很多项目是 http://example.com/item/([0-9]+)
形式的 url,现在我 有 有效 ([0-9]+)
的列表,大约有 300万个索引id,完成整个网页抓取工作看似简单的任务
但是,这个任务的结构是这样的:
/item/
的页面有很多该项目的数据。我想要这些资料,这个实现起来很简单。
- 有 link 引用与项目相关的实体,例如
item owner
与 link 路径 /owner/
,或 the collections the item belongs
与 link 路径 /collection/
等等。我想要这些实体的所有 unique 信息,这很难实现。由于以下原因,它们不应该是 item
的嵌套项目或被单个蜘蛛废弃:
- 单个
owner
有 [1-n]
项。
- 单个项有
[1-n]
owners
.
- 与
collection
相同
- 有 link 引用与该项目相关的其他实体,例如
comment
具有 link 路径 /comment/
或 user
谁喜欢它带有 link 路径 /user/
。显然,将 comment
或 user
信息从 item
中分离出来并使用 key 或索引 来引用实体是明智的。这是单个蜘蛛很难做到的。
所以,我更喜欢启动一个蜘蛛来处理 http://example.com/item/([0-9]+)
的列表,并使用其他类型的蜘蛛来处理 item owner
、collection
、comment
, 和 user
分别。
但是,问题是我没有item owner
、collection
、comment
和[=26的列表=].我只能通过迭代 http://example.com/item/([0-9]+)
.
的网页来浏览所有这些实体
我在谷歌上搜索了很多,但没有找到适合我的问题的解决方案。欢迎大家发表意见。
据我了解,您并不是在寻找 多域 爬虫,因为您基本上是在抓取一个域,对吗?您甚至不需要点击许多不同且不可预测的链接,因为您已经知道要查找的内容。这是正确的吗?
为此,我建议使用 selenium
(也许 BeautifulSoup)。 selenium
非常轻量级,可以 运行 与 PhantomJS 无头,如果你知道被废弃页面的结构,与 Scrappy 相比,你可以放置更多的逻辑和控制(好吧,绝对更容易)。
我没有看到最终数据的结构和类型,但它们似乎有点层次性,并且它们之间存在关系。我会将数据存储在带有列表的字典中,即使它们不是唯一的,然后将它们转储到例如MongoDB(使用 pymongo 非常简单,基本上是 3 个创建连接的命令,然后一个将其放入数据库)。收集完之后,我会关心关系、过滤和其他东西。通常稍后(使用用于此目的的工具,例如 pandas
)然后在报废期间要容易得多。
对于你的特殊情况,我会在你希望废弃的范围 (3M) 上做一个 for 循环,在每一步你都会 运行 访问 URL 的函数,如果不是 404 , 然后是 scrap info, 然后是 scrap owners, 然后是 scrap category... 这些应该是独立的功能,选择器会根据结构而变化,尽可能使用适当的 CSS 或 XPATH,否则你可以使用 find_elements
然后根据文本或 href 过滤它们(例如 /owner/
in href
of all a
)。
您的大部分要求似乎都非常适合 scrapy。您已经说过您可以简单地抓取项目列表,这是一个好的开始。我想你是说每个项目都有 links 给所有者、评论、用户。在这种情况下,您使用 response.xpath 获得 URL,然后使用 yield Request(URL, callback=parse_owner)
作为示例。您将希望 link 将不同的抓取数据放在一起,在这种情况下,您可以将 meta={'id': identifier}
添加到 Request()。正如@kotrfa 所说,转储到数据库可能是最好的,因为这听起来像是有一些交叉 linking 数据。
根据您提供的信息,我只能说这么多。更多信息将使我们的情况更加清晰。
这是 ItemSpider
.
的伪代码
from scrapy_redis.spiders import RedisSpider
import redis
class ItemSpider(RedisSpider):
name = 'item'
def parse(self, response):
# process to get item info.
r = redis.Redis(...)
r.lpush('user:start_urls', user_link)
return ...
这是 UserSpider
.
的伪代码
from scrapy_redis.spiders import RedisSpider
class UserSpider(RedisSpider):
name = 'user'
def parse(self, response):
# process to get user info.
return ...
然后将您的项目 url 添加到 redis 中的 item:start_urls
列表中。
最后,
scrapy crawl item
scrapy crawl user
应该提前考虑更高级的概念,例如避免重复项。至少上述解决方案已经将 ItemSpider
和 UserSpider
的时间表分开了。
由于 here 的帮助,我进入了这个解决方案,感谢@lnxpgn。
谁能提供更好的解决方案?或者提供更好的避免重复抓取的方案?
我认为scrapy的框架可能有点死板。而且我找不到解决问题的好方法。
这是我现在面临的问题。
假设有一个网站 http://example.com/
。我想从中删除一些信息。
它有很多项目是 http://example.com/item/([0-9]+)
形式的 url,现在我 有 有效 ([0-9]+)
的列表,大约有 300万个索引id,完成整个网页抓取工作看似简单的任务
但是,这个任务的结构是这样的:
/item/
的页面有很多该项目的数据。我想要这些资料,这个实现起来很简单。- 有 link 引用与项目相关的实体,例如
item owner
与 link 路径/owner/
,或the collections the item belongs
与 link 路径/collection/
等等。我想要这些实体的所有 unique 信息,这很难实现。由于以下原因,它们不应该是item
的嵌套项目或被单个蜘蛛废弃:- 单个
owner
有[1-n]
项。 - 单个项有
[1-n]
owners
. - 与
collection
相同
- 单个
- 有 link 引用与该项目相关的其他实体,例如
comment
具有 link 路径/comment/
或user
谁喜欢它带有 link 路径/user/
。显然,将comment
或user
信息从item
中分离出来并使用 key 或索引 来引用实体是明智的。这是单个蜘蛛很难做到的。
所以,我更喜欢启动一个蜘蛛来处理 http://example.com/item/([0-9]+)
的列表,并使用其他类型的蜘蛛来处理 item owner
、collection
、comment
, 和 user
分别。
但是,问题是我没有item owner
、collection
、comment
和[=26的列表=].我只能通过迭代 http://example.com/item/([0-9]+)
.
我在谷歌上搜索了很多,但没有找到适合我的问题的解决方案。欢迎大家发表意见。
据我了解,您并不是在寻找 多域 爬虫,因为您基本上是在抓取一个域,对吗?您甚至不需要点击许多不同且不可预测的链接,因为您已经知道要查找的内容。这是正确的吗?
为此,我建议使用 selenium
(也许 BeautifulSoup)。 selenium
非常轻量级,可以 运行 与 PhantomJS 无头,如果你知道被废弃页面的结构,与 Scrappy 相比,你可以放置更多的逻辑和控制(好吧,绝对更容易)。
我没有看到最终数据的结构和类型,但它们似乎有点层次性,并且它们之间存在关系。我会将数据存储在带有列表的字典中,即使它们不是唯一的,然后将它们转储到例如MongoDB(使用 pymongo 非常简单,基本上是 3 个创建连接的命令,然后一个将其放入数据库)。收集完之后,我会关心关系、过滤和其他东西。通常稍后(使用用于此目的的工具,例如 pandas
)然后在报废期间要容易得多。
对于你的特殊情况,我会在你希望废弃的范围 (3M) 上做一个 for 循环,在每一步你都会 运行 访问 URL 的函数,如果不是 404 , 然后是 scrap info, 然后是 scrap owners, 然后是 scrap category... 这些应该是独立的功能,选择器会根据结构而变化,尽可能使用适当的 CSS 或 XPATH,否则你可以使用 find_elements
然后根据文本或 href 过滤它们(例如 /owner/
in href
of all a
)。
您的大部分要求似乎都非常适合 scrapy。您已经说过您可以简单地抓取项目列表,这是一个好的开始。我想你是说每个项目都有 links 给所有者、评论、用户。在这种情况下,您使用 response.xpath 获得 URL,然后使用 yield Request(URL, callback=parse_owner)
作为示例。您将希望 link 将不同的抓取数据放在一起,在这种情况下,您可以将 meta={'id': identifier}
添加到 Request()。正如@kotrfa 所说,转储到数据库可能是最好的,因为这听起来像是有一些交叉 linking 数据。
根据您提供的信息,我只能说这么多。更多信息将使我们的情况更加清晰。
这是 ItemSpider
.
from scrapy_redis.spiders import RedisSpider
import redis
class ItemSpider(RedisSpider):
name = 'item'
def parse(self, response):
# process to get item info.
r = redis.Redis(...)
r.lpush('user:start_urls', user_link)
return ...
这是 UserSpider
.
from scrapy_redis.spiders import RedisSpider
class UserSpider(RedisSpider):
name = 'user'
def parse(self, response):
# process to get user info.
return ...
然后将您的项目 url 添加到 redis 中的 item:start_urls
列表中。
最后,
scrapy crawl item
scrapy crawl user
应该提前考虑更高级的概念,例如避免重复项。至少上述解决方案已经将 ItemSpider
和 UserSpider
的时间表分开了。
由于 here 的帮助,我进入了这个解决方案,感谢@lnxpgn。
谁能提供更好的解决方案?或者提供更好的避免重复抓取的方案?