15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > 系统设计面试之网页爬虫

系统设计面试之网页爬虫

时间:2023-09-18 11:06:01 | 来源:网站运营

时间:2023-09-18 11:06:01 来源:网站运营

系统设计面试之网页爬虫:
本文翻译自GitHub上有关系统设计的repo:system design primer里面关于面试系统设计之网页爬虫,6w+的star。
Note: 为了避免重复,当前文档直接链接到系统设计主题的相关区域,请参考链接内容以获得综合的讨论点、权衡和替代方案。

第一步:概述用例和约束

收集这个问题的需求和范畴。 问相关问题来明确用例和约束。 讨论一些假设。
因为没有面试官来明确这些问题,所以我们自己将定义一些用例和约束。

用例

我们将问题的范畴限定在如下用例

超出范畴的用例

约束和假设

状态假设

使用更传统的系统 - 不要使用 solr 或 nutch 等现有系统。

计算使用

如果您应该运行背信息使用计算,请与您的面试官澄清。

方便的转换指南:

第二步:创建一个高层次设计

概述一个包括所有重要的组件的高层次设计

第三步:设计核心组件

深入每一个核心组件的细节

用例:服务爬取一个网址列表

假设我们有一个最初根据整体网站流行度排名的 links_to_crawl 列表。 如果这不是一个合理的假设,我们可以使用链接到外部内容(如 Yahoo,DMOZ 等)的热门网站为爬虫播种。

我们将使用表 crawled_links 来存储已处理的链接及其页面签名。

我们可以将 links_to_crawlcrawled_links 存储在键值 NoSQL Database 中。 对于 links_to_crawl 中的排名链接,我们可以使用 Redis 和排序集来维护页面链接的排名。我们应该讨论选择 SQL 或 NoSQL 之间的用例和权衡。

向面试官阐明你需要写多少代码

PagesDataStore爬虫服务中使用 NoSQL Database 的抽象:

class PagesDataStore(object): def __init__(self, db); self.db = db ... def add_link_to_crawl(self, url): """Add the given link to `links_to_crawl`.""" ... def remove_link_to_crawl(self, url): """Remove the given link from `links_to_crawl`.""" ... def reduce_priority_link_to_crawl(self, url): """Reduce the priority of a link in `links_to_crawl` to avoid cycles.""" ... def extract_max_priority_page(self): """Return the highest priority link in `links_to_crawl`.""" ... def insert_crawled_link(self, url, signature): """Add the given link to `crawled_links`.""" ... def crawled_similar(self, signature): """Determine if we've already crawled a page matching the given signature""" ...Page爬虫服务中的一个抽象,它封装了一个页面,以及它的内容,子URL和签名:

class Page(object): def __init__(self, url, contents, child_urls, signature): self.url = url self.contents = contents self.child_urls = child_urls self.signature = signatureCrawler爬虫服务中的主要类,由 PagePagesDataStore 组成。

class Crawler(object): def __init__(self, data_store, reverse_index_queue, doc_index_queue): self.data_store = data_store self.reverse_index_queue = reverse_index_queue self.doc_index_queue = doc_index_queue def create_signature(self, page): """Create signature based on url and contents.""" ... def crawl_page(self, page): for url in page.child_urls: self.data_store.add_link_to_crawl(url) page.signature = self.create_signature(page) self.data_store.remove_link_to_crawl(page.url) self.data_store.insert_crawled_link(page.url, page.signature) def crawl(self): while True: page = self.data_store.extract_max_priority_page() if page is None: break if self.data_store.crawled_similar(page.signature): self.data_store.reduce_priority_link_to_crawl(page.url) else: self.crawl_page(page)

处理重复

我们需要注意网络爬虫不会陷入无限循环,这会在当图形包含一个循环时发生。

向面试官阐明你需要写多少代码

我们要删除重复的网址:

class RemoveDuplicateUrls(MRJob): def mapper(self, _, line): yield line, 1 def reducer(self, key, values): total = sum(values) if total == 1: yield key, total检测重复内容更复杂。 我们可以根据页面内容生成签名,并比较这两个签名的相似性。 一些潜在的算法是 雅克卡指数 和余弦相似度。

确定何时更新爬取结果

需要定期爬取页面以确保新鲜度。 爬取结果可能有一个 timestamp 字段,表示爬取页面的最后时间。 在默认时间段(例如一周)之后,应刷新所有页面。 经常更新或更受欢迎的网站可以在较短的时间间隔内刷新。

虽然我们不会深入研究分析的细节,但我们可以进行一些数据挖掘以确定特定页面更新之前的平均时间,并使用该统计信息来确定重新爬取页面的频率。

我们也可能选择支持一个 Robots.txt 文件,该文件可让网站管理员控制爬取频率。

用例:用户输入搜索词并查看带有标题和摘要的相关页面列表

我们将会用一个公开的 REST 风格接口:

$ curl https://search.com/api/v1/search?query=hello+worldResponse:

{ "title": "foo's title", "snippet": "foo's snippet", "link": "https://foo.com",},{ "title": "bar's title", "snippet": "bar's snippet", "link": "https://bar.com",},{ "title": "baz's title", "snippet": "baz's snippet", "link": "https://baz.com",},用于内部通信,我们可以用 RPC。

第四步:扩展这个设计

基于给定的约束条件,确定并解决瓶颈问题。
重要提示: 不要简单的从最初的设计直接跳到最终的设计

说明您将迭代地执行这样的操作:1)Benchmark/Load 测试,2)Profile 出瓶颈,3)在评估替代方案和权衡时解决瓶颈,4)重复前面,可以参考在 AWS 上设计一个可以支持百万用户的系统这个用来解决如何迭代地扩展初始设计的例子。

重要的是讨论在初始设计中可能遇到的瓶颈,以及如何解决每个瓶颈。比如,在多个 Web 服务器上添加负载平衡器可以解决哪些问题?CDN 解决哪些问题?主从复制解决哪些问题? 替代方案是什么和怎么对每一个替代方案进行权衡比较?

我们将介绍一些组件来完成设计,并解决可伸缩性问题。内部的负载平衡器并不能减少杂乱。

为了避免重复的讨论, 参考以下系统设计主题获取主要讨论要点、权衡和替代方案:

有些搜索非常受欢迎,而其他搜索只执行一次。 流行查询可以从内存缓存**(例如 Redis 或 Memcached)提供,以减少响应时间并避免重载反向索引服务文档服务内存缓存对于处理不均匀分布的流量和流量峰值也很有用。 从内存顺序读取 1 MB 大约需要 250 微秒,而从 SSD 读取需要 4 倍,而从磁盘读取需要 80 倍。1

以下是对爬取服务的一些其他优化:

额外的话题

是否更深入探讨额外主题,取决于问题的范围和面试剩余的时间。

SQL 扩展模式

NoSQL

缓存

异步和微服务

通信

安全

参考安全。

延迟数字

见每个程序员都应该知道的延迟数。

持续进行

关键词:爬虫,设计,系统

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭