一、导入库
(一)requests库
具体可阅读库学习01-Requests
作用:用于发送 HTTP 请求(例如 GET、POST 等),与网站或 API 进行交互,爬取网页内容。
(二)pandas库
具体可阅读库学习02-Pandas库
作用:用于数据处理和分析,特别适合处理结构化数据(如表格数据)。将爬取的数据保存为结构化文件(如 CSV)。
(三)BeautifulSoup(来自bs4库)
作用:用于解析 HTML 和 XML 文档,提取所需的数据。
import requests
import pandas as pd
from bs4 import BeautifulSoup
二、模拟浏览器访问
# 设置请求头,模拟浏览器访问
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0',
'Cookie': (
'__ac_nonce=06792f58b00b900af693d; '
'__ac_signature=_02B4Z6wo00f01PNpT5AAAIDDHN6IaxwsGFjzWEsAAFtO72; '
'_ga=GA1.1.1530938358.1737684374; '
'_ga_QEHZPBE5HH=GS1.1.1737684373.1.1.1737684766.0.0.0; '
'csrftoken=27b9e05eec16b3aac691fc5545d7fcc2; '
'gfkadpd=24,6457; '
'local_city_cache=ä¿å®; '
's_v_web_id=verify_m6a4est8_7isoi424_gRvq_4RiH_9bHR_7dSSVzDAx5KI; '
'tt_scid=o5ZRFvwaS8JK8msI6aMFXDjdIfIMb71Afpbgmxf9z8w-n5Y5VbpXNEiD3kMxJR7Vae43; '
'tt_webid=7463297399328228904; '
'ttcid=38da4d430cfb4cbaa0e5b7ed0059507a10; '
'ttwid=1|SayyiwHBZrjOELkSGKG_di1lrwHVLMjJBNNxAUL06Ls|1737684555|b669d88183ad12b32ad0f8215d9793816a160d4fac573be88de1892ab053247b; '
'x-web-secsdk-uid=015289ab-5ad1-4c92-833c-8fe60fcea282'
)
}
三、搜索url
# 今日头条搜索URL(爱国标签)
url = 'https://www.toutiao.com/api/search/content/'
params = {
'keyword': '爱国', # 搜索关键词
'offset': 0, # 分页偏移量
'format': 'json', # 返回格式
'autoload': 'true',
'count': 20, # 每页数量
'cur_tab': 1,
'from': 'search_tab'
}
注意:
-
这是一个专门用于返回搜索结果的 API 接口,通常返回结构化的 JSON 数据,方便程序解析。它是为开发者或前端页面动态加载数据设计的,因此返回的数据格式是标准的 JSON。https://www.toutiao.com/api/search/content/
: -
这是一个面向用户的搜索页面 URL,通常返回的是完整的 HTML 页面,包含搜索结果、广告、推荐内容等。它的主要用途是直接在浏览器中展示,而不是提供结构化的数据。https://so.toutiao.com/search?dvpf=pc&source=input&keyword=%E7%88%B1%E5%9B%BD
:
四、爬取数据
# 存储新闻标题的列表
news_titles = []
# 爬取多页数据
for page in range(5): # 爬取前5页数据
params['offset'] = page * 20 # 每页20条数据
response = requests.get(url, headers=headers, params=params)
# 检查请求是否成功
if response.status_code == 200:
print(f"第 {page + 1} 页请求成功,正在解析数据...")
try:
data = response.json()
if data and 'data' in data:
for item in data['data']:
if 'title' in item and item['title'].strip(): # 确保标题非空
news_titles.append(item['title'].strip())
else:
print("返回的数据无效或为空")
except Exception as e:
print(f"解析数据时出错: {e}")
else:
print(f"请求失败,状态码:{response.status_code}")
break
这段代码中的:
if data and 'data' in data:
for item in data['data']:
其实是两个判断条件:
(1)确保 data
不是 None
(2)确保 data
字典中包含一个名为 'data'
的键。这是因为服务器返回的 JSON 数据可能是一个嵌套结构,真正的新闻数据可能存储在 data['data']
中。
例如,假设服务器返回的 JSON 数据格式如下:
{
"status": "success",
"data": [
{"title": "新闻标题1"},
{"title": "新闻标题2"}
]
}
在这种情况下:
-
data
是整个 JSON 解析后的字典。 -
‘data'
是字典中的一个键,其值是一个列表,列表中包含多个新闻条目。
五、保存标题为CSV文件
CSV 文件是一种结构化的数据格式,适合存储表格形式的数据(如新闻标题),每行可以存储一个新闻标题,列可以存储标题的附加信息(如发布时间、来源等)。
CSV文件的好处?CSV 文件是纯文本文件,格式简单,易于人类阅读和编辑;相比于其他格式(如 JSON、XML),CSV 文件的存储空间更小,因为它只存储数据本身,没有额外的标记或结构;CSV 文件可以直接导入到数据分析工具(如 Pandas、Excel、Tableau 等)中进行进一步处理。
# 将标题保存到CSV文件
if news_titles:
df = pd.DataFrame(news_titles, columns=['Title'])
df.to_csv('news_data.csv', index=False, encoding='utf-8-sig')
print(f"爬取完成,共获取 {len(news_titles)} 条新闻标题,已保存到 news_data.csv 文件。")
else:
print("未获取到任何新闻标题。")
以下为完整代码:(爬取今日头条关于“爱国”标签的新闻标题)
import requests
import pandas as pd
from bs4 import BeautifulSoup
# 设置请求头,模拟浏览器访问
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0',
'Cookie': (
'__ac_nonce=06792f58b00b900af693d; '
'__ac_signature=_02B4Z6wo00f01PNpT5AAAIDDHN6IaxwsGFjzWEsAAFtO72; '
'_ga=GA1.1.1530938358.1737684374; '
'_ga_QEHZPBE5HH=GS1.1.1737684373.1.1.1737684766.0.0.0; '
'csrftoken=27b9e05eec16b3aac691fc5545d7fcc2; '
'gfkadpd=24,6457; '
'local_city_cache=ä¿å®; '
's_v_web_id=verify_m6a4est8_7isoi424_gRvq_4RiH_9bHR_7dSSVzDAx5KI; '
'tt_scid=o5ZRFvwaS8JK8msI6aMFXDjdIfIMb71Afpbgmxf9z8w-n5Y5VbpXNEiD3kMxJR7Vae43; '
'tt_webid=7463297399328228904; '
'ttcid=38da4d430cfb4cbaa0e5b7ed0059507a10; '
'ttwid=1|SayyiwHBZrjOELkSGKG_di1lrwHVLMjJBNNxAUL06Ls|1737684555|b669d88183ad12b32ad0f8215d9793816a160d4fac573be88de1892ab053247b; '
'x-web-secsdk-uid=015289ab-5ad1-4c92-833c-8fe60fcea282'
)
}
# 今日头条搜索URL(爱国标签)
url = 'https://www.toutiao.com/api/search/content/'
params = {
'keyword': '爱国', # 搜索关键词
'offset': 0, # 分页偏移量
'format': 'json', # 返回格式
'autoload': 'true',
'count': 20, # 每页数量
'cur_tab': 1,
'from': 'search_tab'
}
# 存储新闻标题的列表
news_titles = []
# 爬取多页数据
for page in range(5): # 爬取前5页数据
params['offset'] = page * 20 # 每页20条数据
response = requests.get(url, headers=headers, params=params)
# 检查请求是否成功
if response.status_code == 200:
print(f"第 {page + 1} 页请求成功,正在解析数据...")
try:
data = response.json()
if data and 'data' in data:
for item in data['data']:
if 'title' in item and item['title'].strip(): # 确保标题非空
news_titles.append(item['title'].strip())
else:
print("返回的数据无效或为空")
except Exception as e:
print(f"解析数据时出错: {e}")
else:
print(f"请求失败,状态码:{response.status_code}")
break
# 将标题保存到CSV文件
if news_titles:
df = pd.DataFrame(news_titles, columns=['Title'])
df.dropna().drop_duplicates().to_csv('news_data.csv', index=False, encoding='utf-8-sig')
print(f"爬取完成,共获取 {len(news_titles)} 条新闻标题,已保存到 news_data.csv 文件。")
else:
print("未获取到任何新闻标题。")
运行结果: