Building a Coze Bot for Weekend Activity Recommendations with Data Retrieval and Custom Plugins
This article walks through creating a Coze chatbot that recommends weekend attractions and events by designing prompt‑based workflows, leveraging official plugins, scraping city‑level data, constructing a knowledge base, handling pagination with code nodes, and finally deploying the bot for real‑time user queries.
The author starts by recalling a previous post that listed 68 Coze plugins and notes that the main challenge in building a useful bot is defining its creative use case – in this case, recommending weekend activities based on a city and district.
1. Quick Bot Prototyping – Using only prompt engineering, the author creates a Bot named "Dreamina" that can generate a cute avatar and a simple greeting. Sample prompts are shown, and the limitations of relying solely on prompts are discussed.
2. Data Retrieval Strategy – The bot needs two data sources: static attraction information and dynamic weekend event listings. The author classifies these sources as "unchanging" (e.g., long‑standing landmarks) and "dynamic" (e.g., concerts, exhibitions).
To obtain the data, three approaches are considered: uploading an existing knowledge base, using official or marketplace plugins, or writing custom code (including web‑scraping). The author decides to combine all three.
3. Acquiring Attraction Data – The official searchLocation plugin is tested but returns only ten results. To expand coverage, the author uses a large‑model node to list all streets/towns in a district, then batches searchLocation calls. A selector node is used to split the list, but its behavior is flaky, so the workflow is simplified to two parallel plugin calls followed by a deduplication code node.
The deduplication code (shown below) merges results from three plugin calls and removes duplicates using a dictionary keyed by place name:
async def main(args: Args) -> Output:
params = args.params
result_dict = {}
# merge three result lists
for result in params["ifConditionResult1"]:
for place in result["places"]:
result_dict[place["name"]] = {"name": place["name"], "address": place["address"]}
# repeat for other branches ...
return {"result": list(result_dict.values())}Because the plugin still limits results, the author resorts to web‑scraping the map site, extracts JSON files, filters for attractions, and writes a Python script (shown) that de‑duplicates entries and saves them as CSV files for import into Coze’s knowledge base.
# extract city_district attractions
def fetch_attractions_info_list(city_county):
json_dir = f"{os.getcwd()}{os.sep}baidu_jd{os.sep}{city_county}{os.sep}"
attractions_info_dict = {}
for json_file in search_all_file(json_dir, ".json"):
data_list = json.loads(read_file_text_content(json_file))["content"]
for data in data_list:
name = data['name']
tag = data['std_tag']
addr = data['addr']
if tag and ("景点" in tag or "公园" in tag):
if addr in attractions_info_dict:
if len(name) < len(attractions_info_dict[addr]["景点名称"]):
attractions_info_dict[addr]["景点名称"] = name
else:
attractions_info_dict[addr] = {"景点名称": name, "景点标签": tag, "景点地址": addr}
# write CSV
with open(os.path.join(output_dir, f"{city_county}.csv"), 'w+', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=['景点名称', '景点标签', '景点地址'])
writer.writeheader()
for item in attractions_info_dict.values():
writer.writerow(item)These CSV files are uploaded to Coze as knowledge‑base units, indexed by address for fast retrieval.
4. Handling Weekend Event Data – No public API is available, so the author writes a scraper that captures the X‑X‑X event page, extracts activity name, time, location, and cost using a regular expression, and formats the output. The scraper is wrapped in an async code node that sends HTTP requests with proper headers.
activity_pattern = re.compile(r'temprop="summary">(.*?)<.*?时间:
(.*?)<.*?
.*?地点:
(.*?)
', re.S)
async def send_request(url):
headers = {"User-Agent": "Mozilla/5.0 ...", "Host": "www.douban.com", "Refer": url}
resp = await requests_async.get(url, headers=headers)
matches = activity_pattern.findall(resp.text)
result = ""
for name, time, place, cost in matches:
result += f"-【{name}】| {cost} | {time} | {place}\n"
return resultThe workflow builds the request URL from city, district, and optional activity category, queries the first three pages (with a 0.5 s sleep between calls), and concatenates the results into a human‑readable string.
5. Final Bot Assembly – The author ties together the attraction knowledge base, the event‑scraping workflow, and a role‑prompt that decides which sub‑workflow to invoke based on whether the user mentions "景点" (attractions). An opening message with example commands is added, along with preset quick‑reply questions and a chosen voice style.
After publishing, the bot (ID 7337619854435876876) successfully returns comprehensive attraction lists and weekend event information, though the author notes that output formatting could be improved.
The article concludes with deployment tips, such as using cookies to avoid IP bans, deploying the scraper on a separate server, or using mock APIs for stable responses.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.