爬虫:红网网站, 获取指定关键词与指定时间范围内的新闻,并存储到CSV文件 V2.0(控制台版)
爬取目的:为了获取某一地区更全面的在红网已发布的宣传新闻稿,同时也让自己的工作更便捷
对比V1.0升级的内容:可自定义输入查询的关键词、自定义获取的时间段内的新闻,这样大家都可以用
环境:Pycharm2021,Python3.10,
安装的包:requests,csv,bs4,datetime
代码运行结果示例:
爬虫完整代码如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/4/4 21:36
# @Author : LanXiaoFang
# @Site :
# @File : RedNet.py
# @Software: PyCharm
import csv
import requests
from bs4 import BeautifulSoup
import datetime
header = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept - Encoding': 'gzip, deflate, br',
"Accept - Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
'Connection': "keep - alive",
'Referer': 'https://news-search.rednet.cn/Search?q=%E5%8F%8C%E7%89%8C',
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0",
"Cookie": "wdcid=7486a2c50eaf8af8; Hm_lvt_c96b65e9975fa39afbd5e90222af5f39=1711378746,1711528844; Hm_lvt_aaecf8414f59c3fb0127932014cf53c7=1711378746,1711528844; __jsluid_s=56e0acf3607072cce852b9d4fc556f54; Hm_lpvt_c96b65e9975fa39afbd5e90222af5f39=1711528844; Hm_lpvt_aaecf8414f59c3fb0127932014cf53c7=1711528844; __jsl_clearance_s=1711530480.242|1|%2F%2BG2WNMEpLXiwlUgRr2hiMkP%2BMg%3D",
"Upgrade-Insecure-Requests": "1",
}
article_Num_area = 1 # 用于计在标题含指定区域的存储的表中的数据的序号
article_Num = 1 # 用于计在标题不含但内容含指定区域的存储的表中的数据的序号
get_go = 0 # 获取第几页开始的数据,现在是0开始
count = 0 # 用于计算总共爬取的新闻数量
"""------Start Set 这一部分是自定义选项 查找自定义新闻------"""
# 爬取指定区域的文章 或者关键词 比如:双牌 双牌县 优化营商环境······
print("爬取指定区域的文章 或者关键词 比如:双牌 双牌县 优化营商环境")
# area = '双牌'
area = input("请输入想要搜索的关键词")
# 时间设定
# 想要获取的时间段 是个闭区间 年月日 xxxx-xx-xx
print("请输入你想要获取的时间段 是个闭区间 年月日 xxxx xx xx,例如2024 3 4")
start_time = input("请输入起始时间") # 起始时间(包含起始日期这一天)
start_time = datetime.datetime.strptime(start_time, '%Y %m %d')
end_time = input("请输入截止时间") # 截止时间(包含截止日期这一天)
end_time = datetime.datetime.strptime(end_time, '%Y %m %d')
"""------End Set 这一部分是自定义选项 查找自定义新闻------"""
# 获取系统时间
now = datetime.datetime.now()
year = now.year # 年
month = now.month # 月
day = now.day # 日
# # 创建CSV文件并写入头部信息
with open(str(month) + '红网_标题含关键词.csv', 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['序号', '新闻名称', '新闻来源', '媒体级别', '发布日期', '原文链接']) # 根据实际情况定义列名
with open(str(month) + '红网_标题不含内容含关键词.csv', 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(['序号', '新闻名称', '信息来源', '媒体级别', '发布日期', '原文链接']) # 根据实际情况定义列名
# 相当于满足条件就是一直循环
# while get_go <= 2: # 测试时用,只获取前1-3页的新闻
while get_go >= 0:
url = 'https://news-search.rednet.cn/Search?q=%E5%8F%8C%E7%89%8C&s=0&o=1&r=0&p=' + str(get_go)
html_p = requests.get(url, headers=header)
html_p.encoding = 'utf-8'
get_go += 1
if html_p.status_code == 200:
soups = BeautifulSoup(html_p.text, 'html.parser')
article_info = soups.find_all('div', class_='result')
# print(len(article_info), '\n')
for i in article_info:
result_info = i.find_all('div', class_='result-info')
station_source = result_info[0].select('span') # 选择result_info下的所有span标签
station_info = station_source[0].text # 文章发布站点
source_info = station_source[1].text # 文章来源
print(station_info, source_info)
# print(i.find_all('div', class_='title'), '\n')
title_info = i.find_all('div', class_='title')
# 文章链接
article_href = title_info[0].a.get('href')
print(article_href)
# 升级版2.0,这一部分注释掉了,考虑通过文章链接进入文章详情页面获取: 新闻来源 发布时间,这样可以避免来源分析和计算时间的日期
if station_info[3:] == area + "新闻网":
# print("双牌新闻网文章链接:", article_href, "---------", "https://moment.rednet.cn/pc" + article_href[22:])
article_href = "https://moment.rednet.cn/pc" + article_href[22:]
# 修改文章来源为红网时刻
if 'rednet' in article_href:
source_info = "红网"
if 'moment.rednet' in article_href:
source_info = "红网时刻"
if '来源' in source_info:
source_info = station_info[3:]
# 文章标题
article_title = title_info[0].h3.text
# 获取发布时间
article_up_time = title_info[0].span.text
print('发布时间', article_up_time)
"""本来想直接进入文章详情页面直接获取时间的,但是介于文章来源不同每种网站的时间所在标签也不一样,由此还是决定在这里的时间信息进行处理了"""
# 把显示为进入和昨天的时间,改为具体的日期
# 要注意 今天对应的昨天,
# ---如果是今天是1月1日则昨天的年月日应为上一年的12月31日要注意;
# ---如果今天是2-12月的1日则昨天的年月日应为上一月的最后一天
if article_up_time == '今天':
article_up_time = str(year) + '.' + str(month) + '.' + str(day)
elif article_up_time == '昨天':
if day == 1:
if month == 1:
year -= 1
month = 12
day = 31
else:
month -= 1
if month in [3, 5, 7, 8, 10, 12]:
day = 31
elif month in [4, 6, 9, 11]:
day = 30
elif month == 2:
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0): # 闰年2月
day = 29
else:
day = 28
article_up_time = str(year) + '.' + str(month) + '.' + str(day - 1)
# 修改时间显示格式,-替换为.
else:
# article_up_time = article_up_time[:4] + '.' + article_up_time[5:7] + '.' + article_up_time[8:10]
article_up_time = article_up_time.replace('-', '.')
# print(count, '--名称', article_title, '来源', source_info, '日期', article_up_time, '链接', article_href)
# 得到这篇文章发布的时间的日期格式
date_article_up_time = datetime.datetime.strptime(article_up_time, '%Y.%m.%d')
# 现在有个问题怎么退出循环,时间不满足就退出:现在获取到的新闻的时间<开始时间就退出
if date_article_up_time < start_time:
get_go = -1
break
# 把满足自定义时间的新闻内容保存到csv表格中
if start_time <= date_article_up_time <= end_time:
count += 1
# date_article_up_time = datetime.datetime.strftime(date_article_up_time, "%Y.%m.%d")
print( count, '名称', article_title, '来源', source_info, '日期', date_article_up_time, '链接', article_href)
# 把数据存入表格 根据标题或内容 是否含有 #{area} 关键词 分开存储
if area in article_title:
# 这个是标题含有#{area}的
with open(str(month) + '红网_标题含关键词.csv', 'a', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(
[article_Num_area, article_title, source_info, '级', article_up_time, article_href])
article_Num_area += 1
else:
# 这个是标题不含但是内容含有#{area}的
with open(str(month) + '红网_标题不含内容含关键词.csv', 'a', newline='',
encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
writer.writerow([article_Num, article_title, source_info, '级', article_up_time, article_href])
article_Num += 1