论文部分内容阅读
[摘要]本文通过审计实例介绍运用Go语言开发爬虫程序,批量获取某省金融企业监管处罚数据,对被审计单位及所在地域金融企业进行全方位、立体画像,实现网络公开数据与行内数据的相互补充印证,准确锁定审计目标,提升现场审计效率。
[关键词]内部审计 Go语言 数据分析 爬虫程序
随着信息科技与生产过程的不断融合,人们越来越感受到科技在工作中的重要性。在企业内部审计中,可利用数据分析语言开发网络爬虫程序获取被审计单位的日常经营及社会活动相关数据。Go语言(又称Golang语言),是Google公司开发的一种简洁高效的开源编程语言,具有高并发性和跨平台开发优势,非常适合服务器编程。
一、总体思路
首先,开发的爬虫程序必须善意且自觉遵守Robots协议,开发前要查看网站根目录下的robots.txt文件,根据Robots协议合理进行爬取数据。其次,将爬取到的监管信息,存储到CSV文本及本地MySQL数据库中,并从中筛选出关注单位的处罚信息。
爬虫程序工作原理是抓取网页源代码。源代码中包含网页内容信息和网络链接URL地址,可以继续打开网页中的URL地址,进一步抓取下一层网页内容和网络链接URL地址,这样就可以循环抓取所需网页公布的数据信息。
Go语言抓取网页源代码时,最常用的方法是利用Go语言自带的net/http包工具与正则表达式相配合,匹配抓取想要的内容信息,也可以利用一些根据网页节点属性选择的CSS选择器、Colly或Goquery等框架工具提取所需要的数据信息。
二、具体步骤
(一)分析网页目标地址,封装地址函数
首先,明确爬取目标网站的URL链接地址变化规律,需要爬取的内容是金融机构被监管部门处罚的公开处罚信息;其次,打开具体的行政处罚页面首页发现,每页有18份处罚单的名称和链接地址,打开第二页、第三页等多个行政处罚页面,发现每页都包含18份处罚单的链接,而且前三页链接URL地址是一种类型格式,第四页往后的网页是另一种链接URL格式。所以将两种链接URL格式定义为一个数组切片并赋值给urls变量,封装到Get2Urlt函数中,用if语句自动判断,当页码小于4时取第一种URL格式,其他情况则取第二种URL格式,具体语句如下:
func Get2Urlt(idx int) (url string) {
urls :=
[]string{"http://www.****c.**v.cn/cn/st****/data/tocInfo/Selecr********ItemdId/data_itemId=1515,pageIndex=" + strconv.Itoa(idx) + ",pageSize=18.json",
"http://www.****c.**v.cn/dbircweb/tocInfo/Selecr********ItemdId?itemId=1515&pageSize=18&pageIndex=" + strconv.Itoa(idx)}
if idx < 4 {
url = urls[0]
} else {
url = urls[1]
}
return
}
(二)封装函数,获取单个网页信息
选用Go语言程序自带的net/http包中的Get()方法,根据传入的URL链接地址参数便可发起有效请求,获取网页源代码并赋值给变量resp。因为Http.Get()请求是一种网络资源,用完后应第一时间將其关闭,用defer指定的Close()函数来关闭网络请求,语句如下:
func HttpGet(url string) (result []string, err error) {
resp, err1 := http.Get(url)
if err1 != nil {
err = err1
return
}
defer resp.Body.Close()
data1, err2 := ioutil.ReadAll(resp.Body)
b := UserJsonObj{}
json.Unmarshal([]byte(data1), &b)
if err2 != nil {
err = err2
return
}
urlls := make([]string, 0)
for i := 0; i <= 17; i++ {
urllist :=
"http://www.****c.**v.cn/branch/*******I/view/pages/tcommon/Item****t.html?docId=" + strconv.Itoa(int(b.Data.Rows[i].DocId)) + "&itemId=1515"
urlls = append(urlls, urllist)
}
result = urlls
return
}
(三)创建结构体,存储网络Json数据
创建UserJsonObj结构体,用来存储网页的Json数据并赋值给变量b,用json.Unmarshal工具将json字符串解码到相应的结构体中。创建HttpGet()函数获取每页所有罚单的URL链接地址,循环读出每份处罚单的链接URL地址,将所有罚单的链接URL地址赋值给变量urllist,并追加到数组切片urlls中,再将切片urlls赋值给result并返回GetOnePage()函数,语句如下: type UserJsonObj struct {
RptCode float64 `json:"rptCode"`
Msg string `json:"msg"`
Data Data `json:"data"`
}
type Data struct {
Total float64 `json:"total"`
Rows []Brand `json:"rows"`
}
type Brand struct {
DocId float64 `json:"tocId"`
DocSubtitle string `json:"tocSubtitle"`
PublishDate string `json:"publishDate"`
DocSummarystring`json:"tocSummary"`
DocFileUrl string `json:"tocFileUrl"`
Generaltype string `json:"generaltype"`
PdfFileUrl string `json:"pdfFileUrl"`
ItemName string `json:"itemName"`
SolicitFlag string `json:"tolicitFlag"`
DocTitle string `json:"docTitle"`
Datafrom string `json:"datafrom"`
DocUuid string `json:"docUuit"`
Builddate string `json:"builddate"`
}
func GetOnePage(idx int, page chan int) {
url := Get2Urlt(idx)
authors, err := HttpGet(url)
if err != nil {
fmt.Println("HttpGet err:", err)
return
}
mc := make([]string, 0)
dw := make([]string, 0)
xm := make([]string, 0)
yy := make([]string, 0)
tk := make([]string, 0)
fk := make([]string, 0)
rq := make([]string, 0)
for _, jokeURL := range authors {
conUrl := GetUrlt(jokeURL)
contentUrl :=
"http://www.****c.****v.cn/cn/****ic/data/tocInfo/SelecR****t/data_docId=" + conUrl + ".json"
mc1, dw1, xm1, yy1, tk1, fk1, rq1, err := GetTwoPage(contentUrl)
if err != nil {
fmt.Println("Spider2Page err:", err)
continue
}
mc = append(mc, mc1)
dw = append(dw, dw1)
xm = append(xm, xm1)
yy = append(yy, yy1)
tk = append(tk, tk1)
fk = append(fk, fk1)
rq = append(rq, rq1)
}
SpiderWrPage(idx, mc, dw, xm, yy, tk, fk, rq)
page <- idx
}
(四)封裝函数,进一步获取罚单信息
创建GetTwoPage(contentUrl)函数获取第二层中每份罚单的关键信息。传入参数是加工后的contentUrl罚单链接地址,GetTwoPage函数也是使用net/http包中的Get()方法来获取每张罚单的源代码数据,再用Goquery工具的doc.Find()方法对每张罚单文本中的表格数据进行过滤提取,分别提取出罚单中的名称、被处罚单位、被处罚人姓名、被处罚原因、违反条款、处罚信息和处罚日期等关键信息,将提取到的信息分别返回GetOnePage()函数,语句如下:
func GetTwoPage(contentUrl string) (mc1, dw1, xm1, yy1, tk1, fk1, rq1 string, error) {
[关键词]内部审计 Go语言 数据分析 爬虫程序
随着信息科技与生产过程的不断融合,人们越来越感受到科技在工作中的重要性。在企业内部审计中,可利用数据分析语言开发网络爬虫程序获取被审计单位的日常经营及社会活动相关数据。Go语言(又称Golang语言),是Google公司开发的一种简洁高效的开源编程语言,具有高并发性和跨平台开发优势,非常适合服务器编程。
一、总体思路
首先,开发的爬虫程序必须善意且自觉遵守Robots协议,开发前要查看网站根目录下的robots.txt文件,根据Robots协议合理进行爬取数据。其次,将爬取到的监管信息,存储到CSV文本及本地MySQL数据库中,并从中筛选出关注单位的处罚信息。
爬虫程序工作原理是抓取网页源代码。源代码中包含网页内容信息和网络链接URL地址,可以继续打开网页中的URL地址,进一步抓取下一层网页内容和网络链接URL地址,这样就可以循环抓取所需网页公布的数据信息。
Go语言抓取网页源代码时,最常用的方法是利用Go语言自带的net/http包工具与正则表达式相配合,匹配抓取想要的内容信息,也可以利用一些根据网页节点属性选择的CSS选择器、Colly或Goquery等框架工具提取所需要的数据信息。
二、具体步骤
(一)分析网页目标地址,封装地址函数
首先,明确爬取目标网站的URL链接地址变化规律,需要爬取的内容是金融机构被监管部门处罚的公开处罚信息;其次,打开具体的行政处罚页面首页发现,每页有18份处罚单的名称和链接地址,打开第二页、第三页等多个行政处罚页面,发现每页都包含18份处罚单的链接,而且前三页链接URL地址是一种类型格式,第四页往后的网页是另一种链接URL格式。所以将两种链接URL格式定义为一个数组切片并赋值给urls变量,封装到Get2Urlt函数中,用if语句自动判断,当页码小于4时取第一种URL格式,其他情况则取第二种URL格式,具体语句如下:
func Get2Urlt(idx int) (url string) {
urls :=
[]string{"http://www.****c.**v.cn/cn/st****/data/tocInfo/Selecr********ItemdId/data_itemId=1515,pageIndex=" + strconv.Itoa(idx) + ",pageSize=18.json",
"http://www.****c.**v.cn/dbircweb/tocInfo/Selecr********ItemdId?itemId=1515&pageSize=18&pageIndex=" + strconv.Itoa(idx)}
if idx < 4 {
url = urls[0]
} else {
url = urls[1]
}
return
}
(二)封装函数,获取单个网页信息
选用Go语言程序自带的net/http包中的Get()方法,根据传入的URL链接地址参数便可发起有效请求,获取网页源代码并赋值给变量resp。因为Http.Get()请求是一种网络资源,用完后应第一时间將其关闭,用defer指定的Close()函数来关闭网络请求,语句如下:
func HttpGet(url string) (result []string, err error) {
resp, err1 := http.Get(url)
if err1 != nil {
err = err1
return
}
defer resp.Body.Close()
data1, err2 := ioutil.ReadAll(resp.Body)
b := UserJsonObj{}
json.Unmarshal([]byte(data1), &b)
if err2 != nil {
err = err2
return
}
urlls := make([]string, 0)
for i := 0; i <= 17; i++ {
urllist :=
"http://www.****c.**v.cn/branch/*******I/view/pages/tcommon/Item****t.html?docId=" + strconv.Itoa(int(b.Data.Rows[i].DocId)) + "&itemId=1515"
urlls = append(urlls, urllist)
}
result = urlls
return
}
(三)创建结构体,存储网络Json数据
创建UserJsonObj结构体,用来存储网页的Json数据并赋值给变量b,用json.Unmarshal工具将json字符串解码到相应的结构体中。创建HttpGet()函数获取每页所有罚单的URL链接地址,循环读出每份处罚单的链接URL地址,将所有罚单的链接URL地址赋值给变量urllist,并追加到数组切片urlls中,再将切片urlls赋值给result并返回GetOnePage()函数,语句如下: type UserJsonObj struct {
RptCode float64 `json:"rptCode"`
Msg string `json:"msg"`
Data Data `json:"data"`
}
type Data struct {
Total float64 `json:"total"`
Rows []Brand `json:"rows"`
}
type Brand struct {
DocId float64 `json:"tocId"`
DocSubtitle string `json:"tocSubtitle"`
PublishDate string `json:"publishDate"`
DocSummarystring`json:"tocSummary"`
DocFileUrl string `json:"tocFileUrl"`
Generaltype string `json:"generaltype"`
PdfFileUrl string `json:"pdfFileUrl"`
ItemName string `json:"itemName"`
SolicitFlag string `json:"tolicitFlag"`
DocTitle string `json:"docTitle"`
Datafrom string `json:"datafrom"`
DocUuid string `json:"docUuit"`
Builddate string `json:"builddate"`
}
func GetOnePage(idx int, page chan int) {
url := Get2Urlt(idx)
authors, err := HttpGet(url)
if err != nil {
fmt.Println("HttpGet err:", err)
return
}
mc := make([]string, 0)
dw := make([]string, 0)
xm := make([]string, 0)
yy := make([]string, 0)
tk := make([]string, 0)
fk := make([]string, 0)
rq := make([]string, 0)
for _, jokeURL := range authors {
conUrl := GetUrlt(jokeURL)
contentUrl :=
"http://www.****c.****v.cn/cn/****ic/data/tocInfo/SelecR****t/data_docId=" + conUrl + ".json"
mc1, dw1, xm1, yy1, tk1, fk1, rq1, err := GetTwoPage(contentUrl)
if err != nil {
fmt.Println("Spider2Page err:", err)
continue
}
mc = append(mc, mc1)
dw = append(dw, dw1)
xm = append(xm, xm1)
yy = append(yy, yy1)
tk = append(tk, tk1)
fk = append(fk, fk1)
rq = append(rq, rq1)
}
SpiderWrPage(idx, mc, dw, xm, yy, tk, fk, rq)
page <- idx
}
(四)封裝函数,进一步获取罚单信息
创建GetTwoPage(contentUrl)函数获取第二层中每份罚单的关键信息。传入参数是加工后的contentUrl罚单链接地址,GetTwoPage函数也是使用net/http包中的Get()方法来获取每张罚单的源代码数据,再用Goquery工具的doc.Find()方法对每张罚单文本中的表格数据进行过滤提取,分别提取出罚单中的名称、被处罚单位、被处罚人姓名、被处罚原因、违反条款、处罚信息和处罚日期等关键信息,将提取到的信息分别返回GetOnePage()函数,语句如下:
func GetTwoPage(contentUrl string) (mc1, dw1, xm1, yy1, tk1, fk1, rq1 string, error) {