一个小程序,可以爬中国社会组织公共服务平台的基金会年报中所有公益慈善项目的明细,但是只能获取2017和2018年的数据,2016年以前的报表格式不太一样,需要调整代码。

import requests,re 
from bs4 import BeautifulSoup

class Project_Crawler(object):
    """
    用实例名.one_work()来工作
    用实例名.li获取列表
    """

    url = 'http://www.chinanpo.gov.cn/viewbgs.html'
    headers = {
        'Host''www.chinanpo.gov.cn',
        'Origin''http://www.chinanpo.gov.cn',
        'Proxy-Connection''keep-alive',
        'User-Agent''Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36'
    }
    def __init__(self, project_id):
        self.project_id = project_id
        self.li = []

    #执行一次requests,获取页面数据(报表)    
    def get_response(self):
        params = {
            'id': self.project_id,
            'dictionid''102',
            'websitId''1000001',
            'netTypeId''2',
            'topid'''
        }
        self.response = requests.post(self.url, headers = self.headers, params = params)

    #获取项目总数和本年项目总支出
    def get_total_info(self):
        numpattern = re.compile('共开展了( (.*?) )项')
        self.number = re.findall(numpattern, self.response.text)[0]
        costpattern = re.compile('项目总支出为( (.*?) )元')
        self.totalcost = re.findall(costpattern, self.response.text)[0]

    #获取包含所有项目明细的报表
    def get_projects(self):
        pattern = re.compile('备案情况</h3></div></TD></TR>(.*?)<TBODY><TBODY><TR><TD align=\'left\'><h4>')
        content = re.findall(pattern, self.response.text)
        soup = BeautifulSoup(content[0], 'lxml')
        self.projects = soup.find_all('tbody')

    #从上一步获取的报表中分离所有项目
    #这一步之所以有重复的两步(one,two)
    #是因为每一小段报表包含两个项目
    def get_one_piece(self, two):
        one = two[0:13]

        objs = one[8].find_all('img', src="../images/icon_box-checked.png")
        obj = [x.next_sibling for x in objs]

        region = one[10].find_all('img', src="../images/icon_box-checked.png")
        reg = [x.next_sibling for x in region]

        piece = {
            '报告书id': self.project_id,
            '项目总数': self.number,
            '项目总支出': self.totalcost,
            '项目编号': one[0].string,
            '项目名称': re.findall('项目名称:(.*)', one[1].string)[0],
            '是否公募': one[2].find('img', src="../images/icon_circle-slelected.png").next_sibling,
            '公募时间': re.findall('开展公开募捐的起始时间:(.*)', one[3].string)[0],
            '专项审计': one[4].find('img', src="../images/icon_circle-slelected.png").next_sibling,
            '本年收入': re.findall('项目本年度收入:人民币(.*)元', one[5].string)[0],
            '本年支出': re.findall('项目本年度支出:人民币(.*)元', one[6].string)[0],
            '运作模式': one[7].find('img', src="../images/icon_circle-slelected.png").next_sibling,
            '服务对象': obj,
            '服务领域': one[9].find('img', src="../images/icon_circle-slelected.png").next_sibling,
            '服务地区': reg,
            '项目介绍': one[12].string
        }
        self.li.append(piece)
        one = two[13:]

        objs = one[8].find_all('img', src="../images/icon_box-checked.png")
        obj = [x.next_sibling for x in objs]

        region = one[10].find_all('img', src="../images/icon_box-checked.png")
        reg = [x.next_sibling for x in region]

        piece = {
            '报告书id': self.project_id,
            '项目总数': self.number,
            '项目总支出': self.totalcost,
            '项目编号': one[0].string,
            '项目名称': re.findall('项目名称:(.*)', one[1].string)[0],
            '是否公募': one[2].find('img', src="../images/icon_circle-slelected.png").next_sibling,
            '公募时间': re.findall('开展公开募捐的起始时间:(.*)', one[3].string)[0],
            '专项审计': one[4].find('img', src="../images/icon_circle-slelected.png").next_sibling,
            '本年收入': re.findall('项目本年度收入:人民币(.*)元', one[5].string)[0],
            '本年支出': re.findall('项目本年度支出:人民币(.*)元', one[6].string)[0],
            '运作模式': one[7].find('img', src="../images/icon_circle-slelected.png").next_sibling,
            '服务对象': obj,
            '服务领域': one[9].find('img', src="../images/icon_circle-slelected.png").next_sibling,
            '服务地区': reg,
            '项目介绍': one[12].string
        }
        self.li.append(piece)

    #处理所有项目    
    def get_list(self):
        for i in range(len(self.projects)):
            two = self.projects[i].find_all('td')
            self.get_one_piece(two)

    def one_work(self):
        self.get_response()
        self.get_total_info()
        self.get_projects()
        self.get_list()

#一个例子
c33718 = Project_Crawler(33718)
c33718.one_work()
print(c33718.li)

现在有一个问题是,我这个程序只能处理一家NPO,不能处理所有的年报,当我闲下来想搞一个循环,自动挂机处理时,我发现官网登不上去了,显示“正在维护(欢度新春)”,政府工作人员真是轻松呀,不像渣浪,过年还得维护热搜。

来年继续吧。