Python :爬取人民日报新闻

本文分享了使用Python进行新闻爬取与txt文件批量转换为JSON格式的经验,详细介绍了从爬虫代码到转换脚本的实现过程,适合初学者参考。

引用部分内容:https://blog.csdn.net/wenxuhonghe/article/details/90047081

其实我只是因为在那边评论区想评论,然后发现位置不够,所以才打算写这个博客的,然后具体的可以看我转载的文章,很详细,我这边只说一下关于txt转换为JSON格式的问题

第一次写,格式可能很乱,见谅一下

话不多说,直接开始吧

这是未修改前得到的文本样式

在这里插入图片描述

这里的话可以看到,爬取的文章都是按照日期整整齐齐排列的,所以看起来很舒服方便

然后有些可能就算需要json格式来进行保存

当时看了下评论区,发现有这个要求的也有,也看到了有人在下方评论写了方法

尝试了下,如下图

在这里插入图片描述

格式修改了是不错,不过看着好别扭(密集恐惧症的朋友就更不推荐了)

所以再尝试了下其他方法,主要是想着如果能将刚开始运行得到的文件夹里面的所有txt文件一起转

化,然后除了格式,命名啥的不变就完美了,主要是看着方便

于是网上找了一下,再请教了下我组长,得到了如下

在这里插入图片描述

这里面关于json格式我就简单的命名了下title部分,有其他需求的可以自己命名下

至于功能的话我觉得应该是可了的,直接全部转化,简洁方便,速度的话也快

代码如下

import json
import re


def txtToJson(path, out_path):
    # 文件路径
    # path = "E:/Python/news require/data/20190502/20190502-01-01.txt"
    # 读取文件
    with open(path, 'r', encoding="utf-8") as file:
        # 定义一个用于切割字符串的正则
        seq = re.compile(":")
        result = []
        # 逐行读取
        for line in file:
            lst = seq.split(line.strip())
            item = {
                "title": lst[0]
            }
            result.append(item)
        print(type(result))
        # print(result)
        # 关闭文件
    with open(out_path, 'w', encoding='utf-8') as dump_f:
        json.dump(result, dump_f, ensure_ascii=False, indent=4)


def txtToJson_ext():
    # 文件路径
    # path = "E:/Python/news require/data/20190502/20190502-01-01.txt"
    # 读取文件
    import glob
    import os

    out_root = './data_json'

    for path in glob.glob('./data/*/*.txt'):
        # print(path)
        filename = os.path.basename(path)
        data_dir = path.split('\\')[1]
        filename = f'{filename.split(".")[0]}.json'
        # print(filename)
        # print(data_dir)

        # 创建目录
        out_dir = f'{out_root}/{data_dir}'
        if not os.path.exists(out_dir):
            os.makedirs(out_dir)

        out_path = f'{out_dir}/{filename}'
        print(out_path)


def test():
    # txtToJson()
    txtToJson_ext()


if __name__ == '__main__':
    import fire
    fire.Fire()

这里是转换格式部分的代码

这里的话直接运行test函数块部分就可以了

遍历了原来之前的data目录,然后生成新的文件夹将转换后的内容填入

爬取新闻部分代码

import requests
import bs4
import os
import datetime
import time


def fetchUrl(url):  # 用于发起网络请求,可以访问目标URL,获取目标网页的html内容并返回
    '''
    功能:访问url的网页,获取页面内容并返回
    参数:目标网页的url
    返回:目标网页的html内容
    '''
    headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
    }
    '''
    accept 头属性能被用在浏览器响应接受的media类型,表示自己可以接受的类型
    user-agent:告诉HTTP服务器,客户端使用的操作系统和浏览器的名称和版本
    '''
    r = requests.get(url, headers=headers)
    r.raise_for_status()  # 判断是否访问成功
    r.encoding = r.apparent_encoding
    return r.text


def getPageList(year, month, day):  # 爬取当天报纸的各版面的链接,将其保存为一个数组,并返回
    '''
    功能:获取当天报纸的各版面的链接列表
    参数:年,月,日
    '''
    url = 'http://paper.people.com.cn/rmrb/html/' + year + \
        '-' + month + '/' + day + '/nbs.D110000renmrb_01.htm'
    html = fetchUrl(url)
    bsobj = bs4.BeautifulSoup(html, 'html.parser')
    '''
    pageList = bsobj.find('div', attrs={'id': 'pageList'}).ul.find_all(
        'div', attrs={'class': 'right_title-name'})
    网站兼容式更新
    '''
    temp = bsobj.find('div', attrs={'id': 'pageList'})
    if temp:
        pageList = temp.ul.find_all('div', attrs={'class': 'right_title-name'})
    else:
        pageList = bsobj.find('div', attrs={
                              'class': 'swiper-container'}).find_all('div', attrs={'class': 'swiper-slide'})
    linkList = []
    # 分析网页html结构
    for page in pageList:
        link = page.a["href"]
        url = 'http://paper.people.com.cn/rmrb/html/' + \
            year + '-' + month + '/' + day + '/' + link
        linkList.append(url)

    return linkList


def getTitleList(year, month, day, pageUrl):  # 爬取当天报纸的某一版面所有文章的链接,并保存为一个数组并返回
    '''
    功能: 获取报纸某一版面的文章链接列表
    参数: 年, 月, 日, 该版面的链接
    '''
    html = fetchUrl(pageUrl)
    bsobj = bs4.BeautifulSoup(html, 'html.parser')
    '''
    titleList = bsobj.find('div', attrs={'id': 'titleList'}).ul.find_all('li')
    '''
    temp = bsobj.find('div', attrs={'id': 'titleList'})
    if temp:
        titleList = temp.ul.find_all('li')
    else:
        titleList = bsobj.find(
            'ul', attrs={'class': 'news-list'}).find_all('li')
    linkList = []

    for title in titleList:
        tempList = title.find_all('a')
        for temp in tempList:
            link = temp["href"]
            if 'nw.D110000renmrb' in link:

                url = 'http://paper.people.com.cn/rmrb/html/' + \
                    year + '-' + month + '/' + day + '/' + link
                linkList.append(url)

        return linkList


def getContent(html):  # 用于返回文章内容页,爬取文章的标题和正文,并返回
    '''
    功能: 解析HTML网页,获取新闻的文章内容
    参数: HTML网页内容
    '''
    bsobj = bs4.BeautifulSoup(html, 'html.parser')

    # 获取文章 标题
    title = bsobj.h3.text + '\n' + bsobj.h1.text + '\n' + bsobj.h2.text + '\n'
    # print(title)

    # 获取文章 内容
    pList = bsobj.find('div', attrs={'id': 'ozoom'}).find_all('p')
    content = ''
    for p in pList:
        content += p.text + '\n'
    # print(content)
    # 返回结果 标题+内容
    resp = title + content
    return resp


def saveFile(content, path, filename):  # 将文章内容保存到本地指定文件夹中
    '''
    功能: 将文章内容 content 保存到本地文件中
    参数: 要保存的内容,路径,文件名
    '''
    # 如果没有文件夹,则自动生成
    if not os.path.exists(path):
        os.makedirs(path)

    # 保存文件
    with open(path + filename, 'w', encoding='utf-8') as f:
        f.write(content)


def download_rmrb(year, month, day, destdir):
    # 可以根据year,month,day参数下载该天的全部报纸文章内容,并按规则保存在指定路径destdir下
    '''
    功能:爬取 人民日报 网站 某年,某月,某日的新闻内容,并保存在指定目录下
    参数: 年,月,日,文件保存的根目录
    '''
    pageList = getPageList(year, month, day)
    for page in pageList:
        titleList = getTitleList(year, month, day, page)
        for url in titleList:

            # 获取新闻文章内容
            html = fetchUrl(url)
            content = getContent(html)

            # 生成保存的文件路径及文件名
            temp = url.split('_')[2].split('.')[0].split('-')
            pageNo = temp[1]
            titleNo = temp[0] if int(temp[0]) >= 10 else '0' + temp[0]
            path = destdir + '/' + year + month + day + '/'
            fileName = year + month + day + '-' + pageNo + '-' + titleNo + '.txt'

            # 保存文件
            saveFile(content, path, fileName)


def gen_dates(b_date, days):
    day = datetime.timedelta(days=1)
    for i in range(days):
        yield b_date + day * i


def get_date_list(beginDate, endDate):
    '''
    获取日期列表
    param start:开始日期
    param end:结束日期
    return:开始日期和结束日期之间的日期列表
    '''

    start = datetime.datetime.strptime(beginDate, "%Y%m%d")
    end = datetime.datetime.strptime(endDate, "%Y%m%d")

    data = []
    for d in gen_dates(start, (end-start).days):
        data.append(d)

    return data


if __name__ == '__main__':
    '''
    主函数: 程序入口
    '''
    # 输入起止日期,爬取之间的新闻
    beginDate = input('请输入开始日期:')
    endDate = input('请输入结束日期:')
    data = get_date_list(beginDate, endDate)

    for d in data:
        year = str(d.year)
        month = str(d.month) if d.month >= 10 else '0' + str(d.month)
        day = str(d.day) if d.day >= 10 else '0' + str(d.day)
        download_rmrb(year, month, day, 'E:/PYTHON/news require/data')
        print("爬取完成: " + year + month + day)
        time.sleep(3)

这里的话我也尝试了将两部分直接合并,然后直接得到txt文件后转化得到json文件,但是一直报错,失败了

(新手小白刚开始自学python,所以一些可能很简单的问题有时候都能让我懵)

如果有大佬成功合并的话可以在评论区支呼一声

就这些吧,其实写这个文章就是为了一个评论

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值