最近在研究如何获取得到App知识城邦热门圈子的动态内容时,我发现Playwright这个工具确实是个不错的选择。作为一个长期从事Python爬虫开发的工程师,我想分享一下这个实战项目的完整实现过程,包括技术选型、核心实现和常见问题处理。
这个项目的主要目标是获取得到App知识城邦中热门圈子的动态内容,包括帖子标题、作者、发布时间、点赞数等关键信息。相比传统的爬虫方案,使用Playwright可以更好地模拟真实用户操作,有效应对现代Web应用常见的反爬机制。
在评估了多种爬虫方案后,我最终选择了Playwright作为核心工具,主要基于以下几个考虑:
整个爬取流程可以分为以下几个关键步骤:
建议使用Python 3.8或更高版本。可以使用conda或venv创建虚拟环境:
bash复制python -m venv playwright-env
source playwright-env/bin/activate # Linux/macOS
playwright-env\Scripts\activate # Windows
核心依赖包包括:
bash复制pip install playwright
playwright install # 安装浏览器二进制文件
python复制from playwright.sync_api import sync_playwright
def init_browser(headless=False):
with sync_playwright() as p:
browser = p.chromium.launch(
headless=headless,
args=[
'--disable-blink-features=AutomationControlled',
'--start-maximized'
]
)
context = browser.new_context(
user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
viewport={'width': 1920, 'height': 1080}
)
page = context.new_page()
return browser, page
得到App的登录流程相对复杂,需要处理以下几个关键点:
python复制def login(page, username, password):
page.goto('https://www.dedao.cn/login')
page.fill('input[name="username"]', username)
page.fill('input[name="password"]', password)
# 处理可能的验证码
if page.is_visible('.captcha-container'):
input('请手动完成验证码后按回车继续...')
page.click('button[type="submit"]')
page.wait_for_selector('.user-avatar', timeout=10000)
# 保存登录状态
context = page.context
context.storage_state(path='auth.json')
得到App知识城邦的页面结构特点:
python复制def extract_posts(page):
posts = []
items = page.query_selector_all('.post-item')
for item in items:
post = {
'title': item.query_selector('.post-title').inner_text(),
'author': item.query_selector('.author-name').inner_text(),
'publish_time': item.get_attribute('data-time'),
'like_count': int(item.query_selector('.like-count').inner_text()),
'comment_count': int(item.query_selector('.comment-count').inner_text()),
'content': item.query_selector('.post-content').inner_text()
}
posts.append(post)
return posts
由于得到App采用无限滚动加载,需要模拟滚动操作:
python复制def scroll_to_bottom(page):
prev_height = page.evaluate('document.body.scrollHeight')
while True:
page.evaluate('window.scrollTo(0, document.body.scrollHeight)')
page.wait_for_timeout(2000) # 等待内容加载
new_height = page.evaluate('document.body.scrollHeight')
if new_height == prev_height:
break
prev_height = new_height
根据数据量和使用场景,可以考虑以下几种存储方式:
python复制import json
from datetime import datetime
def save_to_json(data, filename=None):
if not filename:
filename = f'posts_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json'
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f'数据已保存到 {filename}')
python复制import csv
def save_to_csv(data, filename=None):
if not filename:
filename = f'posts_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv'
keys = data[0].keys() if data else []
with open(filename, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=keys)
writer.writeheader()
writer.writerows(data)
print(f'数据已保存到 {filename}')
python复制def main():
# 初始化浏览器
browser, page = init_browser(headless=False)
try:
# 登录(如果已有cookies可以跳过)
if not os.path.exists('auth.json'):
login(page, 'your_username', 'your_password')
else:
context = page.context
context.storage_state(path='auth.json')
# 导航至目标页面
page.goto('https://www.dedao.cn/knowledge/circle/hot')
page.wait_for_selector('.post-item', timeout=10000)
# 滚动加载所有内容
scroll_to_bottom(page)
# 提取数据
posts = extract_posts(page)
print(f'共获取到 {len(posts)} 条帖子')
# 保存数据
save_to_json(posts)
save_to_csv(posts)
finally:
browser.close()
如果需要定期爬取,可以结合APScheduler实现:
python复制from apscheduler.schedulers.blocking import BlockingScheduler
scheduler = BlockingScheduler()
@scheduler.scheduled_job('interval', hours=6)
def scheduled_job():
print('开始定时爬取任务...')
main()
if __name__ == '__main__':
scheduler.start()
问题现象:无法找到预期的DOM元素
解决方案:
page.wait_for_selector()问题现象:爬虫运行一段时间后需要重新登录
解决方案:
问题现象:请求被拒绝或返回验证码
解决方案:
在实现这个爬虫的过程中,我积累了一些宝贵的经验:
page.pause()进入调试模式提示:在实际项目中,建议先从非headless模式开始开发,确保核心流程稳定后再切换到headless模式提高性能。
这个爬虫项目展示了如何使用Playwright处理复杂的现代Web应用爬取任务。通过合理的架构设计和细致的异常处理,可以构建出稳定可靠的数据采集系统。后续还可以考虑将爬虫部署到云服务器,实现自动化数据采集和分析。