yellowpages / app.py
NguyNhu's picture
Update app.py
3d5bbcf verified
# app.py
import gradio as gr
import sys
import os
import subprocess
import json # Có thể cần nếu script scraper output JSON
# Thêm đường dẫn thư mục hiện tại vào sys.path để Python có thể tìm thấy script scraper
# Điều này hoạt động tốt khi script scraper được import trực tiếp
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# --- Tùy chọn 1: Thử import hàm trực tiếp từ script scraper ---
# Đây là cách ƯU TIÊN nếu script scraper của bạn có hàm dễ gọi (ví dụ: parse_listing)
# Thay thế 'yellowpages' bằng tên file .py thật của script scraper của bạn (KHÔNG có .py)
# Thay thế 'parse_listing_function' bằng tên hàm trong script của bạn nhận keyword và location
yellowpages_script_name = 'yellowpages' # Tên file script không kèm .py
scraper_function_name = 'parse_listing_function' # Tên hàm trong script
scraper_function = None
try:
# Import module (tên file)
scraper_module = __import__(yellowpages_script_name)
# Lấy hàm từ module
scraper_function = getattr(scraper_module, scraper_function_name, None)
if scraper_function is None:
print(f"Cảnh báo: Không tìm thấy hàm '{scraper_function_name}' trong file '{yellowpages_script_name}.py'.")
# Nếu không tìm thấy hàm, scraper_function vẫn là None
else:
print(f"Đã import thành công hàm '{scraper_function_name}' từ '{yellowpages_script_name}.py'.")
except ModuleNotFoundError:
print(f"Cảnh báo: Không tìm thấy file '{yellowpages_script_name}.py'. Sẽ thử chạy bằng subprocess.")
scraper_function = None # Đảm bảo hàm là None nếu import lỗi
except AttributeError:
print(f"Cảnh báo: Lỗi AttributeError khi import hàm '{scraper_function_name}' từ file '{yellowpages_script_name}.py'.")
scraper_function = None
except Exception as e:
print(f"Lỗi không xác định khi import script scraper: {e}")
scraper_function = None
# --- Tùy chọn 2: Hàm chạy script bằng subprocess (Nếu không import được hàm) ---
def run_scraper_via_cli(script_name_with_py, *args):
"""
Chạy script scraper như một tiến trình con từ dòng lệnh.
Args:
script_name_with_py: Tên file script bao gồm đuôi .py (ví dụ: 'yellowpages.py').
*args: Các đối số dòng lệnh cần truyền cho script.
Returns:
Output từ script (stdout) hoặc thông báo lỗi.
"""
print(f"Đang thử chạy script '{script_name_with_py}' qua command line với args: {args}")
try:
# Lệnh để chạy script
# subprocess.run sẽ tìm script trong PYTHONPATH hoặc PATH.
# Do đã thêm thư mục hiện tại vào sys.path, hy vọng python có thể tìm thấy script_name_with_py
command = [sys.executable, script_name_with_py] + list(args) # sys.executable đảm bảo dùng đúng python
print(f"Lệnh chạy: {' '.join(command)}")
result = subprocess.run(
command,
capture_output=True,
text=True, # Bắt output dưới dạng text
check=False # KHÔNG báo lỗi nếu script trả về mã lỗi khác 0, chỉ bắt output/error
)
# Kiểm tra mã trả về (return code)
if result.returncode != 0:
# Nếu có lỗi khi chạy script (ví dụ: lỗi cú pháp trong script, lỗi runtime trong script)
print(f"Script '{script_name_with_py}' trả về mã lỗi {result.returncode}")
print(f"Stderr:\n{result.stderr}")
print(f"Stdout:\n{result.stdout}")
# Cố gắng trả về lỗi từ stderr hoặc stdout
return f"Lỗi khi chạy script '{script_name_with_py}' (code {result.returncode}):\n{result.stderr or result.stdout or 'Không có thông báo lỗi cụ thể.'}"
# Trả về output chuẩn của script
# Script có thể in kết quả trực tiếp hoặc in JSON/CSV
print(f"Script '{script_name_with_py}' chạy thành công.")
print(f"Stdout:\n{result.stdout}")
# Có thể cần xử lý result.stdout ở đây nếu script in ra dữ liệu cấu trúc (JSON)
return result.stdout # Trả về toàn bộ stdout
except FileNotFoundError:
# Lỗi này xảy ra nếu 'python' hoặc 'script_name_with_py' không tìm thấy
# Lỗi 'script_name_with_py' không tìm thấy đã được báo ở trên nếu dùng import
# Nhưng vẫn giữ lại đây để an toàn
return f"Lỗi: Không tìm thấy file script '{script_name_with_py}' để chạy. Vui lòng đảm bảo file đã được upload."
except Exception as e:
# Các lỗi khác không mong muốn
import traceback
traceback.print_exc()
return f"Đã xảy ra lỗi không xác định khi chạy subprocess: {e}"
# Hàm chính được gọi từ Gradio interface
def scrape_data(scraper_choice, input1, input2=None):
"""
Hàm này nhận lựa chọn scraper và các input tương ứng, sau đó gọi phương thức cạo phù hợp.
"""
if scraper_choice == "Yellow Pages":
if not input1 or not input2:
return "Vui lòng nhập cả Từ khóa tìm kiếm và Địa điểm cho Yellow Pages."
print(f"Yêu cầu cạo Yellow Pages: Từ khóa='{input1}', Địa điểm='{input2}'")
# Ưu tiên dùng hàm import nếu có
if scraper_function:
print("Đang chạy bằng cách import hàm trực tiếp...")
try:
scraped_data = scraper_function(input1, input2)
# Định dạng kết quả từ list of dicts sang string
output_text = "Kết quả từ Yellow Pages:\n\n"
if not scraped_data:
return output_text + "Không tìm thấy kết quả nào."
# Nếu hàm trả về list of dicts, định dạng nó
if isinstance(scraped_data, list) and all(isinstance(item, dict) for item in scraped_data):
for i, item in enumerate(scraped_data):
output_text += f"--- {i+1} ---\n"
# Điều chỉnh các key này ('business_name', 'telephone', v.v.)
# để phù hợp với các key mà script scraper của bạn sử dụng
output_text += f"Name: {item.get('business_name', 'N/A')}\n"
output_text += f"Phone: {item.get('telephone', 'N/A')}\n"
output_text += f"Address: {item.get('street', 'N/A')}, {item.get('locality', 'N/A')}, {item.get('region', 'N/A')} {item.get('zipcode', 'N/A')}\n"
output_text += f"Website: {item.get('website', 'N/A')}\n"
output_text += f"Rating: {item.get('rating', 'N/A')}\n"
output_text += f"Rank: {item.get('rank', 'N/A')}\n"
output_text += f"URL: {item.get('url', 'N/A')}\n"
output_text += "------------\n"
return output_text
else:
# Nếu hàm trả về dạng khác (ví dụ: string báo lỗi)
return f"Kết quả trực tiếp từ hàm scraper:\n{scraped_data}"
except Exception as e:
import traceback
traceback.print_exc()
return f"Lỗi xảy ra khi gọi hàm scraper trực tiếp: {e}"
else:
# Nếu không import được hàm, dùng subprocess để chạy file .py
print("Đang chạy bằng subprocess...")
# Đảm bảo tên file đúng và đối số truyền vào phù hợp với script CLI
# Đối với script yellowpages.py trong repo ScrapeDataCom, cú pháp CLI có thể là:
# python yellowpages.py "keyword" "location"
return run_scraper_via_cli(f"{yellowpages_script_name}.py", input1, input2)
# --- Thêm các trường hợp cho scraper khác tại đây ---
# elif scraper_choice == "Google Search":
# if not input1:
# return "Vui lòng nhập Từ khóa tìm kiếm cho Google Search."
# print(f"Yêu cầu cạo Google Search: Từ khóa='{input1}'")
# # Cần tích hợp logic gọi script Google Search tương tự Yellow Pages
# # Ví dụ: return run_scraper_via_cli("googlesearch_results.py", input1)
# return "Chức năng Google Search chưa được tích hợp hoàn chỉnh."
#
# elif scraper_choice == "Amazon":
# if not input1:
# return "Vui lòng nhập URL sản phẩm hoặc từ khóa cho Amazon."
# print(f"Yêu cầu cạo Amazon: Input='{input1}'")
# # Cần tích hợp logic gọi script Amazon
# # Ví dụ: return run_scraper_via_cli("amazon_products.py", input1) # Giả định script Amazon nhận 1 đối số
# return "Chức năng Amazon chưa được tích hợp hoàn chỉnh."
else:
return "Vui lòng chọn một Scraper từ danh sách."
# Tạo giao diện Gradio
with gr.Blocks() as demo:
gr.Markdown("# Demo Các Web Scraper từ ScrapeDataCom")
gr.Markdown("Chọn một scraper và nhập các thông tin cần thiết. Kết quả sẽ hiển thị bên dưới.")
scraper_dropdown = gr.Dropdown(
["Yellow Pages"], # Thêm tên các scraper khác vào list này sau khi tích hợp
label="Chọn Scraper",
value="Yellow Pages" # Giá trị mặc định
)
# Các input fields. Có thể cần điều chỉnh hiển thị dựa trên lựa chọn dropdown
input_keyword = gr.Textbox(label="Từ khóa", placeholder="Ví dụ: restaurants")
input_location = gr.Textbox(label="Địa điểm", placeholder="Ví dụ: Boston,MA")
# input_generic = gr.Textbox(label="Input (URL hoặc Từ khóa)", placeholder="Nhập URL hoặc từ khóa tùy scraper", visible=False) # Input chung
run_button = gr.Button("Chạy Scraper")
output_text = gr.Textbox(label="Kết quả", lines=20, max_lines=50, interactive=False) # interactive=False để không cho chỉnh sửa
# Định nghĩa hành động khi nút được nhấn
run_button.click(
scrape_data,
inputs=[scraper_dropdown, input_keyword, input_location], # Truyền tất cả các input tiềm năng
outputs=output_text
)
# Ví dụ về cách thay đổi hiển thị input dựa trên dropdown (có thể phức tạp tùy vào số lượng scraper)
# def update_inputs(choice):
# if choice == "Yellow Pages":
# return gr.update(visible=True, label="Từ khóa"), gr.update(visible=True, label="Địa điểm"), gr.update(visible=False)
# elif choice == "Google Search":
# return gr.update(visible=True, label="Từ khóa"), gr.update(visible=False), gr.update(visible=False) # Giả sử Google chỉ cần từ khóa
# # Thêm các trường hợp khác
# return gr.update(visible=False), gr.update(visible=False), gr.update(visible=True, label=f"Input cho {choice}") # Default case
#
# scraper_dropdown.change(
# update_inputs,
# inputs=scraper_dropdown,
# outputs=[input_keyword, input_location, input_generic] # Liệt kê tất cả input có thể thay đổi
# )
# Chạy ứng dụng Gradio
# Trong Hugging Face Space, dòng này sẽ tự động được gọi
# Khi chạy cục bộ, nó sẽ mở giao diện trong trình duyệt
iface = demo # Gán demo cho iface để tương thích với iface.launch() nếu cần, hoặc chỉ dùng demo.launch()
demo.launch()