Python实践 - 网络爬虫笔记 - 1、对 URL 的 get 请求

Python实践笔记 - 1、高德地图的坐标转换与周边搜索

张板书的Python的实践笔记,包括笔记与DeBug的经历。

为了完成一个比较麻烦的实习任务,尝试着做了这样一个爬虫项目。
实践内容为对一个储存了地点的 csv 表格进行处理,并在地图上标好,同时检查这些地点周围是否存在某类型的企业,如果有需要进行标注。

思考得到,需要将这些地点标注在地图上,就需要得到其经纬度,并要基于高德、百度、腾讯等进行此地点的周边搜索,并将符合要求的信息放在csv中。


一、高德地图的开发平台

https://lbs.amap.com/ # 高德开放平台

申请key

高德Web服务API向开发者提供HTTP接口,开发者可通过这些接口使用各类型的地理数据服务,返回结果支持JSON和XML格式。

Web服务API对所有用户开放。使用服务之前,需要在高德开放平台上创建应用,并根据需求申请对应的服务key。不同类型用户可获取不同的数据访问能力。

在这里插入图片描述

例如对本次的需求,我们需要进行坐标转换与周边搜索,所以需要 Web服务。

在这里插入图片描述

阅读开发文档

然后需要阅读开发文档

https://lbs.amap.com/api/webservice/summary/

坐标转换

文档中说:

坐标转换是一类简单的HTTP接口,能够将用户输入的非高德坐标(GPS坐标、mapbar坐标、baidu坐标)转换成高德坐标。

而在这里我们要将一个产业园名称转换为经纬度信息。

第一步,申请”Web服务API”密钥(Key);

第二步,拼接HTTP请求URL,第一步申请的Key需作为必填参数一同发送;

第三步,接收HTTP请求返回的数据(JSON或XML格式),解析数据。

		如无特殊声明,接口的输入参数和输出数据编码全部统一为UTF-8。

文档中给出接口url、请求方式和请求参数:
在这里插入图片描述

1、请求url:

即需要程序向 https://restapi.amap.com/v3/geocode/geo 发送 get 请求,且同时发送参数parameters;

"https://restapi.amap.com/v3/geocode/geo"

2、parameters

在这里是一个字典,字典的具体内容在下面的表格3中;

3、请求参数


params = { 'key': '这里填写之前申请的 web服务 的key',                 
       'address': city   }
                

对于向 url 发送请求后,服务器会把标准化的返回信息以某种格式发送给你,具体标准在开发文档中也有说明:

在这里插入图片描述

周边搜索

和坐标转换一样,不同的只是 url 和请求参数。
在这里插入图片描述


    params = {'key': '你申请的 web服务 的key',
        'location': location, # 用于表示待标注点的坐标,格式为(经纬,纬度)
        'keywords': keywords, # 表示搜索的关键词,多个关键词用 | 分割
        'offset': '20', # 每页记录的数据,不要超过25
        'page':page, # 当前页数,最大翻页100
        'types':'170000',
        # 'output': "JSON", # 返回数据格式类型
        'radius': distance, # 表示搜索的范围半径,单位:米。取值范围(1,50000),默认为3000。
        # "sortrule":"distance" # 返回结果的排序方式;按距离排序:distance;综合排序:weight
        }
                

二、用 Python 来进行抓取

坐标转换

import requests
import json
def get_JWD(city):
	url = 'https://restapi.amap.com/v3/geocode/geo'   
	# 将两个参数放入字典中作为请求参数
	parameters = { 'key': '这里填写之前申请的 web服务 的key',                 
	        'address': city   }                    
	res = requests.get(url, params)
	response =  json.loads(res.text)	# 使用json来解析返回信息
	try:
	    return response['geocodes'][0]['location'] # 解析方式在下面
	except:
	    print ("Erro  地址: {}  查询错误,错误代码: {}".format(city,jd['info']))
	    return "Error"
            

返回信息可以使用开发文档中的插件先进行尝试:
在这里插入图片描述

尝试一下之后可以看返回信息大概是个什么样子,然后再使用相关工具来进行解析

在这里插入图片描述

我们需要得到经纬度,故需要解析的内容是

response['geocodes'][0]['location'] 

运行结果如下:


get_JWD("北京大学")
>>>116.308264,39.995304

get_JWD("这啥都不是")
>>>Erro  地址: 这啥都不是  查询错误,错误代码: OK

附近搜索

同理,做附近搜索的项目


import requests
import json
def zhoubian_search(location,keywords,distance,page): # 输入地址查询周边,参数:中心经纬度,关键词,搜索半径,第几页
    requests.adapters.DEFAULT_RETRIES = 5
    s = requests.session()
    s.keep_alive = False
    url = "https://restapi.amap.com/v3/place/around"
    params = {'key': 'f18d291d2fd31af29c6d2c3378c6d310',
        'location': location, # 用于表示待标注点的坐标,格式为(经纬,纬度)
        'keywords': keywords, # 表示搜索的关键词,多个关键词用 | 分割
        'offset': '10', # 每页记录的数据,不要超过25
        'page':page, # 当前页数,最大翻页100
        # 'types':'170000',# 如果是 170000,则只搜索所有类型为“企业”的地点
        # 'output': "JSON", # 返回数据格式类型
        'radius': distance, # 表示搜索的范围半径,单位:米。取值范围(1,50000),默认为3000。
        # "sortrule":"distance" # 返回结果的排序方式;按距离排序:distance;综合排序:weight
        }
    res = requests.get(url, params)
    jd =  json.loads(res.text)
    ifo = ""
    try:
        for poi in jd['pois']:
            print("企业: {}\t 距离:{}".format(poi["name"],poi["distance"]))
            if check(poi["name"]):	# 简单的数据清洗
                ifo += "企业:{} 距离:{} m \t".format(poi["name"],poi["distance"])
        return ifo
    except:
        return "Error"
            


zhoubian_search("116.308264,39.995304","理发店",5000,1)

>>>企业: 越秀专业美发      距离:686
>>>企业: 北京大学燕园美发  距离:762
>>>企业: 锡华酒店美容美发  距离:815
>>>企业: 啊木造型  距离:828
>>>企业: 好心情美发        距离:885
>>>企业: 越秀造型  距离:958
>>>企业: 胡同理发店        距离:1015
>>>企业: 雨琪造型  距离:1049
>>>企业: 思丝清心美容美发  距离:1050
>>>企业: 思阳光理发店      距离:1062
简单的数据清洗

下面对返回的数据进行一些简单的数据清洗,比如我们不想要名称中含有 “理发店” 与 “美容美发” 的,就需要写一个简易的清洗函数,清洗掉所有含:

def check(name):
    white_list = ["理发店","美发","美容"]
    CK = 0
    for word in white_list:
        try:
            name2 = name.replace(word,"") # 原名称去掉白名单中的关键词
            if name != name2: # 去掉之后不一样,则说明有白名单中的词
                CK += 1
                # return False # 返回不能用
        except:
            CK = CK
    if CK > 0: # 有白名单中的词
        return False
    else:
        return True
        

zhoubian_search("116.308264,39.995304","理发店",5000,1)

>>>企业: 啊木造型  距离:828
>>>企业: 越秀造型  距离:958
>>>企业: 雨琪造型  距离:1049
>>>企业: 木北护肤造型(水磨社区店)  距离:1080
>>>企业: 标心立艺  距离:1085
>>>企业: 鑫沐造型(苏州街店)        距离:1311
>>>企业: 时光发廊  距离:1353
>>>企业: 元琦造型  距离:1398

三、加上 csv 的处理


def get_JWD_file(keywords): # 根据查询关键字列表生成表格
    error_count = 0
    distance = 3000
    page = 1
    adress = "单位"
    file1 = r"开发区2-0.csv"	# 存了各单位名称的文件地址
    file2 = r"ing.csv"	# 需要有一个新的文件,这个文件最好用excel另存为“CSV UTF-8(逗号分隔)”格式,否则保存出来可能解码不出中文来
    # open(file2, "w",encoding = "utf-8")
    with open(file1, "r", encoding = "utf-8") as f, open(file2, "r", encoding = "utf-8") as f2 :
        reader = csv.DictReader(f)
        writer = csv.DictReader(f2)
        reader_l = [row for row in reader]
        writer_l = [row for row in writer]
        for i in range(len(reader_l)):
            line = {}
            line[adress] = reader_l[i][adress]
            for keyword in keywords:	# 不止一个关键词
                ifo = zhoubian_search(get_JWD(reader_l[i][adress]),keyword,distance,page)
                if ifo == "Error":		# 如果找不到
                    error_count += 1
                    print("# # # # # # # --- NO:{}  地址:{} 实在是找不到 --- # # # # # # #".format(error_count,reader_l[i][adress]))
                line["检索关键词:{}".format(keyword)] = ifo
                if i % 10 == 0:
                    print("————— 关键词:{} 查询已完成 {} / {} ; 查询错误 {}—————".format(keyword,i,len(reader_l),error_count))
            writer_l.append(line)
        print("————— 查询已完成 {} / {} ; 查询错误共 {} 个 —————".format(i,len(reader_l),error_count))
        file2 = "ing.csv"
        header = writer_l[0].keys()
        datas = writer_l
        with open(file2, 'a', newline='',encoding='utf-8') as f: 
            writer = csv.DictWriter(f,fieldnames=header) # 提前预览列名,当下面代码写入数据时,会将其一一对应。
            writer.writeheader()  # 写入列名
            writer.writerows(datas) # 写入数据
            
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值