Spaces:
Sleeping
Sleeping
import streamlit as st | |
import requests | |
from bs4 import BeautifulSoup | |
import pandas as pd | |
import base64 | |
# Function to set background image | |
def set_background(image_file): | |
with open(image_file, "rb") as image_file: | |
encoded_string = base64.b64encode(image_file.read()).decode() | |
st.markdown( | |
f""" | |
<style> | |
.stApp {{ | |
background-image: url(data:image/png;base64,{encoded_string}); | |
background-size: cover; | |
}} | |
</style> | |
""", | |
unsafe_allow_html=True | |
) | |
# Set the background image | |
set_background('ddog.png') | |
# Streamlit app title | |
st.title('寵物診所資訊爬蟲') | |
# 網址列表 | |
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/c000081.html', | |
'https://www.tw-animal.com/pet/171211/c000848.html', | |
'https://www.tw-animal.com/pet/171211/c000045.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/c000217.html', | |
'https://www.tw-animal.com/pet/171211/c000802.html', | |
'https://www.tw-animal.com/pet/171211/c001034.html', | |
'https://www.tw-animal.com/pet/171211/c001453.html' | |
] | |
# 讓使用者輸入評分門檻 | |
min_rating = st.slider("請選擇想篩選的最低評分", 0.0, 5.0, 4.5, 0.1) | |
if st.button('開始爬蟲'): | |
# 建立空的列表來儲存每一頁的資料 | |
all_data = [] | |
# 顯示進度條 | |
progress_bar = st.progress(0) | |
status_text = st.empty() | |
# 遍歷每個網址 | |
for i, url in enumerate(urls): | |
# 更新進度條和狀態文字 | |
progress = int((i + 1) / len(urls) * 100) | |
progress_bar.progress(progress) | |
status_text.text(f'正在處理第 {i+1} 個網址,共 {len(urls)} 個') | |
# 發送HTTP請求獲取頁面內容 | |
response = requests.get(url) | |
response.encoding = 'utf-8' | |
# 使用BeautifulSoup解析頁面 | |
soup = BeautifulSoup(response.text, 'html.parser') | |
# 抓取標題、手機、地址和評分 | |
title = soup.find('h1', class_='t-intro__title').get_text(strip=True) | |
phone = soup.find('a', href=lambda href: href and href.startswith('tel:')).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)) | |
# 將評分大於或等於使用者輸入的資料存入列表 | |
if rating >= min_rating: | |
all_data.append({ | |
'標題': title, | |
'手機': phone, | |
'地址': address, | |
'評分': rating | |
}) | |
# 將所有符合條件的資料轉換為DataFrame | |
df = pd.DataFrame(all_data) | |
# 檢查是否有符合條件的資料 | |
if not df.empty: | |
# 輸出篩選後的DataFrame | |
st.dataframe(df) | |
# 提供下載 CSV 檔案的選項 | |
csv = df.to_csv(index=False) | |
st.download_button( | |
label="下載 CSV 檔案", | |
data=csv, | |
file_name="pet_clinics.csv", | |
mime="text/csv", | |
) | |
else: | |
st.write(f"沒有找到評分大於或等於 {min_rating} 的資料。") | |
# 清除進度條和狀態文字 | |
progress_bar.empty() | |
status_text.empty() | |
# LINE Notify 部分 | |
st.header('傳送至 LINE Notify') | |
token = st.text_input("請輸入 LINE Notify 權杖") | |
if st.button('傳送至 LINE'): | |
if 'df' in locals() and not df.empty: | |
msg = df.to_string(index=False) | |
# 傳送 LINE Notify 訊息 | |
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) | |
return r.status_code | |
# 呼叫傳送 LINE Notify 函數 | |
status_code = send_line_notify(token, msg) | |
if status_code == 200: | |
st.success('成功傳送至 LINE Notify!') | |
else: | |
st.error('傳送失敗,請檢查您的權杖是否正確。') | |
else: | |
st.warning('沒有資料可以傳送,請先執行爬蟲。') |