You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3中使用BeautifulSoup构建比特币论坛爬虫的正确方法

完善比特币论坛主题帖子爬虫

嘿,我来帮你补全这个针对Bitcointalk论坛主题的爬虫代码!你已经搭好了基础的请求框架,接下来咱们把所有需要的字段爬取逻辑加上,还能自动遍历主题下的所有页面。

完整代码实现

import requests
from bs4 import BeautifulSoup
import re
import time

# 自定义请求头,避免被反爬拦截
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}

def get_html(url):
    try:
        # 添加延迟,减轻服务器压力
        time.sleep(2)
        r = requests.get(url, headers=HEADERS)
        r.raise_for_status()  # 检查请求是否成功
        r.encoding = 'utf-8'
        return r.text
    except requests.exceptions.RequestException as e:
        print(f"请求出错: {e}")
        return None

def parse_posts(html):
    if not html:
        return []
    
    soup = BeautifulSoup(html, 'html.parser')
    posts = []
    
    # 遍历所有帖子容器
    post_wrappers = soup.find_all('div', class_='post_wrapper')
    for wrapper in post_wrappers:
        post_data = {}
        
        # 1. 用户名
        username_elem = wrapper.find('a', class_='bbc_username')
        post_data['username'] = username_elem.text.strip() if username_elem else '匿名用户'
        
        # 2. 用户状态(在线/离线)
        status_elem = wrapper.find('span', class_=['online', 'offline'])
        post_data['status'] = status_elem['title'].strip() if status_elem else '未知状态'
        
        # 3. 发帖日期时间
        posttime_elem = wrapper.find('div', class_='posttime')
        # 取title里的绝对时间,避免相对时间(比如"今天10:00")
        post_data['post_datetime'] = posttime_elem.find('span')['title'].strip() if posttime_elem and posttime_elem.find('span') else '未知时间'
        
        # 4. 帖子内容(处理HTML转纯文本)
        content_elem = wrapper.find('div', class_='post', id=re.compile(r'msg_\d+'))
        post_data['content'] = content_elem.get_text(strip=True, separator='\n') if content_elem else '无内容'
        
        # 5. 活跃度(Activity)和Merit值
        poster_info = wrapper.find('dl', class_='poster_info')
        if poster_info:
            # 遍历所有dt-dd对,匹配需要的字段
            dt_elements = poster_info.find_all('dt')
            dd_elements = poster_info.find_all('dd')
            for dt, dd in zip(dt_elements, dd_elements):
                dt_text = dt.text.strip()
                if dt_text == 'Activity:':
                    post_data['activity'] = dd.text.strip()
                elif dt_text == 'Merit:':
                    post_data['merit'] = dd.text.strip()
            # 处理缺失字段
            post_data.setdefault('activity', '0')
            post_data.setdefault('merit', '0')
        else:
            post_data['activity'] = '0'
            post_data['merit'] = '0'
        
        posts.append(post_data)
    
    return posts

def get_next_page_url(html):
    if not html:
        return None
    
    soup = BeautifulSoup(html, 'html.parser')
    # 找到下一页链接(页面底部的"Next"按钮)
    next_link = soup.find('a', text='Next')
    if next_link and 'href' in next_link.attrs:
        return 'https://bitcointalk.org/' + next_link['href']
    return None

def crawl_topic(start_url):
    current_url = start_url
    all_posts = []
    
    while current_url:
        print(f"正在爬取页面: {current_url}")
        html = get_html(current_url)
        if not html:
            break
        
        # 解析当前页面帖子
        page_posts = parse_posts(html)
        all_posts.extend(page_posts)
        
        # 获取下一页链接
        current_url = get_next_page_url(html)
    
    print(f"爬取完成,共获取{len(all_posts)}条帖子")
    return all_posts

# 主程序入口
if __name__ == '__main__':
    start_url = 'https://bitcointalk.org/index.php?topic=2056041.0'
    all_posts = crawl_topic(start_url)
    
    # 可以在这里添加保存数据的逻辑,比如存到CSV或者JSON
    # 示例:保存到JSON文件
    import json
    with open('bitcointalk_posts.json', 'w', encoding='utf-8') as f:
        json.dump(all_posts, f, ensure_ascii=False, indent=4)
    print("数据已保存到bitcointalk_posts.json")

代码说明

  • 请求头与延迟:添加了User-Agent模拟浏览器请求,同时每次请求间隔2秒,避免触发论坛的反爬机制。
  • 字段解析逻辑:
    • 用户名:定位到bbc_username类的链接元素
    • 用户状态:通过online/offline类的span标签获取状态描述
    • 发帖时间:使用span标签的title属性获取绝对时间,避免相对时间的歧义
    • 帖子内容:提取post容器内的纯文本,保留换行结构
    • 活跃度与Merit:遍历用户信息的dt-dd对,匹配对应字段,缺失时默认赋值为0
  • 分页处理:通过页面底部的"Next"按钮链接自动获取下一页地址,直到没有下一页为止
  • 数据保存:示例中将爬取到的所有帖子保存为JSON文件,方便后续分析

注意事项

  • 论坛可能会有反爬机制,如果遇到请求被拦截,可以尝试更换User-Agent或者增加请求延迟
  • 部分用户可能没有填写活跃度或Merit值,代码已经做了空值处理
  • 大量爬取前建议先查看论坛的规则,确保合规

内容的提问来源于stack exchange,提问作者egorkh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:00:19