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

Python批量爬取多网站:链接选择器失效,如何正确设置?

解决批量爬取网站帖子时选择器无效的问题

核心问题原因

不同网站的HTML结构差异极大,你用的a.post-link是针对特定网站结构写的选择器,绝大多数网站不会使用这个类名,所以无法匹配到内容。

怎么找到正确的选择器

  • 手动分析单个网站:
    打开目标网站,右键点击任意帖子标题/链接 → 检查元素,查看对应<a>标签的特征:

    • 查看标签的class属性,比如有的网站用a.entry-link、a.post-title-link
    • 查看父级标签的结构,比如帖子可能包裹在<article class="post-item">里,选择器可以写article.post-item > a
    • 用属性匹配,比如帖子链接通常包含/post/或/article/,可以写a[href*="/post/"]
  • 通用兜底选择器(适合批量处理):
    如果不想逐个网站分析,可以先尝试这些通用规则,覆盖大多数常见结构:

    • 匹配标题标签内的链接:h2 > a, h3 > a, h4 > a(大多数帖子标题会放在h2/h3标签里)
    • 匹配带post相关类的父元素下的链接:div.post > a, article.post > a
    • 过滤导航类链接后的所有有效链接:a[href]:not([href*="home"]):not([href*="about"]):not([href*="contact"])

改进后的代码方案

针对1000个网站的批量场景,需要支持自定义选择器+兜底逻辑,同时处理常见问题(相对链接、反爬、错误处理):

1. 导入依赖库

import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
from urllib.parse import urljoin, urlparse

2. 优化爬取函数

def scrape_posts(url, link_selector, title_selector):
    all_posts = []
    # 设置请求头,模拟浏览器访问
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36'
    }
    try:
        response = requests.get(url, headers=headers, timeout=15)
        response.raise_for_status()  # 捕获HTTP错误
        soup = BeautifulSoup(response.content, 'html.parser')

        # 先尝试自定义选择器
        post_elements = soup.select(link_selector)
        
        # 自定义选择器无效时,用兜底规则
        if not post_elements:
            # 优先匹配标题标签内的链接
            post_elements = soup.select('h2 > a, h3 > a, h4 > a')
            # 仍无结果则过滤导航链接
            if not post_elements:
                exclude_keywords = ['home', 'about', 'contact', 'category', 'tag', 'archive']
                post_elements = [
                    a for a in soup.select('a[href]') 
                    if not any(k in a['href'].lower() for k in exclude_keywords)
                ]

        for post_element in post_elements:
            # 处理相对链接,转为绝对链接
            post_link = post_element.get('href', '')
            if post_link:
                post_link = urljoin(url, post_link)
            
            # 获取标题:先尝试自定义选择器,再用链接文本,最后用父元素文本
            post_title = ''
            if title_selector:
                title_tag = post_element.select_one(title_selector)
                if title_tag:
                    post_title = title_tag.get_text(strip=True)
            if not post_title:
                post_title = post_element.get_text(strip=True)
            
            # 只保留有有效链接和标题的条目
            if post_link and post_title:
                all_posts.append({'link': post_link, 'title': post_title})

    except Exception as e:
        print(f"爬取 {url} 失败: {str(e)}")
    return all_posts

3. 批量处理并保存Excel

假设你的网站列表DataFrame为df,包含website_url列,新增自定义选择器列后批量处理:

# 读取网站列表Excel
df = pd.read_excel('websites_list.xlsx')

# 新增自定义选择器列,设置默认值
df['link_selector'] = 'a.post-link'
df['title_selector'] = 'h3.post-title'

# 针对特殊网站修改选择器(示例)
df.loc[df['website_url'] == 'https://example1.com', 'link_selector'] = 'article.post-item > a'
df.loc[df['website_url'] == 'https://example1.com', 'title_selector'] = 'h2.entry-title'

# 批量爬取并生成单个Excel文件
for _, row in df.iterrows():
    url = row['website_url']
    link_sel = row['link_selector']
    title_sel = row['title_selector']
    
    posts = scrape_posts(url, link_sel, title_sel)
    if posts:
        # 用网站域名作为文件名
        domain = urlparse(url).netloc
        pd.DataFrame(posts).to_excel(f'{domain}_posts.xlsx', index=False)
        print(f"已保存 {domain} 的帖子数据")
    # 设置延迟,避免触发反爬
    time.sleep(1)

额外注意事项

  • 动态内容处理:如果网站用JS动态加载帖子(比如滚动加载),requests无法获取到内容,需要用selenium或playwright渲染页面
  • 反爬应对:如果出现频繁被封,可以增加延迟时间、使用代理IP池、随机更换User-Agent
  • 数据去重:可以在爬取后对post_link列去重,避免重复条目

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:11:07