小擦呀,这省市三级联动的数据不太准确,找份最新的吧

举报
梦想橡皮擦 发表于 2023/01/30 20:43:20 2023/01/30
【摘要】 晨会,我那有钱但是不会技术的老板又发话了:咱这网站上的省市三级联动数据看起来有点旧,你去官方采集一份新的吧。小擦:BOSS,去网上下载一份新的不行吗?BOSS:最准确的是民政部官网的,赶紧去抓,别墨迹!小擦:好的领导(喳)这就是今天这篇博客产生的原因了,作为会一点点 Python 的产品经理,时不时的就要采集一些小量数据,这活就不用找开发大哥了,我自己就干了。目标页如下所示,目标地址为:==...

晨会,我那有钱但是不会技术的老板又发话了:咱这网站上的省市三级联动数据看起来有点旧,你去官方采集一份新的吧。

小擦:BOSS,去网上下载一份新的不行吗?
BOSS:最准确的是民政部官网的,赶紧去抓,别墨迹!
小擦:好的领导(喳)

这就是今天这篇博客产生的原因了,作为会一点点 Python 的产品经理,时不时的就要采集一些小量数据,这活就不用找开发大哥了,我自己就干了。

目标页如下所示,目标地址为:==xzqh.mca.gov.cn/map==

⛳️ 目标站点分析

编写小爬虫最耗时的步骤就是页面分析,本案例也会把大篇幅内容放在这里。

第一步:打开目标站点,得到下图所示筛选框

这就是本案例的关键数据区域,通过开发者工具可以查看到第一个下拉列表的数据如下:

下面就是本案例第一步的代码,获取该下拉列表数据。通过 requests 获取模块之后,分析源码竟然发现 JSON 串,如下所示:

这部分数据获取直接采用正则表达式匹配模块即可。

import requests
from lxml import etree
import re
import json

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ……"
}
def get_level_1():
    res = requests.get('http://xzqh.mca.gov.cn/map',headers=headers)
    content =res.text
    pattern = re.compile('var json = (.*?);')
    result = pattern.search(content)
    ret = result.group(1)
    print(ret)

if __name__ == '__main__':
    get_level_1()

代码运行结果如下所示:

下面将其转换为 JSON 对象,代码如下:

def get_level_1():
    res = requests.get('http://xzqh.mca.gov.cn/map',headers=headers)
    content =res.text
    pattern = re.compile('var json = (.*?);')
    result = pattern.search(content)
    ret = result.group(1)
    # 整理成JSON格式
    json_result = json.loads(ret)

原计划继续找下拉数据的接口,结果在页面中直接发现了其它目标数据,如下图所示:

那省下了调用接口的麻烦,直接获取省市区县隐藏数据即可。

# 提取地级市和区县
pattern1 = re.compile("<input type=\"hidden\" value='(.*?)'")
result1 = pattern1.search(content)
ret1 = result1.group(1)
print(ret1)

运行代码,提取到目标数据。

两部分数据都已经准备好,接下来就是拼接环节,需要将数据进行组合,结果拼接的时候发现第二次获取的数据被平铺展示了,无法直接进行筛选,所以还是要回归到接口调用层次,即使用下述接口组合数据。

调用的接口是:http://xzqh.mca.gov.cn/selectJson
参数:shengji: 河北省(冀)

迭代省份数据,获取二级列表的代码如下所示:


def get_level_1():
    res = requests.get('http://xzqh.mca.gov.cn/map', headers=headers)
    content = res.text
    pattern = re.compile('var json = (.*?);')
    result = pattern.search(content)
    ret = result.group(1)
    json_result = json.loads(ret)
    for sheng in json_result:
    	# 获取省份数据
        s = sheng["shengji"]

        headers["Host"] = "xzqh.mca.gov.cn"
        headers["Origin"] = "http://xzqh.mca.gov.cn/map"
        headers["Referer"] = "http://xzqh.mca.gov.cn/map"
        headers["Accept"] = "application/json, text/javascript, */*; q=0.01"
        headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"
        # 获取区县数据
        inner_res = requests.post('http://xzqh.mca.gov.cn/selectJson', data={"shengji": s}, headers=headers)
        xian = inner_res.json()
        for x in xian:
            diji = x["diji"]
            diji_res = requests.post('http://xzqh.mca.gov.cn/selectJson', data={"shengji": s, "diji": diji},
                                     headers=headers)
            print(diji_res.json())

此时县级数据也已经获取到,如下所示:

最后一步对代码进行一下清理,将核心数据进行提取。

import requests
from lxml import etree
import re
import json

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
}


def get_level_1():
    res = requests.get('http://xzqh.mca.gov.cn/map', headers=headers)
    content = res.text
    pattern = re.compile('var json = (.*?);')
    result = pattern.search(content)
    ret = result.group(1)
    json_result = json.loads(ret)
    for sheng in json_result:
        s = sheng["shengji"]
        s_daima = sheng["quHuaDaiMa"]
        headers["Host"] = "xzqh.mca.gov.cn"
        headers["Origin"] = "http://xzqh.mca.gov.cn/map"
        headers["Referer"] = "http://xzqh.mca.gov.cn/map"
        headers["Accept"] = "application/json, text/javascript, */*; q=0.01"
        headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"
        inner_res = requests.post('http://xzqh.mca.gov.cn/selectJson', data={"shengji": s}, headers=headers)
        diji = inner_res.json()

        for d in diji:
            diji_name = d["diji"]
            dijidaima = d["quHuaDaiMa"]

            xian_res = requests.post('http://xzqh.mca.gov.cn/selectJson', data={"shengji": s, "diji": diji_name},
                                     headers=headers)
            xian = xian_res.json()


            for x in xian:
                xianname = x["xianji"]
                xiandaima = x["quHuaDaiMa"]
                print(s, s_daima, diji_name, dijidaima,xianname,xiandaima)


if __name__ == '__main__':
    get_level_1()

运行代码之后,得到了如下数据。

北京市(京) 110000 北京市 110000 东城区 110101
北京市(京) 110000 北京市 110000 西城区 110102
北京市(京) 110000 北京市 110000 朝阳区 110105
北京市(京) 110000 北京市 110000 丰台区 110106
北京市(京) 110000 北京市 110000 石景山区 110107

妥妥的新版省市县三级数据,然后存储到 csv 文件中,完成领导交代的任务。

📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 738 篇原创博客

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。