#!/usr/bin/env python3
"""
832平台爬虫 - 河南地区商品数据抓取
目标：供应商名称、商品名称、单价、销量、联系方式
"""

import asyncio
import csv
import os
from datetime import datetime
from playwright.async_api import async_playwright

# 配置
CONFIG = {
    "username": "chinadavid",
    "password": "dabai123123",
    "area_code": "410000",  # 河南省
    "output_file": "henan_products.csv",
    "login_url": "https://ys.fupin832.com/",
    "product_url": "https://ys.fupin832.com/product/list?areaCode=410000"
}

# CSV 表头
CSV_HEADERS = [
    "序号",
    "供应商名称",
    "商品名称",
    "单价(元)",
    "销量",
    "联系方式",
    "商品链接",
    "抓取时间"
]

class Spider832:
    def __init__(self):
        self.browser = None
        self.context = None
        self.page = None
        self.products = []
    
    async def init_browser(self):
        """初始化浏览器"""
        print("🚀 启动浏览器...")
        playwright = await async_playwright().start()
        self.browser = await playwright.chromium.launch(
            headless=True,  # 无头模式
            args=['--no-sandbox', '--disable-setuid-sandbox']  # 服务器环境需要的参数
        )
        self.context = await self.browser.new_context(
            viewport={"width": 1920, "height": 1080},
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        )
        self.page = await self.context.new_page()
        print("✅ 浏览器启动成功")
    
    async def login(self):
        """登录832平台"""
        print("🔐 开始登录...")
        await self.page.goto(CONFIG["login_url"])
        await self.page.wait_for_load_state("networkidle")
        
        # 点击登录按钮
        try:
            await self.page.click('text="登录"', timeout=5000)
        except:
            print("未找到登录按钮，尝试其他方式...")
        
        await self.page.wait_for_timeout(2000)
        
        # 输入用户名
        username_input = await self.page.query_selector('input[placeholder*="账号"], input[type="text"]')
        if username_input:
            await username_input.fill(CONFIG["username"])
            print(f"✅ 输入用户名: {CONFIG['username']}")
        
        # 输入密码
        password_input = await self.page.query_selector('input[type="password"]')
        if password_input:
            await password_input.fill(CONFIG["password"])
            print("✅ 输入密码")
        
        # 点击登录
        await self.page.wait_for_timeout(1000)
        
        # 查找登录提交按钮
        submit_buttons = await self.page.query_selector_all('button')
        for btn in submit_buttons:
            text = await btn.inner_text()
            if "登录" in text and "注册" not in text:
                await btn.click()
                print("✅ 点击登录按钮")
                break
        
        # 等待登录结果
        print("⏳ 等待登录验证...")
        await self.page.wait_for_timeout(5000)
        
        # 检查是否登录成功（通过URL或页面元素判断）
        current_url = self.page.url
        print(f"📍 当前页面: {current_url}")
        
        # 截图保存登录状态
        await self.page.screenshot(path="login_status.png")
        print("📸 登录状态截图已保存")
        
        return True
    
    async def wait_for_manual_login(self):
        """等待手动登录（如果自动登录失败）"""
        print("\n" + "="*50)
        print("⚠️ 请在浏览器中手动完成登录...")
        print("登录后请按回车继续...")
        print("="*50 + "\n")
        input()
        await self.page.screenshot(path="after_login.png")
        print("📸 登录后截图已保存")
    
    async def navigate_to_products(self):
        """跳转到商品列表页面"""
        print("🛒 跳转到河南商品列表...")
        
        # 尝试直接访问商品列表页
        await self.page.goto(CONFIG["product_url"])
        await self.page.wait_for_load_state("networkidle")
        await self.page.wait_for_timeout(3000)
        
        # 截图
        await self.page.screenshot(path="product_list.png")
        print("📸 商品列表页面截图已保存")
        
        # 获取页面内容用于调试
        content = await self.page.content()
        print(f"📄 页面长度: {len(content)} 字符")
    
    async def scroll_and_load_products(self):
        """滚动页面加载更多商品"""
        print("📜 开始滚动加载商品...")
        
        # 先尝试滚动几次加载数据
        for i in range(5):
            await self.page.evaluate("window.scrollBy(0, 1000)")
            await self.page.wait_for_timeout(1000)
            print(f"  第 {i+1} 次滚动完成")
        
        # 截图
        await self.page.screenshot(path="after_scroll.png")
    
    async def extract_products(self):
        """提取商品数据"""
        print("🔍 开始提取商品数据...")
        
        # 使用JavaScript提取商品数据
        products_data = await self.page.evaluate("""
            () => {
                const results = [];
                
                // 尝试多种选择器
                const selectors = [
                    '.product-item',
                    '.product-list .item',
                    '[class*="product"]',
                    '.goods-item',
                    '.item-product',
                    '.pro-item'
                ];
                
                let items = [];
                for (const sel of selectors) {
                    items = document.querySelectorAll(sel);
                    if (items.length > 0) {
                        console.log('Found selector:', sel, 'with', items.length, 'items');
                        break;
                    }
                }
                
                // 如果没找到，尝试从表格或其他元素提取
                if (items.length === 0) {
                    // 尝试获取所有可能包含商品信息的元素
                    const allDivs = document.querySelectorAll('div');
                    for (const div of allDivs) {
                        const text = div.innerText || '';
                        // 匹配商品名称模式（包含价格等）
                        if (text.match(/\\d+元/) && text.length > 10 && text.length < 200) {
                            results.push({
                                name: text.substring(0, 50),
                                raw: text
                            });
                        }
                    }
                }
                
                return results;
            }
        """)
        
        print(f"📊 初步提取到 {len(products_data)} 条数据")
        
        # 如果上面的方法没找到，尝试更通用的方法
        if len(products_data) == 0:
            print("🔄 尝试其他提取方式...")
            products_data = await self.page.evaluate("""
                () => {
                    const results = [];
                    
                    // 获取页面所有文本内容
                    const bodyText = document.body.innerText;
                    
                    // 尝试查找价格模式
                    const pricePattern = /(\\d+\\.?\\d*元\\/\\w+)/g;
                    const prices = bodyText.match(pricePattern) || [];
                    
                    // 尝试查找商品列表区域
                    const mainContent = document.querySelector('main') || document.querySelector('.main') || document.body;
                    
                    // 获取所有链接文本，可能包含商品信息
                    const links = document.querySelectorAll('a[href*="product"], a[href*="goods"], a[href*="item"]');
                    links.forEach((link, index) => {
                        const text = link.innerText?.trim();
                        const href = link.href;
                        if (text && text.length > 2 && text.length < 100) {
                            results.push({
                                name: text,
                                url: href,
                                index: index
                            });
                        }
                    });
                    
                    return results.slice(0, 50); // 限制数量
                }
            """)
            print(f"📊 通过链接提取到 {len(products_data)} 条数据")
        
        return products_data
    
    async def try_api_extraction(self):
        """尝试通过API获取数据"""
        print("🌐 尝试通过API获取数据...")
        
        # 先登录获取token
        # 这个需要根据实际的API来调整
        
        try:
            # 尝试获取localStorage中的token
            local_storage = await self.page.evaluate("""() => {
                const items = {};
                for (let i = 0; i < localStorage.length; i++) {
                    const key = localStorage.key(i);
                    items[key] = localStorage.getItem(key);
                }
                return items;
            }""")
            print(f"📦 LocalStorage: {list(local_storage.keys())}")
            
            # 尝试获取cookie
            cookies = await self.context.cookies()
            print(f"🍪 Cookies数量: {len(cookies)}")
            
        except Exception as e:
            print(f"⚠️ API获取失败: {e}")
    
    async def save_to_csv(self):
        """保存数据到CSV"""
        if not self.products:
            print("⚠️ 没有数据可保存")
            return
        
        output_path = CONFIG["output_file"]
        
        with open(output_path, 'w', newline='', encoding='utf-8-sig') as f:
            writer = csv.DictWriter(f, fieldnames=CSV_HEADERS)
            writer.writeheader()
            
            for idx, product in enumerate(self.products, 1):
                row = {
                    "序号": idx,
                    "供应商名称": product.get("supplier", ""),
                    "商品名称": product.get("name", ""),
                    "单价(元)": product.get("price", ""),
                    "销量": product.get("sales", ""),
                    "联系方式": product.get("contact", ""),
                    "商品链接": product.get("url", ""),
                    "抓取时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                }
                writer.writerow(row)
        
        print(f"✅ 数据已保存到: {output_path}")
        print(f"📊 共保存 {len(self.products)} 条记录")
    
    async def close(self):
        """关闭浏览器"""
        if self.browser:
            await self.browser.close()
            print("🔒 浏览器已关闭")

async def main():
    """主函数"""
    print("="*60)
    print("  832平台 河南商品爬虫")
    print("  作者: 李狗蛋")
    print("  时间: " + datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
    print("="*60 + "\n")
    
    spider = Spider832()
    
    try:
        # 1. 初始化浏览器
        await spider.init_browser()
        
        # 2. 登录
        await spider.login()
        
        # 3. 如果需要手动登录
        await spider.wait_for_manual_login()
        
        # 4. 跳转到商品列表
        await spider.navigate_to_products()
        
        # 5. 滚动加载
        await spider.scroll_and_load_products()
        
        # 6. 提取数据
        products = await spider.extract_products()
        
        if products:
            spider.products = products
            # 7. 保存数据
            await spider.save_to_csv()
        else:
            print("⚠️ 未提取到商品数据，尝试API方式...")
            await spider.try_api_extraction()
        
        print("\n" + "="*60)
        print("  爬虫执行完成！")
        print("="*60)
        
    except Exception as e:
        print(f"❌ 错误: {e}")
        import traceback
        traceback.print_exc()
    
    finally:
        # 保持浏览器打开，方便查看
        print("\n按回车键关闭浏览器...")
        input()
        await spider.close()

if __name__ == "__main__":
    asyncio.run(main())
