在 Python 3 中避免堆栈溢出
Avoiding a stack overflow in Python 3
免责声明:我完全不了解计算机科学,也不了解幕后发生的任何事情的内部运作方式。使用 Internet 上的所有内容自学编码。
Python版本:
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit(Intel)] on win32
在普通解析器上工作,其主要目的是获取图像的全尺寸 url 图像,将其保存到文件中以供稍后下载,然后移动到下一个图像,这由于相关网站的糟糕网络架构,这几乎是强制性的。当我完成程序时,在第 976 次执行时遇到错误。
RuntimeError: maximum recursion depth exceeded in comparison
经过研究,发现问题出在"Stack overflow"。但是,目前我不知道如何在不造成任何显着性能下降的情况下解决问题。 (虽然,这不是真正的问题,因为我只是为了学习而这样做。)
这让我想到了我的问题,我该如何解决这个问题,我在哪里可以了解更多关于这些事情的信息,比如什么是 Stack Overflow?
(程序运行良好,堆栈溢出停止)
import requests
from bs4 import BeautifulSoup
def somesite_parsing(url):
connection = requests.get(url)
html = connection.text
soup = BeautifulSoup(html, "html.parser")
# The exception is necessary due to the web architecture.
# Images that don't have different versions by size have an img tag.
# Returns "http://www.somesite.net/tag_tag_tag.full.jpg"
try:
semi_link = soup.select("html > body > #wrapper > #body > #content > #large > a")
full_link = semi_link[0].get("href")
print(full_link)
except IndexError:
semi_link = soup.select("html > body > #wrapper > #body > #content > #large > img")
full_link = semi_link[0].get("src")
print(full_link)
# File was created during testing so I switched to appending.
# Saves link into folder.
fx = open("list_file.txt", "a")
fx.write(full_link + "\n")
fx.close()
# Fetches the next url.
# Returns "/id_number"
next_link = soup.select("html > body > #wrapper > #body > #menu > .smallthumbs > li > a")
next_link = next_link[0].get("href")
next_link = "http://www.somesite.net" + next_link
print(next_link)
print()
somesite_parsing(next_link)
somesite_parsing("http://www.somesite.net/1905220")
嵌套函数调用过多时会出现栈溢出。这主要发生在函数继续无休止地调用自身时。
在您的例子中,您在自身内部调用 somesite_parsing
。这最终会导致堆栈溢出。
有几种方法可以避免这种情况。我建议围绕您的解析进行循环。
将somesite_parsing
改为return下一个link,而不是调用自身,你可以这样做:
next_link = "http://www.somesite.net/1905220"
while next_link:
next_link = somesite_parsing(next_link)
这将允许您从 somesite_parsing
return 一个 falsy 值来停止循环。
'while' 循环正是您所需要的。
这是我的做法,虽然我没有运行代码。
import requests
import json
start_url = "http//your_start_url"
def save_data(data):
"""Or however you want to save your data.
I like .jsonl, see http://jsonlines.org/"""
data = json.dumps(data)
fx = open("data_file.jsonl", "a") #see
fx.write(data + "\n")
fx.close()
def get_url(url):
"This returns something similar to an 'option type'."
r = requests.get(url)
return {"success": r.ok,
"next_url": parse_your_response_for_next_url(r.text),
"page": r.text,
"url": url}
##################################
response = get_url(start_url)
while respose["success"]:
save_data(response)
response = get_url(response["next_url"])
(我使用的是伪 'option type' 和 jsonl 文件。但这只是一种风格决定。参见 https://en.wikipedia.org/wiki/Option_type and http://jsonlines.org/)
此外,如果您发出足够多的请求以达到最大递归深度,那么用 @functools.lru_cache
或一些磁盘支持的替代方法存储响应可能会很好。
免责声明:我完全不了解计算机科学,也不了解幕后发生的任何事情的内部运作方式。使用 Internet 上的所有内容自学编码。
Python版本:
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit(Intel)] on win32
在普通解析器上工作,其主要目的是获取图像的全尺寸 url 图像,将其保存到文件中以供稍后下载,然后移动到下一个图像,这由于相关网站的糟糕网络架构,这几乎是强制性的。当我完成程序时,在第 976 次执行时遇到错误。
RuntimeError: maximum recursion depth exceeded in comparison
经过研究,发现问题出在"Stack overflow"。但是,目前我不知道如何在不造成任何显着性能下降的情况下解决问题。 (虽然,这不是真正的问题,因为我只是为了学习而这样做。)
这让我想到了我的问题,我该如何解决这个问题,我在哪里可以了解更多关于这些事情的信息,比如什么是 Stack Overflow?
(程序运行良好,堆栈溢出停止)
import requests
from bs4 import BeautifulSoup
def somesite_parsing(url):
connection = requests.get(url)
html = connection.text
soup = BeautifulSoup(html, "html.parser")
# The exception is necessary due to the web architecture.
# Images that don't have different versions by size have an img tag.
# Returns "http://www.somesite.net/tag_tag_tag.full.jpg"
try:
semi_link = soup.select("html > body > #wrapper > #body > #content > #large > a")
full_link = semi_link[0].get("href")
print(full_link)
except IndexError:
semi_link = soup.select("html > body > #wrapper > #body > #content > #large > img")
full_link = semi_link[0].get("src")
print(full_link)
# File was created during testing so I switched to appending.
# Saves link into folder.
fx = open("list_file.txt", "a")
fx.write(full_link + "\n")
fx.close()
# Fetches the next url.
# Returns "/id_number"
next_link = soup.select("html > body > #wrapper > #body > #menu > .smallthumbs > li > a")
next_link = next_link[0].get("href")
next_link = "http://www.somesite.net" + next_link
print(next_link)
print()
somesite_parsing(next_link)
somesite_parsing("http://www.somesite.net/1905220")
嵌套函数调用过多时会出现栈溢出。这主要发生在函数继续无休止地调用自身时。
在您的例子中,您在自身内部调用 somesite_parsing
。这最终会导致堆栈溢出。
有几种方法可以避免这种情况。我建议围绕您的解析进行循环。
将somesite_parsing
改为return下一个link,而不是调用自身,你可以这样做:
next_link = "http://www.somesite.net/1905220"
while next_link:
next_link = somesite_parsing(next_link)
这将允许您从 somesite_parsing
return 一个 falsy 值来停止循环。
'while' 循环正是您所需要的。
这是我的做法,虽然我没有运行代码。
import requests
import json
start_url = "http//your_start_url"
def save_data(data):
"""Or however you want to save your data.
I like .jsonl, see http://jsonlines.org/"""
data = json.dumps(data)
fx = open("data_file.jsonl", "a") #see
fx.write(data + "\n")
fx.close()
def get_url(url):
"This returns something similar to an 'option type'."
r = requests.get(url)
return {"success": r.ok,
"next_url": parse_your_response_for_next_url(r.text),
"page": r.text,
"url": url}
##################################
response = get_url(start_url)
while respose["success"]:
save_data(response)
response = get_url(response["next_url"])
(我使用的是伪 'option type' 和 jsonl 文件。但这只是一种风格决定。参见 https://en.wikipedia.org/wiki/Option_type and http://jsonlines.org/)
此外,如果您发出足够多的请求以达到最大递归深度,那么用 @functools.lru_cache
或一些磁盘支持的替代方法存储响应可能会很好。