30、BeautifulSoup实例2:统计区域数据抓取
2022-04-14 本文已影响0人
魔方宫殿

上集回顾:
- 分析需求:每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(']')
本集总结:
- 需求分析
- 流程图
- 代码实现
下集见