网络爬虫又称“网络蜘蛛”或“网络机器人”,它是一种按照一定规则从互联网中获取网页内容的程序。广为人知的百度、谷歌等搜索引擎就是最常见的爬虫程序。近年来,利用Python等爬虫技术采集互联网信息已在各领域得到广泛应用。2022年,高台县审计局在开展县级预算执行和其他财政收支情况审计项目中首次使用了Python爬虫技术。
一、应用背景
《中华人民共和国预算法》第十四条第二款规定,“经本级政府财政部门批复的部门预算、决算及报表,应当在批复后二十日内由各部门向社会公开,并对部门预算、决算中机关运行经费的安排、使用情况等重要事项作出说明。”2021年12月,国务院办公厅印发《关于新形势下进一步加强督查激励的通知》(国办发〔2021〕49号),提出“对……预决算公开等财政工作绩效突出的省(自治区、直辖市),中央财政通过年度预算安排资金予以奖励,由省级财政统筹使用”的激励导向。2022年4月,甘肃省财政厅统一部署开展预算公开情况自查工作,要求全面梳理摸排部门预算公开情况,确保各单位数据及时向社会公开。该项工作也引起了该县审计局高度重视,将预算公开情况作为当年预算执行审计的重点审计事项。
二、爬虫开发
该县共有58个一级预算单位和9个镇政府,在县政府门户网站集中进行预算公开,每个部门(镇)单独一个网页。如果采取人工采集方式,则费时费力。因此,审计人员决定编写Python爬虫采集预算公开信息。
代码中使用了urllib、Beautiful Soup、re等库,在程序开始前需要先引入这些库:
from bs4 import BeautifulSoup
import urllib.request
import xlwt
import re
import os
具体步骤如下:
(一)获取目录页URL
该县政府门户网站专门设置了“三公经费及预决算”公开栏目,从栏目网页层级结构看,预算公开网页可分为两级,一级网页为若干目录页,二级网页为各部门预算的详情页。通过目录页中的链接可打开详情页。
对目录页URL进行分析:
第1页:http://.../sgjfjyjs/
第2页:http://.../sgjfjyjs/index_1.html
第3页:http://.../sgjfjyjs/index_2.html
可以看出,除第1页外,其他页面URL都只是最后的序号不同。采集相关信息,首先要获取目录页URL。关键代码如下:
base_url = r"http://www.../sgjfjyjs"
for p in range(count_page): #count_page为目录页总页数
if p == 0:
url = base_url
else:
url = base_url + "/index_" + str(p) + ".html"
(二)爬取指定网页源代码
爬取过程中,既要爬取目录页,也要爬取详情页,为优化代码结构,需要写一个函数,用来爬取指定网页的HTML源代码,为下一步提取相关信息做好准备。代码中的headers参数是为了模拟浏览器访问服务器,以防止服务器识别出是爬虫程序而拒绝访问。
def ask_url(url):
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"}
req = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(req)
html = response.read().decode("utf-8")
response.close()
return html
(三)解析提取目录页信息
在目录页中,审计人员的目的是提取详情页的标题和URL。经对网页源代码分析,可从<li>目录列表中的<a>标签进行提取。其中部门预算公开的标题格式均为“×××(单位)202×年部门预算公开说明”,因此可通过设置年度、“预算”等关键词进行判断,只提取特定年度的预算公开详情页。关键代码如下:
datalist = [] #详情页有关信息列表
soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all("li", class_="clearfix"):
data = []
title_all = re.findall(find_title, str(item))[0]
data.append(title_all[1]) #详情页标题
link = base_url + title_all[0]
data.append(link) #详情页链接
datalist.append(data)
(四)解析提取详情页信息
从详情页布局分析,页面大致分为上、中、下三部分:上方以表格形式显示,包括标题、索引号、关键词、发布机构、生成日期等信息;中间为文字内容(部门预算公开说明);下方为可下载的附件(预算报表)。其中:审计需要的标题、发布机构、生成日期等信息可从页面表格中进行提取;附件可通过<a>标签href属性判断是否有链接,如果无链接,则说明未公开附件。
在分析网页源代码时发现,该网站采用静态化网页生成技术,因技术性原因,各网页的源代码布局结构不一致,关键信息的标签位置不固定,利用XPath、Beautiful Soup进行解析均难以准确定位,会导致部分网页信息提取不准确。审计人员遂决定利用功能强大的正则表达式提取信息。
# 定义正则表达式
find_file_link = re.compile(r'<a.*?href="\.(/.*?)".*?>(.*?)</a>') #文件下载链接
find_unit = re.compile(r'<span>发布机构</span></div>.*?<div><span>(.*?)</span>', re.S) #单位名称
find_public_time = re.compile(r'<span>生成日期</span></div>.*?<div><span>(.*?)</span>', re.S) #公开时间
关键代码如下:
# 解析详情页
data_all = [] #准备保存到Excel表中的相关信息
def getdata_2(data): #data为包含详情页标题、链接的列表
html = ask_url(data[1])
unit = re.findall(find_unit, html)[0].strip()
public_time = re.findall(find_public_time, html)[0].strip()
items = re.findall(find_file_link, html)
if items:
data_all.append([unit, data[0], public_time, "发现附件链接", data[1]])
# 提取附件url,以备下载之用,代码略
else:
data_all.append([unit, data[0], public_time, "未发现附件链接", data[1]])
(五)保存结果
成功提取各详情页有关信息到data_all列表后,最后一步就是数据保存。为了方便后续查阅分析,可引用xlwt库保存为Excel文件,命名为“预算公开提取信息表”。
三、分析成果
运行爬虫程序后,爬取结果自动生成Excel表格,共用时7.37秒,极大地提高了工作效率。审计人员重点分析了以下审计事项:
1.筛查未公开的预算单位。将“预算公开提取信息表”中的单位名称与财政部门提供的“预算单位基本信息表”进行比对,分析“预算单位基本信息表”存在而“预算公开提取信息表”不存在的预算单位。经分析,无未公开的预算单位。
2.筛查公开时间逾期的预算单位。将“预算公开提取信息表”按公开时间进行排序(或者编写函数公式),查看财政部门批复20日之后有无记录。经分析,无公开时间逾期的预算单位。
3.筛查只公开预算说明未公开预算报表的预算单位。爬虫程序已在Excel表格的“下载情况”列中进行了标注,利用Excel进行筛选,发现有7个预算单位只公开了预算说明而未公开预算报表。
作者姓名:蔺耀雷
工作单位:甘肃省张掖市高台县审计局
留言与评论(共有 0 条评论) “” |