Spaces:
Sleeping
Sleeping
| # 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() |