想知道大家都在杭州去哪玩?不如试试自己动手搞点数据来看看——我最近就尝试了一种低成本的数据抓取+图表分析方案,整个过程还挺有趣的,分享给你。
旅行越来越个性化,但信息太散怎么办?
大家应该也有这种感觉吧,现在出去旅游,做攻略几乎成了“信息大战”——去哪玩?怎么玩?值不值得?网上各种推荐、评论、问答混在一起,有时候看得头都大了。
我比较好奇的是:这些攻略信息到底有没有共性?
比如:
- 是不是总有那么几个地方被大家反复提起?
- 游客最关心的问题,到底是“交通”、“门票”还是“吃住”?
带着这些问题,我想试着从某个旅游社区采集一批数据,做个小分析。我选了马蜂窝,因为它的用户内容还算丰富。
我的目标很简单
输入一个关键词,比如“杭州”,我想获取:
- 这个城市的热门景点列表;
- 一些相关的旅游攻略标题;
- 用户在问答区都讨论了啥问题;
最后,做成两个图:一个热门景点排行图,一个关键词词云图。
说白了,就是试着还原一下大家对“杭州”这个目的地的关注重点。
用什么方法搞这些数据?
我做的事,大致是这样:
- 用自动浏览器(有点像我们手动点网页)去打开马蜂窝;
- 模拟用户在搜索框中输入“杭州”;
- 等待网页加载后,读取页面中呈现的景点信息;
- 把每个景点的标题、链接保存下来;
- 用简单的分类方式存储数据;
- 最后做个小分析。
为了防止访问太频繁被限制,我还加了网络代理(可以让网站误以为每次访问都来自不同网络环境)和浏览器模拟参数,尽量让这套访问方式显得“像人”。
实际代码片段
下面是我写的部分示例代码,主要逻辑就是通过 Playwright 实现浏览器行为,采集景点卡片中的标题和链接。
import asyncio
from playwright.async_api import async_playwright
import json
import os
# 网络代理配置(参考亿牛云爬虫代理示例 www.16yun.cn)
PROXY_SERVER = "http://你的代理地址:端口"
PROXY_USERNAME = "用户名"
PROXY_PASSWORD = "密码"
KEYWORD = "杭州"
os.makedirs("mafengwo_data", exist_ok=True)
async def run():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context(
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/114.0.0.0 Safari/537.36",
proxy={
"server": PROXY_SERVER,
"username": PROXY_USERNAME,
"password": PROXY_PASSWORD
}
)
page = await context.new_page()
await page.goto("https://www.mafengwo.cn/")
await page.context.add_cookies([{
'name': 'mfw_uuid', 'value': 'example-uuid', 'domain': '.mafengwo.cn', 'path': '/'
}])
# 输入关键词并搜索
await page.fill('input[id="search-input"]', KEYWORD)
await page.click('div.search-btn')
await page.wait_for_timeout(3000)
# 提取搜索结果中的景点卡片
scenic_cards = await page.locator('div[class*="list_mod"]').all()
results = []
for card in scenic_cards:
title = await card.locator('h3').inner_text()
link = await card.locator('a').get_attribute('href')
results.append({
"景点": title.strip(),
"链接": f"https://www.mafengwo.cn{link}" if link.startswith('/') else link
})
# 保存每个景点信息为JSON文件
for r in results:
filename = os.path.join("mafengwo_data", f"{r['景点']}.json")
with open(filename, "w", encoding="utf-8") as f:
json.dump(r, f, ensure_ascii=False, indent=2)
await browser.close()
asyncio.run(run())
数据分析和图形展示
我对采集到的内容做了两种可视化:
- 柱状图:展示热门景点 Top10;
- 词云图:分析大家关心的问题关键词。
代码如下:
import os
import json
import matplotlib.pyplot as plt
from collections import Counter
from wordcloud import WordCloud
files = os.listdir("mafengwo_data")
scenic_counts = Counter()
qa_keywords = Counter()
for file in files:
with open(os.path.join("mafengwo_data", file), "r", encoding="utf-8") as f:
data = json.load(f)
scenic_counts[data["景点"]] += 1
# 模拟关键词统计(实际可根据内容语义提取)
qa_keywords.update(["交通", "门票", "住宿", "路线"])
# 热门景点Top10
plt.figure(figsize=(10, 5))
names, counts = zip(*scenic_counts.most_common(10))
plt.bar(names, counts, color='skyblue')
plt.title("热门景点排行")
plt.ylabel("次数")
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig("hot_scenic.png")
plt.close()
# 关键词词云图
wc = WordCloud(font_path="msyh.ttc", background_color="white", width=800, height=400)
wc.generate_from_frequencies(qa_keywords)
wc.to_file("qa_wordcloud.png")
分析结果和一些观察
景点热度排行
图中可以看到,“西湖”、“灵隐寺”、“千岛湖”等依然是大家最常提及的地点。说明即使有很多小众路线,经典景区依然占据C位。
大家最关心什么?
从词云可以看出,“门票”、“交通”、“住宿”频率较高。这印证了游客在出行前的核心关注点还集中在实用信息上。
我的几点思考
- 用自动浏览+代理模拟的方式,其实比想象中稳定,尤其适合这种信息量大但结构变化快的页面;
- 数据量虽然不大,但已经能观察到一些趋势,非常适合用来做数据故事;
- 后续还可以加入内容摘要、评论情感分析等模块,做成小型推荐系统。
总结
通过一个小型“杭州”旅游信息采集与分析项目,我初步验证了用浏览器模拟访问配合简单图表工具,可以完成信息抓取和洞察分析。不需要动用复杂框架,依靠灵活组合也能产出有价值的分析图表。