使用Python爬取Forbes评论文章时CSV仅生表头无数据求助
解决Forbes.es评论文章爬取仅生成表头的问题
问题分析
你的代码只生成表头无数据,核心原因集中在这几点:
- 反爬拦截:Forbes.es会识别非浏览器发起的请求,直接返回空页面或验证页面,导致无法提取文章链接和内容
- 无异常处理:单个页面/文章爬取失败(元素找不到、请求超时等)会直接终止程序,没有数据写入
- 分页范围不合理:
range(1,60)可能包含不存在的页面,这类页面返回空链接列表
修复后的代码
import requests from bs4 import BeautifulSoup import csv base_url = "https://forbes.es" # 模拟浏览器请求头,绕过基础反爬 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" } def scrape_forbes_article(link): try: response = requests.get(link, headers=headers, timeout=10) response.raise_for_status() # 抛出HTTP错误 soup = BeautifulSoup(response.content, 'html.parser') # 容错提取标题 title_tag = soup.find("h1", {"class": "article__title"}) title = title_tag.text.strip() if title_tag else "" # 容错提取正文 body_tag = soup.find("div", {"class": "article__body"}) body = body_tag.text.strip() if body_tag else "" # 容错提取日期 date_tag = soup.find("time", {"class": "article__date"}) date = date_tag["datetime"] if date_tag else "" return title, body, date except Exception as e: print(f"爬取文章失败 {link}: {str(e)}") return "", "", "" def get_article_links(page_link): try: response = requests.get(page_link, headers=headers, timeout=10) response.raise_for_status() soup = BeautifulSoup(response.content, "html.parser") # 提取文章链接,若页面结构更新需调整选择器 article_links = [base_url + item["href"] for item in soup.select("h2.card__title a")] return article_links except Exception as e: print(f"获取页面链接失败 {page_link}: {str(e)}") return [] def main(): articles_data = [] # 先测试1-5页,确认有效后再扩大范围 for i in range(1, 6): page_link = f"https://forbes.es/seccion/opinion/page/{i}/" article_links = get_article_links(page_link) if not article_links: print(f"页面 {page_link} 无可用链接,停止分页遍历") break for link in article_links: title, body, date = scrape_forbes_article(link) # 仅添加有有效内容的条目 if title or body or date: articles_data.append([title, body, date]) with open('forbes_opinion_articles.csv', 'w', newline='', encoding='utf-8') as csvfile: fieldnames = ['Title', 'Body', 'Date'] writer = csv.writer(csvfile) writer.writerow(fieldnames) for article in articles_data: writer.writerow(article) print(f"爬取完成,共写入 {len(articles_data)} 条数据") if __name__ == "__main__": main()
关键修改说明
- 添加请求头:模拟真实浏览器请求,避开网站基础反爬机制
- 异常捕获:处理请求、解析过程中的错误,避免程序直接崩溃,同时打印错误信息方便排查
- 容错提取:每个元素提取前先判断是否存在,避免出现AttributeError
- 分页终止逻辑:遇到无链接的页面时停止遍历,减少无效请求
- 数据过滤:只保留有有效内容的条目,避免CSV出现空行
内容的提问来源于stack exchange,提问作者AnukS
相关产品推荐
相关产品推荐

