python爬取新闻数据

爬虫数据网址:新闻中心滚动新闻_新浪网

最近想获取一些新闻数据来做一个NLP的分类模型所以爬取了新浪的一些新闻数据用于学习使用。

首先先查看网页源码:

发现url中id和类别中的s_id相等,经过尝试替换,发现该编号确实是类别所在标签。

有发现page这个参数和页数相同,其中num=50 ,和pageid=153这两个参数没有太大的影响,所以就可以通过修改这两个参数的值来获得不同标签下的url了。

然后通过这个url  放入谷歌浏览器中去抓取数据所在的json:

可以发现每个数据文件所在的json文档为:https://feed.mix.sina.com.cn/api/roll/get?&k=&num=50&lid=2510&pageid=153&page=5

其中传入的参数基本和原来的参数雷同,所以就解析这个json文档,就可以获得新闻的标题,新闻的类别,以及新闻的内容所在的url,而新闻的日期在url中。
但是在获取新闻文本内容的时候发现采用xpath索引不出我想要的东西,获取的内容基本上是对的,但是xpath读取数据还是出现错误,BeautifulSoup也尝试了一下,发现也是一样的结果。

不得已采用正则表达式,但是又出现不通网址之间标签不同的情况,所以这里采用了最笨的办法,判断正则里面有没有获取到东西。源码如下图所示:

for line in list1:
try:
    req = requests.get(line[0])
    req.encoding = "utf-8"
    req = req.text
    content = re.findall('<!-- 行情图end -->.*<!-- news_keyword_pub',req,re.S)
    if len(content)!=0:
        pass
    else:
        content = re.findall('<!-- 正文 start -->.*<!--', req, re.S)
    if len(content)!=0:
       pass
    else:
        content = re.findall('<!--新增众测推广文案-->.*?<!-- ', req, re.S)

但是这里又出现一个问题,日期数据在url中:https://finance.sina.com.cn/stock/usstock/c/2022-03-09/doc-imcwipih7460106.shtml

 https://news.sina.com.cn/o/2022-03-11/doc-imcwipih7927286.shtml

用"/"进行切分的话又不确定索引在哪里,所以也采用最笨的办法进行if判断,尽可能得到长度为10的数据具体代码如下图所示:

print(content)
if len(line[0].split("/")[3])==10:
    out_date.append([line[0].split("/")[3], line[2], line[1], content, label])

elif len(line[0].split("/")[4])==10:
    out_date.append([line[0].split("/")[4], line[2], line[1], content, label])


elif len(line[0].split("/")[5])==10:
     out_date.append([line[0].split("/")[5], line[2], line[1], content, label])

elif len(line[0].split("/")[6]) == 10:
     out_date.append([line[0].split("/")[6],line[2],line[1],content,label])

当然这里可以使用正则表达式,这里我看了一下效果还不错所以就没改了。

所有代码整体如下:

import pandas as pd
import requests
import json
import re
import numpy as np

class get_data():

    def __init__(self,dic,url):
        self.url = url
        self.dic = dic
    def get_url(self,lid,page,pageid=153):
        return self.url +"&lid="+str(lid)+"&pageid="+str(pageid)+"&page="+str(page)

    def get_json_url(self,url):
        out = []
        json_req = requests.get(url)
        user_dict = json.loads(json_req.text)
        print(url)
        for dic in user_dict["result"]["data"]:
            out.append([dic["url"],dic['intro'],dic['title']])

        return out

    def getfind_data(self,list1,label):
        out_date = []

        for line in list1:
            try:
                req = requests.get(line[0])
                req.encoding = "utf-8"
                req = req.text
                content = re.findall('<!-- 行情图end -->.*<!-- news_keyword_pub',req,re.S)
                if len(content)!=0:
                    pass
                else:
                    content = re.findall('<!-- 正文 start -->.*<!--', req, re.S)
                if len(content)!=0:
                    pass
                else:
                    content = re.findall('<!--新增众测推广文案-->.*?<!-- ', req, re.S)

                print(content)
                if len(line[0].split("/")[3])==10:
                    out_date.append([line[0].split("/")[3], line[2], line[1], content, label])

                elif len(line[0].split("/")[4])==10:
                    out_date.append([line[0].split("/")[4], line[2], line[1], content, label])


                elif len(line[0].split("/")[5])==10:
                    out_date.append([line[0].split("/")[5], line[2], line[1], content, label])

                elif len(line[0].split("/")[6]) == 10:
                    out_date.append([line[0].split("/")[6],line[2],line[1],content,label])


            except:
                pass

        return out_date

    def main(self):
        out_data_list = []
        for label,lid in self.dic.items():
            for page in range(1,101):
                he_url = self.get_url(lid,page)
                json_url_list = self.get_json_url(he_url)
                output_data = self.getfind_data(json_url_list,label)
                out_data_list+=output_data
        data = pd.DataFrame(np.array(out_data_list), columns=['时间', '标题', '摘要', '内容','类别'])
        data.to_csv("data.csv")


if __name__ == "__main__":
    data_dic = {"国内":2510,
                "国际":2511,
                "社会":2669,
                "体育":2512,
                "娱乐":2513,
                "军事":2514,
                "科技":2515,
                "财经":2516,
                "股市":2517,
                "美股":2518}
    url = "https://feed.mix.sina.com.cn/api/roll/get?&k=&num=50"
    get = get_data(data_dic,url)
    get.main()

这样就获得到了我的新闻数据了。

然后对数据进行清洗,去掉data.csv中的一些无用的数据。

首先读取data.csv

然后采用正则表达式来获得在中文符号旁边的中文。

import re
def funtion1(x):
    res1 = ''.join(re.findall('[\u4e00-\u9fa5]*[",","。","!","”","%","“",":"]*',x[20:]))
    res1 = res1.replace("\"","")
    
    res1 = res1.replace("引文","")
    res1 = res1.replace("正文","")
    
    return res1

 然后因为这里是进行一个url切分获得数据 所有删掉一些不是不是时间的数据。


# 因为对url进行切片可能获取到的不是时间数据所有使用如下函数删掉
def out_data(x):
    if "2022" in x or "2021" in x or "2020" in x:
        return True
    else:
        return False
data = data[[out_data(i) for i in data["时间"].astype(str)]]
data.to_csv("pre_data.csv")

整体数据清洗的代码如下:

import pandas as pd
import re
data = pd.read_csv("data.csv",index_col=0)
def function_(x):
    if len(x)>2:
        return True
    else:
        return False
def funtion1(x):
    res1 = ''.join(re.findall('[\u4e00-\u9fa5]*[",","。","!","”","%","“",":"]',x[20:]))
    res1 = res1.replace("\"","")
    
    res1 = res1.replace("引文","")
    res1 = res1.replace("正文","")
    
    return res1

# 获取数据内容
data["内容"] = data["内容"].apply(funtion1)
# 数据去重
data = data.drop_duplicates()
# import numpy as np
# 因为对url进行切片可能获取到的不是时间数据所有使用如下函数删掉
def out_data(x):
    if "2022" in x or "2021" in x or "2020" in x:
        return True
    else:
        return False
data = data[[out_data(i) for i in data["时间"].astype(str)]]
data.to_csv("pre_data.csv")
data[data["内容"].apply(function_)]["类别"].value_counts()

结果如下图所示

  • 6
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值