爬虫:红网网站, 获取指定关键词与指定时间范围内的新闻,并存储到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 datetimeheader = {'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=' + area + '&s=0&o=1&r=0&p=' + str(get_go)html_p = requests.get(url, headers=header)html_p.encoding = 'utf-8'get_go += 1if 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.textprint('发布时间', 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 -= 1month = 12day = 31else:month -= 1if month in [3, 5, 7, 8, 10, 12]:day = 31elif month in [4, 6, 9, 11]:day = 30elif month == 2:if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0): # 闰年2月day = 29else:day = 28article_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 = -1break# 把满足自定义时间的新闻内容保存到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 += 1else:# 这个是标题不含但是内容含有#{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