PET_STREAMLIT / app.py
Roberta2024's picture
Update app.py
8a76c02 verified
raw
history blame
6.23 kB
import streamlit as st
import requests
from bs4 import BeautifulSoup
import pandas as pd
import plotly.express as px
import base64
import folium
from streamlit_folium import st_folium
from geopy.geocoders import Nominatim
# Function to set background image
def set_background(png_file):
with open(png_file, "rb") as f:
data = f.read()
encoded = base64.b64encode(data).decode()
st.markdown(
f"""
<style>
.stApp {{
background: url(data:image/png;base64,{encoded});
background-size: cover;
}}
</style>
""",
unsafe_allow_html=True
)
# Set the background image
set_background('CAT.png')
# Title of the app
st.title("寵物醫院評分查詢")
# User input for minimum rating
min_rating = st.slider("請輸入想查詢的最低評分:", 1.0, 5.0, 3.5)
# List of URLs to scrape
urls = [
"https://www.tw-animal.com/pet/171211/c000196.html",
"https://www.tw-animal.com/pet/171211/c000186.html",
"https://www.tw-animal.com/pet/171211/c000186.html",
"https://www.tw-animal.com/pet/171211/c000081.html",
"https://www.tw-animal.com/pet/171211/c001166.html",
"https://www.tw-animal.com/pet/171211/c000773.html",
"https://www.tw-animal.com/pet/171211/c001038.html",
"https://www.tw-animal.com/pet/171211/c000741.html",
"https://www.tw-animal.com/pet/171211/c001451.html",
"https://www.tw-animal.com/pet/171211/c000102.html",
"https://www.tw-animal.com/pet/171211/c000757.html",
"https://www.tw-animal.com/pet/171211/c000703.html",
"https://www.tw-animal.com/pet/171211/c000481.html",
"https://www.tw-animal.com/pet/171211/c000971.html",
"https://www.tw-animal.com/pet/171211/c000187.html",
"https://www.tw-animal.com/pet/171211/c001357.html",
"https://www.tw-animal.com/pet/171211/c001065.html",
"https://www.tw-animal.com/pet/171211/c000165.html",
"https://www.tw-animal.com/pet/171211/c001138.html",
"https://www.tw-animal.com/pet/171211/c000484.html",
"https://www.tw-animal.com/pet/171211/c001089.html",
"https://www.tw-animal.com/pet/171211/c001252.html"
]
# Create an empty list to store the extracted data
data_list = []
# Initialize the geolocator
geolocator = Nominatim(user_agent="geoapiExercises")
# Scrape data when the button is pressed
if st.button('開始爬取資料'):
st.write("正在爬取資料,請稍候...")
# Loop through each URL and extract the data
for url in urls:
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
# Extract data
title = soup.find('h1', class_='t-intro__title').get_text(strip=True)
phone = soup.find('a', class_='t-font-large').get_text(strip=True)
address = soup.find('a', class_='t-font-medium').get_text(strip=True)
rating = float(soup.find('span', class_='t-intro__recommand').get_text(strip=True))
# Append the data to the list if rating meets the threshold
if rating >= min_rating:
try:
# Geocode the address to get the latitude and longitude
location = geolocator.geocode(address)
if location:
data_list.append({
"標題": title,
"手機": phone,
"地址": address,
"評分": rating,
"經度": location.longitude,
"緯度": location.latitude
})
except Exception as e:
st.warning(f"無法獲取經緯度:{e}")
# If data was scraped successfully
if data_list:
df1 = pd.DataFrame(data_list)
# Extract the region from the address (assuming region is part of the address)
df1['區域'] = df1['地址'].apply(lambda x: x.split()[0])
# Group by region and merge hospitals in the same region
grouped_df = df1.groupby('區域').agg({
'標題': lambda x: ' | '.join(x),
'手機': lambda x: ' | '.join(x),
'地址': lambda x: ' | '.join(x),
'評分': 'mean' # Aggregation for average rating
}).reset_index()
# Display the dataframe
st.dataframe(df1)
# Display Plotly bar chart
bar_fig = px.bar(grouped_df, x='區域', y='評分', title="各區域寵物醫院統計", labels={'評分':'平均評分', '區域':'區域'})
st.plotly_chart(bar_fig)
# Display Plotly pie chart
pie_fig = px.pie(grouped_df, names='區域', values='評分', title="各區域寵物醫院比例")
st.plotly_chart(pie_fig)
# Display the map
if st.button('顯示地圖'):
# Create a folium map centered around the average location
map_center = [df1['緯度'].mean(), df1['經度'].mean()]
pet_map = folium.Map(location=map_center, zoom_start=12)
# Add markers for each hospital
for index, row in df1.iterrows():
folium.Marker(
location=[row['緯度'], row['經度']],
popup=f"{row['標題']} (評分: {row['評分']})",
tooltip=row['標題']
).add_to(pet_map)
# Render the map using streamlit_folium
st_folium(pet_map, width=700, height=500)
# Sending notification to LINE
if st.button('發送前五筆資料到Line'):
msg = df1[:5].to_string(index=False)
token = "DzMHaXosskpjtGuIjuB7NIcQ5TIoptLz7l7VYzV3Wp4" # Replace with your LINE Notify token
# Send message to LINE
def send_line_notify(token, msg):
headers = {
"Authorization": "Bearer " + token,
"Content-Type": "application/x-www-form-urlencoded"
}
params = {"message": msg}
r = requests.post("https://notify-api.line.me/api/notify", headers=headers, params=params)
send_line_notify(token, msg)
st.success('資料已成功發送到 Line!')
else:
st.warning('沒有符合條件的資料。')