爬取无法翻页网页——自然科学基金项目及可视化
本文作者:方 言,中南财经政法大学金融学院
本文编辑:尚晨曦
技术总编:王子一
Stata&Python云端课程来啦!
好雨知时节,当春乃发生。为了感谢大家长久以来的支持和信任,爬虫俱乐部为大家送福利啦!!!Stata&Python特惠课程双双上线腾讯课堂~原价2400元的Python编程培训课程,现在仅需100元,详情请查看推文《Python云端课程福利大放送!0基础也能学~》。关于Stata,爬虫俱乐部推出了系列课程,内容包括字符串函数、正则表达式、爬虫专题和文本分析,可以随心搭配,价格美丽,物超所值,更多信息可查看Stata系列推文《与春天有个约会,爬虫俱乐部重磅推出正则表达式网络课程!》、《与春天有个约会,爬虫俱乐部重磅推出基本字符串函数网络课程》等。变的是价格,不变的是课程质量和答疑服务。对报名有任何疑问欢迎在公众号后台和腾讯课堂留言哦!
在之前的推文《用词云图看2020社科基金课题~》中,我们直接获取了社会科学基金的课题并对其进行了词云分析。今天呢,我们就来看一下自然科学基金的项目公示情况。由于2020年自科项目公示较少,因此本文先爬取2017年-2019年的自科项目,目的是借助爬虫对已公布的课题进行抓取和整理;最后,本文针对爬取的申请领域实现可视化操作,绘制词云图。接下来,让我们看一下具体是怎么操作的吧~
一、网页介绍首先,进入自然科学基金的官网(https://fund.cingta.com/),通过高级检索输入我们想要的信息,由于高级检索需要会员才能爬取,我们可以通过分享邀请码获取限时免费的会员,得到会员身份之后,通过高级检索筛选出我们想要的自科基金项目。本文获取的是2017-2019年管理学部自科基金项目,因此在高级检索中输入如下信息:
但是申报领域在检索过程中是没有被筛选出来的:
F12
进入到Chrome
开发者工具中,点击Network
并刷新一下。由于换页时候URL
并没有发生变动,考虑网页中的数据可能是AJAX
加载(AJAX
是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX
可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新),因此我们在Network
的XHR
中进行查找,并成功在“query-fund/”得到了真实的网页链接。Headers
,可以看到Request Method
中显示本网页使用的是POST
方法,页数(pageNo)、每页条数(pageSize)等信息都可以在Form Data
中找到,这样我们就找到了翻页的依据。首先,我们调用需要用的库:
import requests
import time
import json
import math
通过在上一部分的分析,我们这里运用requests.post()
发送网页请求,并对页码进行循环。由于返回的数据类型为json
格式,我们使用json.loads()
解析网页返回的信息,并写入到2017年-2019年管理科学部自科基金项目.csv
当中。由于每页只显示20个项目,但是在爬取的过程中发现,最大的爬取页数为500页,即每次最多只能获取10000个项目,大家可以根据自己的需求查看相对应领域的项目,只要一次的检索数量低于10000个即可。因此这里对自科基金分类中的管理科学部下属的107个项目领域进行爬取,由于单个领域的项目没有整体那么多,所以循环的页码一般是不会到500页的,当然按照500页进行循环也是可以的,只是非常的浪费时间,这里我们通过获取每个领域的项目总数再除以每页最大显示20条就能够获取领域需要循环的页码数,这里我们先将管理科学部下属的领域整理成列表:subject=["管理科学与工程","管理理论与研究方法论","运筹与管理","决策理论与方法","博弈理论与方法","评价理论与方法","预测理论与方法",\
"管理统计理论与方法","管理心理与行为","管理系统工程","管理系统分析","管理系统计算与仿真","管理系统复杂性","工业工程与管理",\
"物流与供应链理论","服务科学与工程","系统可靠性与管理","信息系统与管理","信息系统及其管理","决策支持系统","数据挖掘与商务分析",\
"知识管理","风险管理","金融工程","工程管理","交通运输管理","工商管理","战略管理","组织理论与组织行为","组织理论","组织行为",\
"企业技术管理与创新管理","人力资源管理","财务管理","会计与审计","市场营销","营销模型","消费者行为","营销战略","生产与质量管理",\
"生产管理","质量管理","企业信息管理","企业信息资源管理","商务智能","电子商务","运营管理","企业物流与供应链管理","服务管理",\
"项目管理","创业管理","国际商务与跨文化管理","经济科学","博弈论与信息经济","行为经济与实验经济","计量经济与经济计算",'经济发展与贸易',\
'经济增长与发展',"贸易经济","货币政策与财税政策","金融管理","银行体系管理","金融市场管理","金融创新管理","人口资源环境经济与劳动经济",\
'劳动经济','人口资源环境经济','农林经济管理','林业经济管理','农业经济管理','农村改革与发展','食物经济管理','区域经济与产业经济',\
'区域经济管理','产业经济管理','宏观管理与政策','公共管理','公共管理基础理论','政府组织管理','社会与区域治理','政策科学理论与方法',\
'非营利组织管理','科技管理与政策','科学计量学与科技评价','科研管理','知识产权管理','创新管理与政策','卫生管理与政策',\
'卫生政策','药事管理','医院管理','社区卫生管理','健康服务管理','中医药管理与政策','教育管理与政策','文化与休闲产业管理',\
'公共安全与危机管理','社会福利管理','环境与生态管理','资源管理与政策','区域发展管理','区域发展战略管理','城镇发展与管理',\
'信息资源管理','图书情报档案管理','社会与政府信息资源管理','电子政务']
接着,我们获取到每个领域的总项目数量(这里需要有会员身份才可以运行,获取会员身份后保持登陆状态并更换案例中给到的Cookie):
base_url="https://fund.cingta.com/api/query-fund/"
headers={
'Cookie': 'UM_distinctid=17983639a7720e-0b374960e61d9d-2363163-100200-17983639a78cc; sessionid=hdmo9dphxymis0kp3z1pd5l1gjpp7zmw; CNZZDATA1276339390=1509971688-1621406626-%7C1621434862; CNZZDATA1254581267=767189894-1621406627-%7C1621434862',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'
}
number_list=[]
for j in subject:
data={
'pageNo': 1,
'pageSize': 20,
'orderby': 1,
'searchtype': '(立项年份=2017-2019) AND (资助机构=["中国国家自然科学基金委员会"])AND (申报领域=["{}"])'.format(j)
}
response=requests.post(base_url,headers=headers,data=data).text
data=json.loads(response)
for item in data['data']['category']['subject']:
#print(item['doc_count'])
number=item['doc_count']
number_list.append(item['doc_count'])
print(number_list)
math
函数中的ceil
进行向上取整,进而对每个领域的项目进行爬取:title_list=[]
agency_list=[]
money_list=[]
leader_list=[]
date_list=[]
sponser_list=[]
field_list=[]
for j in subject:
for number in number_list:
num=math.ceil(number/20)+1
# print(num)
for i in range(1,num):
data={
'pageNo': i,
'pageSize': 20,
'orderby': 1,
'searchtype': '(立项年份=2017-2019) AND (资助机构=["中国国家自然科学基金委员会"])AND (申报领域=["{}"])'.format(j)
}
response=requests.post(base_url,headers=headers,data=data).text
data=json.loads(response)
#print(data)
for item in data['data']['query']['data']:
title=str(item['project'])
agency=str(item['org'])
money=str(item['amount'])
leader=str(item['leader'])
date=str(item['year'])
sponser=str(item['fund']['cn_full_name'])
field=str(item['subject'])
# print(title)
title_list.append(title)
agency_list.append(agency)
money_list.append(money)
leader_list.append(leader)
date_list.append(date)
sponser_list.append(sponser)
field_list.append(field)
print("当前在"+str(j)+"领域")
最终,我们将爬取的结果写入到csv
文件中:file = "2017年-2019年管理科学部自科基金项目.csv"
with open(file, "w", encoding = 'gb18030') as f :
f.write('''"项目名称","受资机构","金额","负责人","日期","资助机构","申报领域"\n''')
for title,agency,money,leader,date,sponser,field in zip(title_list,agency_list,money_list,leader_list,date_list,sponser_list,field_list):
info =title+","+agency+","+money+","+leader+","+date+","+sponser+","+field
info = '''"%s","%s","%s","%s","%s","%s","%s"\n''' % (title,agency,money,leader,date,sponser,field)
f.write(info)
print("结果已输出到"+file)
在输出的文件中,显示2017年-2019年管理科学部的自科基金项目有1913个:csv
文件,获取到项目名称后将其转换为文本,这里可能会出现'utf-8' codec can't decode byte 0xcf in position 0: invalid continuation byte
的报错,将csv
文件另存为csv
文件utf-8
编码格式的即可,之所以不在输出csv
文件时用utf-8
编码,是因为会出现乱码的情况:#将csv文件从gb18030编码转换成utf-8编码
import chardet
import codecs
file_in = '2017年-2019年管理科学部自科基金项目.csv'
file_out = '2017年-2019年管理科学部自科基金项目.csv'
encode_in = 'gb18030'
encode_out = 'utf-8'
with codecs.open(filename=file_in,mode='r',encoding=encode_in) as fin:
data = fin.read()
with open(file_out,mode='w',encoding=encode_out,newline='') as fout:
fout.write(data)
fout.close()
读入csv
文件,获取到项目名称后将其转换为文本:
import pandas as pd
data = pd.read_csv('2017年-2019年管理科学部自科基金项目.csv') #'utf-8' codec can't decode byte 0xcf in position 0: invalid continuation byte出现这种报错
#把源文件重新另存为utf-8的编码格式
a=data["项目名称"]
text=[]
n=0
for i in a :
text.append(i)
n+=1
接着对转换成文本的项目名称进行分词并做词云图:
import jieba
from PIL import Image
import numpy as np
from collections import Counter
import matplotlib.pyplot as plt
from wordcloud import WordCloud, STOPWORDS
#jieba.load_userdict(r"C:\Users\PC\Desktop\词典.txt") #添加自定义词典
result=[]
seg_list = jieba.lcut(str(text))
seg_list=filter(lambda word:len(word)>3,seg_list)#过滤长度为1的词
result.extend(seg_list) #将分词结果加入到列表result中
word_counts = Counter(result) # 对分词做词频统计
stopwords=set(STOPWORDS)
with open('停用词表.txt',encoding='UTF-8') as f:
stop_words=[i.strip() for i in f.readlines()]
for word in stop_words:
stopwords.add(word)
#在上述操作之后,导入背景图,便可使用WordCloud来制作词云图:
images = Image.open("people.png")
maskImages = np.array(images)
w=WordCloud(
background_color='white', # 设置背景颜色
font_path="msyh.ttc", #设置输出词云的字体为微软雅黑
width=400, height=400, #设置词云图的宽度,高度
max_words=1000,
min_font_size=1,
scale=8,
stopwords=stopwords ,
mask=maskImages #设置词云形状
)
wordcloud=w.generate_from_frequencies(word_counts) #加载词云文本
#到这里,我们以完成了基本步骤,为了让图片的色彩更加丰富,小编在这里导入一张渐变色的背景图片,操作如下:
#设置背景色
#展示图片
plt.figure(figsize = (10,8))
plt.imshow(wordcloud,interpolation='bilinear')
plt.axis("off") #设置显示的词云图中无坐标轴
plt.show()
w.to_file('社科.png')
通过结果输出可以看到,比较热门的研究科题为技术创新、资源配置、生态系统、不确定性、金融风险等。大家可以参考本篇推文获取其他领域的项目信息~
最后,我们为大家揭秘雪球网(https://xueqiu.com/)最新所展示的沪深证券和港股关注人数增长Top10。
欢迎大家点赞、评论、转发呦~
对我们的推文累计打赏超过1000元,我们即可给您开具发票,发票类别为“咨询费”。用心做事,不负您的支持!
往期推文推荐爬取京东评论数据进行情感分类
Stata与音乐之间的酷炫连接
这些年,爬虫俱乐部走出的博士们!看这里,近五年各校高被引论文上榜名单!
高校经管类核心期刊发文排行榜
疯狂的科研创新加速器——Stata!
可盐可甜,“粽”有所爱,快来pick你最爱的粽子吧!
好玩有趣的手绘图形库——cutecharts
爬虫实战|摩尔庄园微博话题讨论
一季度财报出炉,哪些公司最烧钱?
一季度财报出炉,哪些公司最赚钱?
技能篇 | 图片合并大法
批量空气质量数据文件合并分析
Stata17之日期时间新功能
Stata17之Lasso新功能
爱奇艺视频弹幕爬取之《小舍得》 数据可视化利器——Matplotlib从第七次人口普查看中国人口变化|Stata与Python交互绘图
200万投资者关注!!哪家公司这么牛?
带你领略一天天气之变化
利用pyecharts看微博粉丝地区分布
零值太多怎么办?解锁Stata17新命令ziologit
Stata17新功能之Python API 小罗肥归升级啦|解锁Stata17之新命令xtmlogit 初识PyStata
辞旧迎新——Stata17之Do-file编辑器优化
Stata17新亮点——解放表格输出生产力
【爬虫+可视化】链家网北京租房信息
关于我们
微信公众号“Stata and Python数据分析”分享实用的Stata、Python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。
此外,欢迎大家踊跃投稿,介绍一些关于Stata和Python的数据处理和分析技巧。
投稿邮箱:statatraining@163.com投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。