我正在使用网络抓取工具。抓取工具是为具有多个类别的网页构建的。这些类别可以有子类别,子类别也是如此。
所以它看起来像这样:
所以我做了一个递归方法,它提供了深度的第一次搜索。
def deep_search(url):
if is_leaf(url):
return get_data(url)
for url in get_subcategories(url):
deep_search(url)
此方法工作正常,但需要很长时间才能完成,因此存在连接中断或其他错误引发的情况。
如果发生错误并且下次从此状态继续,您将如何记住状态?
我不能记得最后一次' url'或类别,因为有循环,程序不知道什么' urls'和类别已存储在上部循环中。
答案 0 :(得分:1)
如果搜索路径的顺序是稳定的(每次脚本以相同的顺序访问子类别),那么您可以在DFS中维护一个分支编号列表,并使其保持持久性 - 将其保存在文件或数据库中:
current_path = [] # save the path currently visited
def deep_search(url, last_saved_path=None):
if is_leaf(url):
if last_saved_path:
# Continue where you left off
if path_reached(last_saved_path):
data = get_data(url)
else: # first run
data = get_data(url)
# save the whole path persistently
save_to_file(current_path)
# add data to result
else:
for index, url in enumerate(get_subcategories(url)):
current_path.append(index)
deep_search(url, last_saved_path)
del current_path[-1]
def path_reached(old_path):
print old_path, current_path
# if the path has been visited in last run
for i,index in enumerate(current_path):
if index < old_path[i]:
return False
elif index > old_path[i]:
return True
return True
第二次运行抓取工具时,您可以加载已保存的路径并从上次停止的位置开始:
# first run
deep_search(url)
# subsequent runs
last_path = load_last_saved_path_from_file()
deep_search(url, last_path)
那就是说,我认为在网络爬虫中有两种任务:遍历图形和下载数据。并且最好将它们分开:使用上面的DFS算法(加上逻辑来跳过已访问的路径)来遍历链接,并将下载URL保存在队列中;然后启动一堆工作人员从队列中获取URL并下载。这样,您只需要在中断时记录队列中的当前位置。
我向你推荐scrapy
,我没有读过scrapy的来源,但我想它实现了上述所有内容,等等。
答案 1 :(得分:0)
作为一个简单的提示,您可以使用try-except
语句来处理错误并保存相对url
,作为此类任务的一个不错的选择,您可以使用collections.deque
一个容量,并在下一次迭代中检查它。
演示:
来自集合import deque
def deep_search(url,deq=deque(maxlen=1)):
if is_leaf(url):
return get_data(url)
try:
for url in get_subcategories(url):
if deq[0]==url:
deep_search(url,deq)
except : #you can put the error title after except
deq.append(url)
但作为处理网络的更加pythonic方式,您可以使用networkx。
NetworkX是一个Python语言软件包,用于创建,操作和研究复杂网络的结构,动态和功能。