爬虫数据网址:新闻中心滚动新闻_新浪网
最近想获取一些新闻数据来做一个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()
结果如下图所示