30、BeautifulSoup实例2:统计区域数据抓取

Life is short, you need Python!

上集回顾:

  1. 分析需求:每2分钟检查一次更新情况,直至更新或请假为止。
  2. 代码实现

上集分析并实现了如何轮询查看网文是否更新,用Python代码代替自己反复的手动刷新。
本集研究如何抓取统计区划数据。

一、需求分析
首先查看统计区划数据首页:

统计区划数据首页

能够看到全国31个省(自治区、直辖市)。

然后再点击一个省份,查看省份详情页面:


省份

可以看到统计用区划代码和市级列表。

再点击一个市名称,查看市详情:


市辖区

可以看到市辖区列表。

有时候我们会需要行政区划的JSON文件,虽然TJJ在官方网站进行公布,但是如果一个一个复制粘贴,那将是海量的工程。所幸Python是处理这些繁琐事情的好帮手。只要遍历了省市区三级区划并保存到本地文件,就算完工了。

二、流程图

流程图

获取省级列表并遍历,嵌套获取市级列表并遍历,获取市辖区列表并保存,遍历结束即可。

三、代码实现

from bs4 import BeautifulSoup
import requests
import datetime
import time
import random
import re

URL = 'http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2021/'

def get_header() :
    return {
      "Content-Type": "text/html",
      'Cookie': 'SF_cookie_1=37059734',
      'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"
    }

def get_soup(url) :
    print('----------url: ' + url)
    headers = get_header()
    res = requests.get(url, headers=headers, timeout=15)
    return BeautifulSoup(res.content, "html.parser")

def write_start(tag, file) :
    href = tag.get('href')
    code = href[:-5]
    if '/' in code :
        print('write city: ', tag.text)
        code = code[3:] + '00'
    else :
        print('write province: ', tag.text)
        code = code + '0000'
    file.write('{"code":"' + code + '", "name":"' + tag.text + '", "children": [\n')
    return href

def write_end(file, is_end) :
    if is_end :
        file.write(']}\n')
    else :
        file.write(']},\n')
    time.sleep(2 + random.random())

def get_area(href, file) :
    soup = get_soup(URL + href)
    areas = soup.find_all("a", href=re.compile("html"), text=re.compile("[^0-9]"))
    length = len(areas)
    for i in range(length):
        tag = areas[i]
        code = tag.get('href')[3:-5]
        if len(code) > 6 : return # 区级以下区域
        print('write: ', tag.text)
        file.write('{"code":"' + code + '", "name":"' + tag.text + '"}')
        if i != length -1 : file.write(',')
        file.write('\n')

def get_city(href, file) :
    soup = get_soup(URL + href)
    citys = soup.find_all("a", href=re.compile("html"), text=re.compile("[^0-9]"))
    length = len(citys)
    for i in range(length):
        href = write_start(citys[i], file)
        get_area(href, file)
        write_end(file, i == length -1)

def get_province(file) :
    soup = get_soup(URL + 'index.html')
    provinces = soup.find_all("a", href=re.compile("html"))
    length = len(provinces)
    for i in range(length): 
        href = write_start(provinces[i], file)
        get_city(href, file)
        write_end(file, i == length -1)

if __name__ == '__main__' :
    time_formatter = '%Y%m%d'
    time_str = datetime.datetime.now().strftime(time_formatter)
    filename = 'area_stats_' + time_str + '.json'
    with open(filename, 'w') as file:
        file.write('[\n')
        get_province(file)
        file.write(']')

本集总结:

  1. 需求分析
  2. 流程图
  3. 代码实现

下集见

你可能感兴趣的:(30、BeautifulSoup实例2:统计区域数据抓取)