python学习第九节:爬虫实战-抓取地址库

python学习第九节:爬虫实战-抓取地址库

在这里插入图片描述
话不多说,直接上代码;下面的代码是从统计局抓取地址库并保存为json格式和excel格式。大家拿到代码直接运行即可。

#coding=utf-8
#加入上面这行代码表示可以在下面代码中包含中文
import bs4  #网页解析,获取数据
import time #引入time模块
import re  #正则表达式,进行文字匹配
import urllib.request,urllib.error #制定URL,获取网页数据
import xlwt # 进行excel操作
import sqlite3 # 进行SQLite数据库操作import
#urllib.parse模块是一个用于解析URL的工具包,支持各种对URL的操作,包括拆分、拼接、编码、解码等。
import urllib.parse
# 解析网页
from bs4 import BeautifulSoup
#定义全局变量
durl="https://www.stats.gov.cn/sj/tjbz/tjyqhdmhcxhfdm/2023/"
file_path="E://地址库"+str(time.time())+".json"
excel_path="E://地址库"+str(time.time())+".xls"

# 爬取网页
def getHtml():
    # 定义全局变量
    response = None
    html = ""
    try:
        # 请求网页
        response = urllib.request.urlopen(durl+"index.html")
        # 获取网页响应内容
        html = response.read().decode("utf-8")
    except urllib.error.URLError as e:
        if hasattr(e, "code"):  # 打印错误状态码
            print(e.code)
        if hasattr(e, "reason"):  # 打印错误问题原因
            print(e.reason)
    # 如果返回状态不是200,说明访问失败
    if response.status != 200:
        print("---访问失败!")
    # 打印读取到的网页内容
    print(html)
    return html

# 解析网页
def paseHtml(html):
    print("*" * 20, "开始解析网页", "*" * 20)
    bs = BeautifulSoup(html, "html.parser")
    # 获取页面中所有tb下的a标签 得到所有省级的a标签
    provinces = bs.select("td > a")
    data = []
    # 循环省级标签
    for provinceTag in provinces:
        name = provinceTag.text
        url = provinceTag.attrs["href"]
        code = re.sub(".html", "", url) + "0000000000"
        print("省级名称:", name, "   url=", url, "   code=", code)
        child = getChild(durl,url)
        d = {
            "code": code,
            "name": name,
            "child": child
        }
        data.append(d)
    return data

#获取子级地址
def getChild(purl,url):
    child = []
    html = ""
    qurl=purl + "" + url
    print("开始获取", qurl, "的信息")
    try:
        # 请求网页
        response = urllib.request.urlopen(qurl)
        # 获取网页响应内容
        html = response.read().decode("utf-8")
    except urllib.error.URLError as e:
        return child
    # 如果返回状态不是200,说明访问失败
    if response.status != 200:
        print("---访问"+url+"失败!")
        return child
    bs = BeautifulSoup(html, "html.parser")
    # 获取页面中所有class=citytr的
    childtrs = bs.select(".citytr,.countytr,.towntr,.villagetr")
    #print("=====",childtrs)
    # 循环标签
    for childtr in childtrs:
        #print("childtr=", childtr)
        url=""
        code=""
        name=""
        #兼容 没得a标签情况 childtr= <tr class="countytr"><td>130101000000</td><td>市辖区</td></tr>
        if len(childtr.find_all("td")[0].find_all("a"))==0:
            if len(childtr.select(".villagetr"))==0: # 说明这不是最后一层
                code = childtr.find_all("td")[0].text
                name = childtr.find_all("td")[1].text
            else:
                code = childtr.find_all("td")[0].text
                name = childtr.find_all("td")[2].text
        else:
            if "href" in childtr.find_all("td")[0].a.attrs:
                url = childtr.find_all("td")[0].a.attrs["href"]
            code = childtr.find_all("td")[0].a.text
            name = childtr.find_all("td")[1].a.text
        #print("name=", name, "  code=", code, "   url=", url)
        child2=[]
        if url!="":
            qurl = qurl[0:qurl.rindex("/")+1]
            child2 = getChild(qurl,url)
        d = {
            "code": code,
            "name": name,
            "child": child2
        }
        child.append(d)
    return child


# 将将数据写入文件
def save_file(data):
    print("*"*20,"开始写入文件","*"*20)
    # 打开文件
    fo = open(file_path,"w",encoding="utf-8") # w表示打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件
    # 写入内容
    fo.write(str(data))
    # 关闭文件
    fo.close()
    print("*" * 20, "写入文件完成", "*" * 20)


# 将将数据写入excel
def save_excel(data):
    print("*" * 20, "开始写入excel", "*" * 20)
    book = xlwt.Workbook(encoding="utf-8", style_compression=0)  # 创建workbook对象 新建一个工作簿对象
    sheet = book.add_sheet("2024地址库", cell_overwrite_ok=True)  # 创建工作表 cell_overwrite_ok=True 重新写入会自动覆盖之前的内容不会报错
    # 创建表格表头
    col = ("地区代码", "地区名称", "等级", "父级代码")
    for i in range(len(col)):
        sheet.write(0, i, col[i])
    # 插入数据
    i=0
    # 解析省级
    for p in data:
        pcode=p["code"]
        pname=p["name"]
        plevel=1
        pf_code="0"
        pchild=p["child"]
        sheet.write(i + 1, 0, pcode)
        sheet.write(i + 1, 1, pname)
        sheet.write(i + 1, 2, plevel)
        sheet.write(i + 1, 3, pf_code)
        i+=1
        if len(pchild)==0:
            continue
        #解析市级
        for c in pchild:
            ccode = c["code"]
            cname = c["name"]
            clevel = 2
            cf_code = pcode
            cchild = c["child"]
            sheet.write(i + 1, 0, ccode)
            sheet.write(i + 1, 1, cname)
            sheet.write(i + 1, 2, clevel)
            sheet.write(i + 1, 3, cf_code)
            i += 1
            if len(cchild) == 0:
                continue
            # 解析区级
            for d in cchild:
                dcode = d["code"]
                dname = d["name"]
                dlevel = 3
                df_code = ccode
                dchild = d["child"]
                sheet.write(i + 1, 0, dcode)
                sheet.write(i + 1, 1, dname)
                sheet.write(i + 1, 2, dlevel)
                sheet.write(i + 1, 3, df_code)
                i += 1
                if len(cchild) == 0:
                    continue
                # 解析镇级
                for a in dchild:
                    acode = a["code"]
                    aname = a["name"]
                    alevel = 4
                    af_code = dcode
                    sheet.write(i + 1, 0, acode)
                    sheet.write(i + 1, 1, aname)
                    sheet.write(i + 1, 2, alevel)
                    sheet.write(i + 1, 3, af_code)
                    i += 1
    book.save(excel_path)
    print("*" * 20, "写入excel完成", "*" * 20)


def run():
    html = getHtml()# 爬取网页
    data=paseHtml(html) # 解析网页
    save_file(data) #将数据存入文件
    save_excel(data) # 将数据写入excel


if __name__ == '__main__':
    run()
    print("爬虫结束")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值