美文网首页
【实战】 stata-教育部文件数据爬取(中)

【实战】 stata-教育部文件数据爬取(中)

作者: Hobbit的理查德 | 来源:发表于2020-02-03 11:38 被阅读0次

【实战】 stata-教育部文件数据爬取(上)

1.背景

春节假期,大家在家待着估计都要闲得发慌了。

前两天跟同事聊天,聊到她想获取教育部的政策文件,看看政策走向啥的。

奈何python和R还都没学好,只能先用学会的stata爬取网站数据搞一搞了。

2.需求

3.思路

  1. 获取每页的含文件链接的html,以教育部文件为例,共711页;

  2. 清洗并获得每个文件的链接,以教育部文件为例,共10662条链接;

每页链接.png
  1. 获取每个文件的html,以教育部文件为例,共10662个html;

  2. 清洗每个文件的html,得到文件信息,以教育部文件为例,包括文件id(自定义),标题信息索引生成日期,发文机构,发文字号,信息类别,内容概述,正文标题,正文内容,正文落款,正文日期,页面链接,上传日期,信息拥有司局,公文形式等。

    文件信息.png

参考来源1:https://www.jianshu.com/p/2f0e293866f1
参考来源2:https://www.jianshu.com/p/4d573d50459e

4.过程

经过前3个过程:

①获取每页的含文件链接的html
②清洗并获得每个文件的链接
③获取每个文件的html

得到了每个文件的源代码,虽然根据网上教程,可以将这10662个txt合并再统一处理,但是,合并后就有上百万行,运行起来的速度太慢了,每操作一次都比较卡,还崩了几次……因此,考虑通过循环来处理每个文件。

形成两类数据文件:①每个文件导出1份excel文件,用于查阅和分析文件正文;②生成1份含所有文件的信息,即10662条不重复的数据,用于检索分析所有文件。

以file10(教育部发布《关于在部分高校开展基础学科招生改革试点工作的意见》)的html为例:

可以看出,可以获得字段包括标题信息索引生成日期,发文机构,发文字号,信息类别,内容概述,正文标题,正文内容,正文落款,正文日期,公文形式字段数据。

文件html.png

④清洗每个文件的html

(1)每个链接1个excel文件(含正文内容)

*调用过程②清洗并获得每个文件的链接的步骤四生成的含有所有文件链接的数据jyb_file_all
use C:\study\实战\stata\jyb\jyb_file_all,clear

*将该数据的数据量_N存至暂元N中,不直接写10662,是为了便于以后即使官网数据更新,也不用手动修改循环次数了。
local N=_N

*修改工作路径至文件夹jyb2
cd C:\study\实战\stata\jyb\jyb2

*开始循环
forvalue f=1(1)`N'{
*调入每个文件的源代码的txt文件
infix strL v 1-20000 using file`f'.txt,clear

*将变量v显示更宽,便于查看
format v %1000s

*新增变量row,用于标记每个case所在行数
gen row=_n

*新增变量id,用于标识每个文件
gen id=`f'
  • 开始获取字段数据
*新增变量gwxs(公文形式)
*通过字符串函数ustrregexra去除html标志以及"信息公开_"字符串,|表示或的关系
gen gwxs=ustrregexra(v,`"<div id="xxgk_content_gwbt">|</div>|信息公开_"',"") if regexm(v,"xxgk_content_gwbt")
gwxs.png
*新增变量xxmc(信息名称)
*由于这些字段的数据都在字段名称的下一行,因此,新生成变量后取字段名称下一行的变量v的数据,获取字段信息名称内容
gen xxmc=v[row+1] if regexm(v,"信息名称")&regexm(v,"td")

*通过字符串函数去掉html标志,将原始xxmc字符串分为三段,取第二段
replace xxmc=regexs(2) if regexm(xxmc,"(<td class.*>)(.*)(</td)")
字段信息.png xxmc.png xxmc清洗后.png
*同理,信息索引,生成日期,发文机构,发文字号,信息类别,内容概述字段处理与字段信息名称相同
gen xxsy=v[row+1] if regexm(v,"信息索引")&regexm(v,"td")
replace xxsy=regexs(2) if regexm(xxsy,"(<td class.*>)(.*)(</td)")

gen scrq=v[row+1] if regexm(v,"生成日期")&regexm(v,"td")
replace scrq=regexs(2) if regexm(scrq,"(<td class.*>)(.*)(</td)")

gen fwjg=v[row+1] if regexm(v,"发文机构")&regexm(v,"td")
replace fwjg=regexs(2) if regexm(fwjg,"(<td class.*>)(.*)(</td)")

gen fwzh=v[row+1] if regexm(v,"发文字号")&regexm(v,"td")
replace fwzh=regexs(2) if regexm(fwzh,"(<td class.*>)(.*)(</td)")

gen xxlb=v[row+1] if regexm(v,"信息类别")&regexm(v,"td")
replace xxlb=regexs(2) if regexm(xxlb,"(<td class.*>)(.*)(</td)")

gen nrgs=v[row+1] if regexm(v,"内容概述")&regexm(v,"td")
replace nrgs=regexs(2) if regexm(nrgs,"(<td class.*>)(.*)(</td)")
字段信息清洗后.png
*新增变量zwbt(正文标题),处理与xxmc(信息名称)相似
gen zwbt=ustrregexra(v,"<h1>|</h1>","") if regexm(v,"<h1>")
zwbt.png
*新增变量zwnr(正文内容),这部分比较麻烦,不同文件的内容和html的标识不大一样,需要多次尝试
*当变量v含有以<p.*>或者</p>结尾,或者以<p.*>或者</p>结尾,或者含有字符串"附件",".pdf",".docx",".doc",".xlsx",".xls","<br />"等个案时,将数据复制到变量zwnr中。
*ps:由于有的文件正文只有一个附件或换行显示或<div>包含的一段文字等特殊情况,因此,增加了含有字符串"附件",".pdf",".docx",".doc",".xlsx",".xls","<br />","<div>.*[\u4e00-\u9fff].*</div>"等的判断
*ps:正则表达式中,表示点.需要加转义符\,否则会认为是有特殊功能的元字符

gen zwnr=v if ustrregexm(v,"^(<p.*>).*(</p>)$|^(<P.*>).*(</P>)$|附件|\.pdf|\.docx|\.doc|\.xlsx|\.xls|<br />|(<div>.*[\u4e00-\u9fff].*</div>)|(<DIV.*[\u4e00-\u9fff].*</DIV>)|(<td.*[\u4e00-\u9fff].*</td>)")

zwnr.png
*除去有的文件只有图片的情况,将正文内容中所有的html标志去除,即去除<>的内容,并且,去除带有“版权所有”和“京公网安备11010202007625号”,“扫一扫”字符串的内容
replace zwnr=ustrregexra(zwnr,"<[^>]+>", "") if regexm(v,"jpg")==0
replace zwnr="" if regexm(zwnr,"版权所有|京公网安备11010202007625号|扫一扫")
zwnr清洗后.png
*新增变量zwlk(正文落款)和zwrq(正文日期)
*由于落款和日期都是靠右排布,因此挑出变量v中带有字符串`"<p align="right">"'的内容,复制变量zwlk中,然后将变量zwlk中的html标志清除
gen zwlk=ustrregexra(v,`"<p align="right">|</p>"',"") if regexm(v,`"<p align="right">"')
*根据变量zwlk中带有字符串"月"的内容复制到变量zwrq中,同时,清除变量zwnr中带有字符串"月"的内容
*注意,若字符串中本身带有引号,则需要加`'

gen zwrq=zwlk if regexm(zwlk,"月")
replace zwlk="" if regexm(zwlk,"月")

(ps:由于file10文件中没有落款和时间,则以file1文件为例)


zwlk&zwrq.png
*对上述新增变量添加变量标签
label var gwxs "公文形式"
label var xxmc "信息名称"
label var xxsy "信息索引"
label var scrq "生成日期"
label var fwjg "发文机构"
label var fwzh "发文字号"
label var xxlb "信息类别"
label var nrgs "内容概述"
label var zwbt "正文标题"
label var zwnr "正文内容"
label var zwlk "正文落款"
label var zwrq "正文日期"

  • 对新增的变量进行处理
    将除了字段zwnr(正文内容)和row外的所有字段,都进行复制,这样,每份文件中除了正文内容外,其他字段都相同,也为了后续(2)生成1个excel文件(不含正文内容)方便
*对新增变量gwxs-zwbt zwlk zwrq进行循环处理
foreach i of varlist gwxs-zwbt zwlk zwrq{
*将需要循环的变量倒序排序,使得有数据的排序在前
gsort -`i'

*将变量缺失的内容根据前一行非缺失的内容进行复制填补,也可以用carryforward `i',replace(需要ssc install carryforward)
replace `i' = `i'[_n-1] if missing(`i')
}
*对变量row进行排序,使得正文内容能够按顺序排列下来
sort row

*删除变量zwnr(正文内容)缺失的个案
keep if zwnr!=""

*重新对变量row进行自然数填充
replace row=_n
新增变量处理后.png
*和数据jyb_file_all根据id进行多对一的匹配,获得每个文件的额外信息:页面链接,标题,上传日期,信息拥有司局
merge m:1 id using C:\study\实战\stata\jyb\jyb_file_all
*只保留两份数据中都存在的个案
keep if _merge==3

*删除匹配时生成的变量_merge
drop _merge
合并后.png
  • 附件链接整理

有的文件的正文内容中包含了附件及链接,因此,也整理以下正文内容的附件及链接内容

(ps:由于file10文件中没有附件,则以file1文件为例)


附件html.png

由于附件链接绝大部分是页面链接部分前部分加附件所在的html中的链接拼接而成,

例如,file1文件的网页链接为http://www.moe.gov.cn/srcsite/A01/s7048/202001/t20200122_416318.html,

而附件下载链接为

http://www.moe.gov.cn/srcsite/A01/s7048/202001/W020200122538206720057.pdf

因此,通过提取上述匹配后的网页链接前部分和附件所在的html中的链接进行拼接处理

*新增变量purlsub,获取页面链接中最后一个/前面的内容,以上述为例,即获取http://www.moe.gov.cn/srcsite/A01/s7048/202001/
gen purlsub=regexs(1) if regexm(purl,"(.*/)(.*)")

*对含有字符串href="[^"]*"的变量zwnr(正文内容)进行处理
*将文字+空格+页面链接前部分+提取出的网页链接拼接
replace zwnr=zwnr+" "+purlsub+ustrregexs(0) if ustrregexm(v,`"href="[^"]*""')
*将拼接后的字符串中的"href=",或`"""',或"./"删除
*ps:正则表达式中,表示点.需要加转义符\,否则会认为是有特殊功能的元字符
replace zwnr=ustrregexra(zwnr,`"href=|"|\./"',"")
*将拼接后的字符串中的"//"替换成"/"
replace zwnr=ustrregexra(zwnr,"//","/") 

附件链接.png
  • 每个文件导出excel
*去掉变量v
keep row-zwbt zwlk-purlsub zwnr
*对变量purlsub添加变量标签
label var purlsub "附件链接前缀"
*导出excel数据
export excel "C:\study\实战\stata\jyb\jyb2\data\zw`f'.xlsx",firstrow(varl) replace
}

以file10为例,生成的excel文件zw10:


zw10.png

循环后,获得每个政策文件的excel文件,共10662个:

zw.gif

预告:

《【实战】stata-教育部文件数据爬取(下)》

《【实战】stata-教育部中央文件数据爬取》

《【实战】stata-其他部门文件数据爬取》

相关文章

网友评论

      本文标题:【实战】 stata-教育部文件数据爬取(中)

      本文链接:https://www.haomeiwen.com/subject/lschxhtx.html