我正在尝试创建一个网络抓取应用程序,该应用程序从某个房地产网站获取数据并返回包括价格和城市的数据集。返回数据集后,脚本应包含一个滑块,允许我设置价格并按其进行过滤。然而,每当我稍微移动滑块时,StreamLit 都会重新运行脚本,并且网络抓取、清理和结构化数据的过程会重新开始。我尝试过使用
session_state
,但感觉好像我错过了一些东西,因为它仍然重新加载整个东西。我能做什么呢?
starter = st.checkbox('Begin Data Gathering')
if starter:
def dataframe_creation(linker):
link = linker
br = requests.get(link)
page = br.content
soup = bs(page, 'html.parser')
#PRICES
advert = soup.find_all("div", attrs={"class": "advert__content-header"})
price_list = [] ##################FINAL COLUMN
import re
html_code = str(advert)
matches = re.findall(r'<b>(€)</b>(.*?)</span>', html_code)
for match in matches:
euro = match[0]
number = match[1]
number = number.split(" ")[0]
number22 = number.replace(".", "")
price_list.append(number22)
# CITY LOCATION
city = soup.find_all("div", attrs={"class": "advert__content-place"})
city2 = str(city)
city3 = re.findall(r'>(.*?)</div>', city2)
city_list = [] #### THIS DATA
for z in city3:
kols = z.split(",")[0]
city_list.append(kols)
finale1 = pd.DataFrame({
"Prices": price_list,
"Cities": city_list})
finale1['Prices'] = finale1['Prices'].astype(int)
finale1
slider = st.slider("Price in Euros", min_value=200, max_value=5000, step=10)
finale1[finale1['Prices'] <= int(slider)]
本质上,您所缺少的部分称为缓存。正如您所说,每当应用程序的状态发生变化时,即您布置的任何 Streamlit 组件的状态发生变化时,Streamlit 都会在服务器上重新渲染页面并将其返回给客户端(浏览器)。这是预期的行为。本质上,您缺少的部分称为缓存。正如您所说,每次应用程序的状态发生变化时,即您布置的任何 Streamlit 组件的状态发生变化时,streamlit 都会重新渲染服务器上的页面并将其返回给客户端(浏览器)。这是预期的行为。
为了提高这些重新渲染的效率,Streamlit 有两种机制,分别充当某种内存 session_states 和缓存。作为某种总结:
示例: 如果您有一个 Streamlit 页面,其中包含用于冗长过程(例如读取非常大的 csv)的代码,则每次您通过操作 Streamlit 元素更改页面状态时,它都会执行您的页面代码以再次底部读取csv 并使您的应用程序变慢。
import pandas as pd
<page layout>
df = pd.read_csv("some.csv") # Rexecuted on every action.
<page layout>
为了纠正这种行为,我们将冗长的过程封装在一个函数中并添加一个装饰器(就是这样)。新代码将如下所示。
import pandas as pd
<page layout>
@st.cache_data
def csv_reader(path):
return pd.read_csv("some.csv")
df = csv_reader(path="some.csv")
<page layout>
有点冗长,但好多了。现在,我们第一次渲染页面时,将执行函数 csv_reader。执行结束时,将使用传递给函数的名称和值创建哈希,并且 (hash, function_result) 将作为键值对存储在内部字典中。下次重新渲染页面并且 Streamlit 调用该函数时,它将首先查找该函数是否已为该内部字典中的这些参数调用,然后由于情况如此,它将从字典中恢复结果,而不必实际再次重新执行该函数。您已经避免再重新执行那个冗长的部分了。
如果函数总是使用不同的参数调用或者其中包含随机性元素,则这种方法没有用,但我相信情况并非如此。我没有完整的代码要测试,但我相信通过使用缓存装饰器包装您的函数并显式返回数据帧,您的问题将会得到解决,例如,
@st.cache_data
def dataframe_creation(linker):
...
return finale1
finale1 = dataframe_creation(linker=some_data)