如何并行递归抓取网站?
How to website crawl with recursion in parallel?
我正在尝试在 Python 中使用 BeautifulSoup 并行抓取网站。
我给一个函数一个 url 和一个深度变量,它看起来像这样:
def recursive_crawl(url, depth):
if depth == 0:
return
links = fetch_links(url) # where I use the requests library
print("Level : ", depth, url)
for link in links:
if is_link_valid(link) is True:
recursive_crawl( URL , depth - 1)
输出部分类似于:
Level : 4 site.com
Level : 3 site.com/
Level : 2 site.com/research/
Level : 1 site.com/blog/
Level : 1 site.com/stories/
Level : 1 site.com/list-100/
Level : 1 site.com/cdn-cgi/l/email-protection
等等。
我的问题是这样的:
我正在使用 set()
,以避免转到已经访问过的链接,所以我遇到了共享内存问题。我可以并行实现这个递归网络爬虫吗?
注意:请不要推荐scrapy,我希望用BeautifulSoup.
这样的解析库来完成
我认为你使用的解析库不是很重要。看来您要问的是如何管理线程。这是我的一般方法:
- 建立 shared queue 个要访问的 URL 个。虽然主要内容是 URL 字符串,但您可能希望用一些补充信息包装它们:深度、引用链接以及您的蜘蛛需要的任何其他上下文信息。
- 构建一个维护 already-visited URL 列表的看门人对象。 (那个集合就是你提到的那个。)该对象有一个方法,它接受一个 URL 并决定是否将它添加到 #1 中的队列中。 (提交的 URLs 也被添加到集合中。您也可以在添加之前删除 GET 参数的 URLs。)在设置/实例化过程中,它可能会采用因其他原因限制爬网的参数.根据您选择的队列的种类,您还可以在此对象中进行一些优先级排序。由于您正在使用此网守来包装队列的输入,因此您可能还想包装队列的输出。
- 启动多个 worker Threads。您需要确保每个线程都使用引用单个网守实例的参数进行实例化。该线程包含一个包含所有 page-scraping 代码的循环。循环的每次迭代从网守队列中消耗一个 URL,并将任何发现的 URL 提交给网守。 (线程不关心 URL 是否已经在队列中。该责任属于看门人。)
我正在尝试在 Python 中使用 BeautifulSoup 并行抓取网站。
我给一个函数一个 url 和一个深度变量,它看起来像这样:
def recursive_crawl(url, depth):
if depth == 0:
return
links = fetch_links(url) # where I use the requests library
print("Level : ", depth, url)
for link in links:
if is_link_valid(link) is True:
recursive_crawl( URL , depth - 1)
输出部分类似于:
Level : 4 site.com
Level : 3 site.com/
Level : 2 site.com/research/
Level : 1 site.com/blog/
Level : 1 site.com/stories/
Level : 1 site.com/list-100/
Level : 1 site.com/cdn-cgi/l/email-protection
等等。
我的问题是这样的:
我正在使用 set()
,以避免转到已经访问过的链接,所以我遇到了共享内存问题。我可以并行实现这个递归网络爬虫吗?
注意:请不要推荐scrapy,我希望用BeautifulSoup.
这样的解析库来完成我认为你使用的解析库不是很重要。看来您要问的是如何管理线程。这是我的一般方法:
- 建立 shared queue 个要访问的 URL 个。虽然主要内容是 URL 字符串,但您可能希望用一些补充信息包装它们:深度、引用链接以及您的蜘蛛需要的任何其他上下文信息。
- 构建一个维护 already-visited URL 列表的看门人对象。 (那个集合就是你提到的那个。)该对象有一个方法,它接受一个 URL 并决定是否将它添加到 #1 中的队列中。 (提交的 URLs 也被添加到集合中。您也可以在添加之前删除 GET 参数的 URLs。)在设置/实例化过程中,它可能会采用因其他原因限制爬网的参数.根据您选择的队列的种类,您还可以在此对象中进行一些优先级排序。由于您正在使用此网守来包装队列的输入,因此您可能还想包装队列的输出。
- 启动多个 worker Threads。您需要确保每个线程都使用引用单个网守实例的参数进行实例化。该线程包含一个包含所有 page-scraping 代码的循环。循环的每次迭代从网守队列中消耗一个 URL,并将任何发现的 URL 提交给网守。 (线程不关心 URL 是否已经在队列中。该责任属于看门人。)