<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Goofish on KnightLi Blog</title>
        <link>https://www.knightli.com/en/tags/goofish/</link>
        <description>Recent content in Goofish on KnightLi Blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Sun, 17 May 2026 17:24:03 +0800</lastBuildDate><atom:link href="https://www.knightli.com/en/tags/goofish/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>ai-goofish-monitor: An Open-Source AI Monitoring System for Goofish Listings</title>
        <link>https://www.knightli.com/en/2026/05/17/ai-goofish-monitor/</link>
        <pubDate>Sun, 17 May 2026 17:24:03 +0800</pubDate>
        
        <guid>https://www.knightli.com/en/2026/05/17/ai-goofish-monitor/</guid>
        <description>&lt;p&gt;ai-goofish-monitor is an open-source Goofish product monitoring system from Usagi-org.&lt;/p&gt;
&lt;p&gt;Its goal is clear: automate Goofish search, filtering, product analysis, result logging, and notifications, so users can find matching second-hand listings faster. The project uses Playwright for browser automation and connects to image-capable AI models to judge product information more intelligently.&lt;/p&gt;
&lt;p&gt;Project link: &lt;a class=&#34;link&#34; href=&#34;https://github.com/Usagi-org/ai-goofish-monitor&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/Usagi-org/ai-goofish-monitor&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-short-version&#34;&gt;The Short Version
&lt;/h2&gt;&lt;p&gt;ai-goofish-monitor is closer to a &amp;ldquo;Goofish purchasing intelligence dashboard&amp;rdquo; than a simple keyword alert script.&lt;/p&gt;
&lt;p&gt;It has several notable traits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A complete web admin UI for managing tasks, accounts, AI criteria, logs, and results.&lt;/li&gt;
&lt;li&gt;Concurrent multi-task monitoring, where each task can define keywords, price range, filters, and AI Prompt.&lt;/li&gt;
&lt;li&gt;Playwright-based page automation, useful for scenarios that require login state and page interaction.&lt;/li&gt;
&lt;li&gt;AI-based product judgment, not just keyword matching.&lt;/li&gt;
&lt;li&gt;Notifications through ntfy.sh, WeCom, Bark, Telegram, Webhook, and other channels.&lt;/li&gt;
&lt;li&gt;Cron scheduling, multi-account management, proxy rotation, retry handling, and Docker deployment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It fits users who often search Goofish for specific items, such as second-hand electronics, cameras, GPUs, hard drives, game consoles, musical instruments, appliances, and collectibles. But it is not an &amp;ldquo;automatic bargain hunter.&amp;rdquo; Goofish search results change, login states may expire, and platform risk controls can affect automation stability. Treat it as an assisted filtering tool, not a replacement for human judgment.&lt;/p&gt;
&lt;h2 id=&#34;what-problem-it-solves&#34;&gt;What Problem It Solves
&lt;/h2&gt;&lt;p&gt;Finding second-hand products on Goofish often has several pain points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are too many listings to browse manually.&lt;/li&gt;
&lt;li&gt;Titles and descriptions are inconsistent, so keywords can miss or misclassify listings.&lt;/li&gt;
&lt;li&gt;Good prices appear briefly and may be gone by the time you see them.&lt;/li&gt;
&lt;li&gt;The same product may differ by region, price, condition, and seller.&lt;/li&gt;
&lt;li&gt;Low-priced listings can include accessories, damaged goods, refurbished items, or misleading titles.&lt;/li&gt;
&lt;li&gt;Watching multiple keywords continuously is hard to sustain manually.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Basic keyword alerts solve only part of this. Searching for &amp;ldquo;ThinkPad X1&amp;rdquo; may mix in accessories, broken screens, empty boxes, or disassembled parts. Searching for &amp;ldquo;Sony A7C&amp;rdquo; may return lens bundles, rentals, clickbait titles, or abnormal prices.&lt;/p&gt;
&lt;p&gt;ai-goofish-monitor&amp;rsquo;s idea is to use automation to collect candidate listings, then let AI apply your criteria, and finally push the results worth attention.&lt;/p&gt;
&lt;h2 id=&#34;core-features&#34;&gt;Core Features
&lt;/h2&gt;&lt;p&gt;The project README lists a fairly complete feature set:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual web management: task management, account management, AI criteria editing, run logs, and result browsing.&lt;/li&gt;
&lt;li&gt;AI-driven workflow: create tasks with natural language and analyze products with multimodal models.&lt;/li&gt;
&lt;li&gt;Concurrent tasks: each task can define keywords, prices, filters, and AI Prompt independently.&lt;/li&gt;
&lt;li&gt;Advanced filters: free shipping, newly listed time range, and province / city / district filtering.&lt;/li&gt;
&lt;li&gt;Instant notifications: ntfy.sh, WeCom, Bark, Telegram, Webhook, and more.&lt;/li&gt;
&lt;li&gt;Scheduled execution: Cron-based periodic tasks.&lt;/li&gt;
&lt;li&gt;Account and proxy rotation: multi-account management, task-account binding, proxy pool rotation, and retry handling.&lt;/li&gt;
&lt;li&gt;Docker deployment: containerized deployment support.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together, these cover the full chain from creating a monitoring task to receiving a matching alert.&lt;/p&gt;
&lt;h2 id=&#34;workflow&#34;&gt;Workflow
&lt;/h2&gt;&lt;p&gt;A typical workflow looks like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Deploy the service and open the Web UI.&lt;/li&gt;
&lt;li&gt;Import Goofish account login state.&lt;/li&gt;
&lt;li&gt;Create a monitoring task.&lt;/li&gt;
&lt;li&gt;Set keywords, price range, region, newly listed window, and other filters.&lt;/li&gt;
&lt;li&gt;Write criteria or let AI generate them.&lt;/li&gt;
&lt;li&gt;Run the task in real-time or on a schedule.&lt;/li&gt;
&lt;li&gt;Playwright opens pages and extracts product information.&lt;/li&gt;
&lt;li&gt;AI checks title, description, images, and Prompt against your needs.&lt;/li&gt;
&lt;li&gt;Matching results are written to SQLite.&lt;/li&gt;
&lt;li&gt;The system sends notifications through configured channels.&lt;/li&gt;
&lt;li&gt;You review results, logs, and price history in the Web UI.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;AI matters most at step 8. It can understand natural language criteria like &amp;ldquo;good condition, reasonable price, no accessories, no repaired units, preferably local pickup,&amp;rdquo; which is more flexible than simple keyword rules.&lt;/p&gt;
&lt;h2 id=&#34;docker-deployment&#34;&gt;Docker Deployment
&lt;/h2&gt;&lt;p&gt;The project recommends Docker deployment:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/Usagi-org/ai-goofish-monitor &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; ai-goofish-monitor
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp .env.example .env
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;vim .env
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose logs -f app
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose down
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The default Web UI address is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;http://127.0.0.1:8000
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The official image is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghcr.io/usagi-org/ai-goofish:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If the image pulls slowly, the README also gives an accelerated mirror example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker pull ghcr.nju.edu.cn/usagi-org/ai-goofish:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker tag ghcr.nju.edu.cn/usagi-org/ai-goofish:latest ghcr.io/usagi-org/ai-goofish:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The Docker image includes Chromium, so the host does not need an extra browser. Default persistent directories include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;data/&lt;/code&gt;: main SQLite storage for tasks, results, and price history.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;state/&lt;/code&gt;: login-state cookie files.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prompts/&lt;/code&gt;: task prompts.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;logs/&lt;/code&gt;: runtime logs.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;images/&lt;/code&gt;: product images and temporary task image folders.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you change &lt;code&gt;SERVER_PORT&lt;/code&gt; in &lt;code&gt;.env&lt;/code&gt;, also update the port mapping in &lt;code&gt;docker-compose.yaml&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;minimum-configuration&#34;&gt;Minimum Configuration
&lt;/h2&gt;&lt;p&gt;The minimum configuration mainly covers the AI model and Web UI login:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-env&#34; data-lang=&#34;env&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your_api_key
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;OPENAI_BASE_URL&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your_openai_compatible_base_url
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;OPENAI_MODEL_NAME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;your_multimodal_model
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;WEB_USERNAME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;admin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;WEB_PASSWORD&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;change_me
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The first three are required for AI model access:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;OPENAI_API_KEY&lt;/code&gt;: model API key.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OPENAI_BASE_URL&lt;/code&gt;: OpenAI-compatible endpoint.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OPENAI_MODEL_NAME&lt;/code&gt;: model name that supports image input.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;WEB_USERNAME&lt;/code&gt; and &lt;code&gt;WEB_PASSWORD&lt;/code&gt; are used for Web UI login. The README mentions the default credentials &lt;code&gt;admin/admin123&lt;/code&gt;; change them in production.&lt;/p&gt;
&lt;h2 id=&#34;first-use&#34;&gt;First Use
&lt;/h2&gt;&lt;p&gt;The first-use flow is roughly:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;http://127.0.0.1:8000&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Log in to the Web UI.&lt;/li&gt;
&lt;li&gt;Go to Goofish account management.&lt;/li&gt;
&lt;li&gt;Use the provided Chrome extension to export Goofish login-state JSON.&lt;/li&gt;
&lt;li&gt;Paste the login state into the system.&lt;/li&gt;
&lt;li&gt;The state file is saved to &lt;code&gt;state/&lt;/code&gt;, for example &lt;code&gt;state/acc_1.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Return to task management, create a task, and bind an account.&lt;/li&gt;
&lt;li&gt;Run the task and check results.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The key part is login state. Goofish does not provide a standard open API for arbitrary third-party scraping, so the project uses browser login state to simulate normal page access. Expired login state, risk controls, captchas, and account anomalies can all affect task execution.&lt;/p&gt;
&lt;h2 id=&#34;ai-tasks-and-keyword-tasks&#34;&gt;AI Tasks and Keyword Tasks
&lt;/h2&gt;&lt;p&gt;The project supports two task creation modes.&lt;/p&gt;
&lt;p&gt;The first is &lt;code&gt;AI判断&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can enter detailed requirements, and the system asynchronously generates analysis criteria. This fits complex needs, for example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only the main unit, no accessories.&lt;/li&gt;
&lt;li&gt;Alert only when the price is clearly below market.&lt;/li&gt;
&lt;li&gt;Good condition, with no water damage, repair, or hidden defects in the description.&lt;/li&gt;
&lt;li&gt;Prefer local listings and face-to-face pickup.&lt;/li&gt;
&lt;li&gt;Images should show serial number, packaging, or key accessories.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The second is &lt;code&gt;关键词判断&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is closer to traditional rule-based monitoring: create tasks directly from keywords, prices, regions, and other conditions without AI generation. It fits simple rules where some false positives are acceptable.&lt;/p&gt;
&lt;p&gt;In practice, you can mix both: keywords handle initial filtering, AI reduces false positives.&lt;/p&gt;
&lt;h2 id=&#34;what-the-web-ui-does&#34;&gt;What the Web UI Does
&lt;/h2&gt;&lt;p&gt;The Web UI is a major difference between this project and ordinary scripts.&lt;/p&gt;
&lt;p&gt;The task management page can configure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI-created tasks.&lt;/li&gt;
&lt;li&gt;Keyword rules.&lt;/li&gt;
&lt;li&gt;Price ranges.&lt;/li&gt;
&lt;li&gt;Newly listed windows.&lt;/li&gt;
&lt;li&gt;Region filters.&lt;/li&gt;
&lt;li&gt;Account binding.&lt;/li&gt;
&lt;li&gt;Scheduling rules.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The account management page can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Import Goofish account login state.&lt;/li&gt;
&lt;li&gt;Update login state.&lt;/li&gt;
&lt;li&gt;Delete accounts.&lt;/li&gt;
&lt;li&gt;Assign accounts to tasks.&lt;/li&gt;
&lt;li&gt;Let the system choose accounts automatically.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Results and logs pages can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View matching products.&lt;/li&gt;
&lt;li&gt;Export results.&lt;/li&gt;
&lt;li&gt;Search history.&lt;/li&gt;
&lt;li&gt;Inspect task execution.&lt;/li&gt;
&lt;li&gt;Troubleshoot login expiration, risk controls, and AI call issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The system settings page can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;View system status.&lt;/li&gt;
&lt;li&gt;Edit Prompt.&lt;/li&gt;
&lt;li&gt;Adjust proxy and rotation configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For long-term monitoring, the Web UI is important. Without it, many tasks quickly make configuration, logs, results, and notifications hard to maintain.&lt;/p&gt;
&lt;h2 id=&#34;data-storage&#34;&gt;Data Storage
&lt;/h2&gt;&lt;p&gt;The current online primary storage is SQLite, with the default path:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;data/app.sqlite3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Docker mounts the SQLite main database by default:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./data:/app/data
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;On startup, the app creates tables automatically and tries to import historical data once from old &lt;code&gt;config.json&lt;/code&gt;, &lt;code&gt;jsonl/&lt;/code&gt;, and &lt;code&gt;price_history/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;state/&lt;/code&gt;, &lt;code&gt;prompts/&lt;/code&gt;, &lt;code&gt;logs/&lt;/code&gt;, and &lt;code&gt;images/&lt;/code&gt; remain filesystem directories and are not stored in SQLite. Product images are temporarily saved to directories like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;images/task_images_&amp;lt;task_name&amp;gt;/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;They are cleaned up by default after the task ends.&lt;/p&gt;
&lt;p&gt;This structure fits personal or small-team deployments: SQLite is lightweight and easy to migrate, while files keep login state, images, and logs easy to inspect.&lt;/p&gt;
&lt;h2 id=&#34;notification-channels&#34;&gt;Notification Channels
&lt;/h2&gt;&lt;p&gt;The project supports multiple notification channels. Common configuration items include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NTFY_TOPIC_URL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GOTIFY_URL&lt;/code&gt; / &lt;code&gt;GOTIFY_TOKEN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BARK_URL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WX_BOT_URL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TELEGRAM_BOT_TOKEN&lt;/code&gt; / &lt;code&gt;TELEGRAM_CHAT_ID&lt;/code&gt; / &lt;code&gt;TELEGRAM_API_BASE_URL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WEBHOOK_*&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notifications are central to the experience. If a monitor only writes results to a backend, users still need to keep checking the page. With push notifications, matching listings reach the user immediately.&lt;/p&gt;
&lt;p&gt;A practical setup is to tier notifications by item value:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Normal keyword hits are written only to the backend.&lt;/li&gt;
&lt;li&gt;High-confidence AI results are pushed to the phone.&lt;/li&gt;
&lt;li&gt;High-value items are pushed to WeCom or Telegram.&lt;/li&gt;
&lt;li&gt;Enable more logs during debugging, then reduce noise after stabilization.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;developer-run&#34;&gt;Developer Run
&lt;/h2&gt;&lt;p&gt;Without Docker, local development requires:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python 3.10+&lt;/li&gt;
&lt;li&gt;Node.js + npm&lt;/li&gt;
&lt;li&gt;Playwright CLI&lt;/li&gt;
&lt;li&gt;Chromium or Chrome / Edge browser&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Basic commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/Usagi-org/ai-goofish-monitor
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; ai-goofish-monitor
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp .env.example .env
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;One-command startup:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;chmod +x start.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./start.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;start.sh&lt;/code&gt; checks Playwright CLI and browser conditions, installs dependencies, builds the frontend, copies build artifacts, and starts the backend.&lt;/p&gt;
&lt;p&gt;Start the backend manually:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python -m src.app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Or:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uvicorn src.app:app --host 0.0.0.0 --port &lt;span class=&#34;m&#34;&gt;8000&lt;/span&gt; --reload
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Frontend development:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; web-ui
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm run dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Testing and build:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PYTEST_DISABLE_PLUGIN_AUTOLOAD&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; pytest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; web-ui &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;who-it-fits&#34;&gt;Who It Fits
&lt;/h2&gt;&lt;p&gt;ai-goofish-monitor fits users who:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Frequently watch Goofish for specific models.&lt;/li&gt;
&lt;li&gt;Want to monitor second-hand electronics, cameras, game devices, hardware parts, and similar goods.&lt;/li&gt;
&lt;li&gt;Want to automate &amp;ldquo;keyword search + manual screening.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Have an OpenAI-compatible model API and accept AI judgment costs.&lt;/li&gt;
&lt;li&gt;Are comfortable with Docker or basic command-line deployment.&lt;/li&gt;
&lt;li&gt;Need matching results pushed to phone, WeCom, or Telegram.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is less suitable if you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Know nothing about deployment and only want a ready-to-use app.&lt;/li&gt;
&lt;li&gt;Do not want to handle login state, captchas, or account risk controls.&lt;/li&gt;
&lt;li&gt;Need official authorization and strongly compliant data APIs.&lt;/li&gt;
&lt;li&gt;Want large-scale high-frequency platform scraping.&lt;/li&gt;
&lt;li&gt;Expect AI to automatically judge trading risk and place orders for you.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;risks-and-boundaries&#34;&gt;Risks and Boundaries
&lt;/h2&gt;&lt;p&gt;Tools like this need clear boundaries.&lt;/p&gt;
&lt;p&gt;First, follow platform rules.&lt;/p&gt;
&lt;p&gt;Goofish has its own terms, risk controls, and account security mechanisms. Automation may trigger restrictions. Do not scrape at high frequency, bypass risk controls, harass sellers, bulk-collect private information, or disrupt platform order.&lt;/p&gt;
&lt;p&gt;Second, protect account login state.&lt;/p&gt;
&lt;p&gt;Files in &lt;code&gt;state/&lt;/code&gt; are login-state cookie files. They are effectively account access credentials. Do not commit them to Git, and do not put them on untrusted servers. If the server is exposed to the public internet, change the default Web UI password and place it behind a VPN, reverse-proxy authentication, or an internal network.&lt;/p&gt;
&lt;p&gt;Third, AI judgment is not a factual guarantee.&lt;/p&gt;
&lt;p&gt;AI can reduce false positives, but it cannot guarantee product authenticity, seller trustworthiness, reasonable pricing, or transaction safety. You still need to review product details, seller reputation, chat history, shipping method, and payment process.&lt;/p&gt;
&lt;p&gt;Fourth, watch cost.&lt;/p&gt;
&lt;p&gt;If every candidate listing is analyzed by a multimodal model, costs can rise quickly. Use keyword, price, and region filters first, then send a smaller candidate set to AI.&lt;/p&gt;
&lt;p&gt;Fifth, protect privacy.&lt;/p&gt;
&lt;p&gt;Product screenshots, chat-related content, account state, and notification content may all contain sensitive information. Protect notification Webhooks, log directories, and databases carefully.&lt;/p&gt;
&lt;h2 id=&#34;difference-from-ordinary-scripts&#34;&gt;Difference from Ordinary Scripts
&lt;/h2&gt;&lt;p&gt;Ordinary Goofish monitoring scripts usually do three things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Search keywords.&lt;/li&gt;
&lt;li&gt;Check prices.&lt;/li&gt;
&lt;li&gt;Send notifications.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ai-goofish-monitor goes further:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manage tasks and accounts through Web UI.&lt;/li&gt;
&lt;li&gt;Express complex buying criteria with AI Prompt.&lt;/li&gt;
&lt;li&gt;Use multimodal models to inspect product images and descriptions.&lt;/li&gt;
&lt;li&gt;Store results and price history in SQLite.&lt;/li&gt;
&lt;li&gt;Use log pages to diagnose task failures.&lt;/li&gt;
&lt;li&gt;Improve stability through proxy rotation and multi-account mechanisms.&lt;/li&gt;
&lt;li&gt;Support long-running schedules with Cron.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because it does more, it also costs more to deploy and maintain. For normal users, Docker is the easiest path. For developers, the Web UI, FastAPI, Playwright, and SQLite structure is also friendly for secondary development.&lt;/p&gt;
&lt;h2 id=&#34;how-to-use-it&#34;&gt;How to Use It
&lt;/h2&gt;&lt;p&gt;A practical approach is to start with small tasks.&lt;/p&gt;
&lt;p&gt;For example, if you want a second-hand camera, create a task like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keywords: &lt;code&gt;A7C&lt;/code&gt;, &lt;code&gt;索尼 A7C&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Price range: set an upper limit based on market price&lt;/li&gt;
&lt;li&gt;Region: prefer same province or local city&lt;/li&gt;
&lt;li&gt;Newly listed window: last day or last few hours&lt;/li&gt;
&lt;li&gt;AI criteria: exclude lens-only listings, repaired units, obvious accessories; pay attention to shutter count and condition&lt;/li&gt;
&lt;li&gt;Notification: push only results that pass AI judgment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After it runs stably, gradually add more tasks. Do not start with dozens of keywords, multiple accounts, and high-frequency Cron. First check login stability, false-positive rate, AI cost, and notification noise, then tune parameters.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;ai-goofish-monitor moves Goofish monitoring from a &amp;ldquo;keyword script&amp;rdquo; to a manageable AI monitoring system. It uses Playwright for page automation, AI for complex judgment, Web UI for tasks and results, SQLite for storage, and multiple notification channels for delivery.&lt;/p&gt;
&lt;p&gt;It is best for individuals or small teams monitoring specific products, especially second-hand electronics, hardware, and cameras where prices fluctuate, timing matters, and descriptions are noisy.&lt;/p&gt;
&lt;p&gt;But it must be used carefully: protect login state, change default passwords, keep scraping frequency restrained, review AI results manually, and respect platform rules and privacy boundaries. As an assisted filtering tool, it can be valuable. As a fully automated trading system, it is easy to overestimate.&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/Usagi-org/ai-goofish-monitor&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Usagi-org/ai-goofish-monitor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/Usagi-org/ai-goofish-monitor/blob/master/README_EN.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Project English README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/Usagi-org/ai-goofish-monitor/blob/master/DISCLAIMER.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Project disclaimer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
