小程序项目思路分享爬虫

小程序项目思路分享爬虫

具体需求:
 有这几个就行,门店名称+门店地址+门店类型,再加上省、市、县/区

在这里插入图片描述

门店名称:storeName

门店地址:storeAddress

程序运行:

honor_spider获取经纬度信息。

经纬度——>详细店铺接口

这是荣耀店铺接口数据,请求参数带有省/市的经纬度信息。返回响应数据是省、市下的行政区划荣耀店铺信息

https://retail.hihonor.com/isrp/sms/online/store-info/getTargetStore/hi-honor
curl
curl -H 'Host: retail.hihonor.com' -H 'appsource: wxapp' -H 'x-from: wxapp' -H 'charset: utf-8' -H 'x-appname: wxapp' -H 'user-agent: Mozilla/5.0 (Linux; Android 13; Mi 10 Build/TKQ1.221114.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 XWEB/1160117 MMWEBSDK/20240301 MMWEBID/291 MicroMessenger/8.0.48.2580(0x2800303D) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android' -H 'x-user-token: ' -H 'content-type: application/json' -H 'x-access-token: ' -H 'referer: https://servicewechat.com/wxde6bc80b07638016/409/page-frame.html' --data-binary '{"coordinateType":"2","longitude":116.31188232421874,"latitude":40.03590304904514,"isGetTargetStore":true,"operatingStatus":1,"isCheckSpu":true,"range":50000,"enableWechatApplet":1}' --compressed 'https://retail.hihonor.com/isrp/sms/online/store-info/getTargetStore/hi-honor'
接口特点:

接口只返回省市下的店铺信息,而不返回区级及以下的店铺信息。所以要提取行政区划信息,要对店铺地址写正则表达式提取。

代码:
import requests
import jsonheaders = {"Host": "retail.hihonor.com","appsource": "wxapp","x-from": "wxapp","charset": "utf-8","x-appname": "wxapp","user-agent": "Mozilla/5.0 (Linux; Android 13; Mi 10 Build/TKQ1.221114.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 XWEB/1160117 MMWEBSDK/20240301 MMWEBID/291 MicroMessenger/8.0.48.2580(0x2800303D) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android",}
url = "https://retail.hihonor.com/isrp/sms/online/store-info/getTargetStore/hi-honor"
data = {"coordinateType": "2","longitude": 114.571090,"latitude": 38.146190,
}
data = json.dumps(data, separators=(',', ':'))
response = requests.post(url, headers=headers, data=data)# 解析响应数据
response_data = response.json()  # 使用.json()方法直接解析JSON响应数据# 提取storeName和storeAddress字段
if response_data['status'] == 'success' and 'result' in response_data:for store in response_data['result']:store_name = store.get('storeName')  # 使用get方法避免KeyErrorstore_address = store.get('storeAddress')  # 使用get方法避免KeyErrorprint('店铺名称:', store_name)print('店铺地址:', store_address)
else:print('请求失败或响应数据格式不正确')
结果

在这里插入图片描述

创建scrapy:scrapy startproject miniprogram

创建爬虫:scrapy genspider honor

省市——>经纬度接口
url = 'https://apis.map.qq.com/jsapi?qt=geoc&addr={}&output=jsonp&pf=jsapi&ref=jsapi&cb=qq.maps._svcb3.geocoder0'.format(name)

请求参数是省市名称,返回的数据是经纬度信息,这里我调用的是开源的腾讯地图api接口。

爬取直辖市province_data = {'北京市': 'CN-11', '天津市': 'CN-12', '河北省': 'CN-13', '山西省': 'CN-14','内蒙古自治区': 'CN-15', '辽宁省': 'CN-21', '吉林省': 'CN-22', '黑龙江省': 'CN-23','上海市': 'CN-31', '江苏省': 'CN-32', '浙江省': 'CN-33', '安徽省': 'CN-34', '福建省': 'CN-35','江西省': 'CN-36', '山东省': 'CN-37', '河南省': 'CN-41', '湖北省': 'CN-42', '湖南省': 'CN-43','广东省': 'CN-44', '广西壮族自治区': 'CN-45', '海南省': 'CN-46', '重庆市': 'CN-50','四川省': 'CN-51', '贵州省': 'CN-52', '云南省': 'CN-53', '西藏自治区': 'CN-54','陕西省': 'CN-61', '甘肃省': 'CN-62', '青海省': 'CN-63', '宁夏回族自治区': 'CN-64','新疆维吾尔自治区': 'CN-65'}
请求测试逻辑
# import requests
# import json
# import re
#
# # 假设您已经定义了get_proxies方法,如果没有,您可以将proxies参数从下面的请求中移除
# def get_proxies():
#     # 返回代理服务器的配置,例如:
#     
#     # 如果您不使用代理,可以返回None或者直接在请求中移除proxies参数
#     return None
#
# # 坐标
# def zb(name):  # name是区名
#     print('爬取坐标')
#     url = 'https://apis.map.qq.com/jsapi?qt=geoc&addr={}&output=jsonp&pf=jsapi&ref=jsapi&cb=qq.maps._svcb3.geocoder0'.format(name)
#     headers = {
#         "user-agent": '
#     }
#     try:
#         response = requests.get(url=url, headers=headers, proxies=get_proxies(), timeout=7)
#         html = response.text
#         if html[-1] != ';':
#             html = html + ';'
#
#         html = html.replace('\n', '').replace('\t', '').replace('\r', '')
#         html = re.findall('\({(.*?)\);', html)[0]
#         html = json.loads('{' + html)
#         return html
#     except Exception as e:
#         print('获取坐标错误', name, '重试!')
#         print(e)
#         return zb(name)
#
# # 测试代码
# if __name__ == "__main__":
#     test_name = "北京市"  # 测试用的区名,可以更换为其他区名。用provinceName
#     result = zb(test_name)
#     print(json.dumps(result, indent=4, ensure_ascii=False))  import requests
import json
import re
from connRedis import OPRedis# 假设您已经定义了get_proxies方法,如果没有,您可以将proxies参数从下面的请求中移除
# def get_proxies():
#如需调用,自行配置,这里我删除了。
#        proxies = {"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": tid, "pwd": password, "proxy": proxy_ip},"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": tid, "pwd": password, "proxy": proxy_ip}}return proxies# 坐标
def zb(name):  # name是区名print('爬取坐标')url = 'https://apis.map.qq.com/jsapi?qt=geoc&addr={}&output=jsonp&pf=jsapi&ref=jsapi&cb=qq.maps._svcb3.geocoder0'.format(name)headers = {"user-agent": }try:response = requests.get(url=url, headers=headers, proxies=get_proxies(), timeout=7)html = response.textif html[-1] != ';':html = html + ';'html = html.replace('\n', '').replace('\t', '').replace('\r', '')jsonp_str = re.findall('\((.*?)\);', html)[0]  # 提取JSONP响应中的JSON部分json_data = json.loads(jsonp_str)  # 将JSON字符串转换为字典pointx = json_data['detail']['pointx']pointy = json_data['detail']['pointy']return {'pointx': pointx, 'pointy': pointy}  # 返回经纬度的值except Exception as e:print('获取坐标错误', name, '重试!')print(e)return zb(name)# 测试代码
if __name__ == "__main__":test_name = "正定县"  # 测试用的区名,可以更换为其他区名coordinates = zb(test_name)print('经度:', coordinates['pointx'])print('纬度:', coordinates['pointy'])
返回数据

在这里插入图片描述

import requests
import jsonheaders = {"Host": "retail.hihonor.com","appsource": "wxapp","x-from": "wxapp","charset": "utf-8","x-appname": "wxapp","user-agent": "x-user-token": "","content-type": "application/json","x-access-token": "","referer": "https://servicewechat.com/wxde6bc80b07638016/409/page-frame.html"
}
url = "https://retail.hihonor.com/isrp/sms/online/store-info/getTargetStore/hi-honor"
data = {"coordinateType": "2","longitude": 116.231280,"latitude": 40.220770,"isGetTargetStore": True,"operatingStatus": 1,"isCheckSpu": True,"range": 50000,"enableWechatApplet": 1
}
data = json.dumps(data, separators=(',', ':'))
response = requests.post(url, headers=headers, data=data)print(response.text)
print(response)帮我提取出这段代码中的
问题
1.获取某些省,位置坐标报错

在这里插入图片描述

只能获取市级单位的经纬坐标

可见从头开始做测试的重要性,切忌想当然!!

2.代理不稳定,要重复请求
石家庄市

在这里插入图片描述

省——>市接口
"https://ccpce-cn.consumer.huawei.com/ccpcmd/services/dispatch/secured/CCPC/EN/ccpc/queryRegionList/1000"

这个接口比较特殊,是在华为消费者官网上找到的接口,通过这个接口。可以直接将省下面的市名列表获取到。这样就不用单独建数据库表了,直接调用就好了。这里注明来源,防止之后失效。

代码
# 获取下一级,省->市->区/县->
def get_next_level(code, level):#返回的是市级的数据,不要区县headers = {"Accept": "*/*","Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7","Connection": "keep-alive","Referer": "https://consumer.huawei.com/","Sec-Fetch-Dest": "script","Sec-Fetch-Mode": "no-cors","Sec-Fetch-Site": "same-site","User-Agent": "sec-ch-ua": "^\\^Not","sec-ch-ua-mobile": "?0","sec-ch-ua-platform": "^\\^Windows^^"}cookies = {}url = "https://ccpce-cn.consumer.huawei.com/ccpcmd/services/dispatch/secured/CCPC/EN/ccpc/queryRegionList/1000"params = {"jsonp": "jQuery36205836021093286132_{}".format(int(time.time() * 1000)),  # 使用当前时间戳,"countryCode": "CN","lang": "zh-cn","parent_alpha_2_code": code,"scopeGrade": level,"curpage": "1","pagesize": "1000","_": int(time.time() * 1000)}# 初始化重试次数max_retries = 3attempts = 0while attempts < max_retries:try:response = requests.get(url=url, headers=headers, cookies=cookies, params=params, proxies=get_proxies(), timeout=7)html = response.text# print(html)# 确保返回的JavaScript响应以分号结尾if html[-1] != ';':html = html + ';'# 使用正则表达式提取JSONP响应中的JSON数据html = re.findall('\({(.*?)\);', html)[0]# 将提取的JSON字符串转换为Python字典html = json.loads('{' + html)# 初始化一个空列表,用于存储解析后的数据datas = []# 遍历响应数据中的list部分,将每一项数据添加到datas列表中for data in html['responseData']['list']:datas.append(data)# print('打印响应数据')# print('----------------------------------------')# print(datas)# 返回解析后的数据列表return datasexcept Exception as e:print('获取下一级错误', code, '返回空数组!')print('异常类型:', type(e).__name__)print('异常信息:', e)# 如果尝试次数达到最大重试次数,则返回空数组if attempts == max_retries:print('已达到最大尝试次数,返回空数组!')return []# 短暂休眠后再次尝试time.sleep(2)# if __name__ == '__main__':
#         data = get_next_level("CN-36","city")#逻辑是如果是省调用这个接口
# 主函数
if __name__ == '__main__':# 遍历province_data中的每个省份for province_name, province_code in province_data.items():# 如果省份名称以"市"结尾,跳过直辖市,因为直辖市不需要获取下级市if province_name.endswith('市'):continue# 获取省份下的市级数据city_data = get_next_level(province_code, "city")# 市数量计数city_count = len(city_data)# # 初始化市名列表# city_names = [city['regionName'] for city in city_data]# city_names = [item['multi_lang_name'] for item in city_data['responseData']['list']]city_names = [item['multi_lang_name'] for item in city_data]# 打印省份名称,市的个数和市名列表print(f'省份名称: {province_name}')print(f'市的个数: {city_count}')print(f'包含的市名列表: {city_names}')print('----------------------------------------')
结果

在这里插入图片描述

代码优化:

写成了面向对象,有需要的可以后台call我。

之后如果客户有其他小程序的需求,还需要用scrapy框架进行分布式爬取数据

封装成scrapy框架
scrapy genspider honor consumer.huawei.com
实例:Scrapy框架请求逻辑
import scrapy
import json
import re
import time
from connRedis import OPRedisclass RegionSpider(scrapy.Spider):name = 'region_spider'allowed_domains = ['consumer.huawei.com']province_data = {# ... 省略其他省份数据 ...'江西省': 'CN-36',# ... 省略其他省份数据 ...}def start_requests(self):for province_name, province_code in self.province_data.items():if province_name.endswith('市'):continueyield scrapy.Request(url=self.get_url(province_code, "city"),callback=self.parse_city,meta={'province_name': province_name, 'province_code': province_code},cookies=self.get_cookies(),headers=self.get_headers())def parse_city(self, response):province_name = response.meta['province_name']province_code = response.meta['province_code']try:jsonp_string = response.textjson_string = re.findall(r'\((.*?)\);', jsonp_string)[0]data = json.loads(json_string)city_data = data['responseData']['list']city_count = len(city_data)city_names = [item['multi_lang_name'] for item in city_data]print(f'省份名称: {province_name}')print(f'市的个数: {city_count}')print(f'包含的市名列表: {city_names}')except Exception as e:self.logger.error(f'解析错误: {e}, 省份代码: {province_code}')def get_url(self, code, level):timestamp = int(time.time() * 1000)return f"https://ccpce-cn.consumer.huawei.com/ccpcmd/services/dispatch/secured/CCPC/EN/ccpc/queryRegionList/1000?jsonp=jQuery36205836021093286132_{timestamp}&countryCode=CN&lang=zh-cn&parent_alpha_2_code={code}&scopeGrade={level}&curpage=1&pagesize=1000&_={timestamp}"def get_cookies(self):return {# ... 省略其他cookies ..."JSESSIONID": "F78B38998A33F9B74DE0077819BF987E603F6C1FC1AC1005",# ... 省略其他cookies ...}def get_headers(self):return {"Accept": "*/*","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",}
代码用法

Scrapy爬虫类中,start_requests方法生成初始请求,parse_city方法解析响应并打印结果。get_urlget_cookiesget_headersget_proxies方法用于构建请求的URL、Cookies、Headers和代理。

在这里connRedis的模块和OPRedis的类是代理中间件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/806858.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu配置VScode的C++环境

在Ubuntu系统下配置C环境&#xff0c;并运行helloworld 1. 下载VScode 我这里使用的是星火应用商店&#xff0c;在商店里面可以直接下载安装 http://spark-app.store/ 2.创建文件夹 3.启动VScode并打开该文件夹 4.安装以下几个扩展 PS&#xff1a;Clang这个插件别安装&…

【电路笔记】-逻辑或非门

逻辑或非门 文章目录 逻辑或非门1、概述2、晶体管逻辑或非门3、数字逻辑或非门类型4、通用或非门逻辑或非门是数字逻辑或门与反相器或非门串联的组合。 1、概述 或非(Not-OR)门的输出通常为逻辑电平“1”,并且仅当其任何输入处于逻辑电平“1”时才变为“低”至逻辑电平“0”…

OpenHarmony应用开发引入开源C/C++库---之Har包里的NDK

Har 包 HAR&#xff08;Harmony Archive&#xff09;是静态共享包&#xff0c;可以包含代码、C 库、资源和配置文件。通过 HAR 可以实现多个模块或多个工程共享 ArkUI 组件、资源等相关代码。HAR 不同于 HAP&#xff0c;不能独立安装运行在设备上&#xff0c;只能作为应用模块…

力扣HOT100 - 73. 矩阵置零

解题思路&#xff1a; 题目要求使用原地算法 在原地算法中&#xff0c;输入数据通常在内存中直接被修改&#xff0c;而不需要额外的辅助数据结构来存储中间结果。原地算法的一个常见应用是在数组或列表上进行操作&#xff0c;而不是创建新的数组或列表来存储结果。 class So…

【截至2023年底】语言模型的发展

什么是大语言模型LLM&#xff1f;ChatGPT、LLAMA各自有什么优势&#xff1f; from&#xff1a; https://www.youtube.com/watch?vt6qBKPubEEo github&#xff1a; https://github.com/Mooler0410/LLMsPracticalGuide 来自这篇survey&#xff0c;但据说还在更新&#xff0c;到…

数据结构——线性表(顺序存储结构)

语言&#xff1a;C语言软件&#xff1a;Visual Studio 2022笔记书籍&#xff1a;数据结构——用C语言描述如有错误&#xff0c;感谢指正。若有侵权请联系博主 一、线性表的逻辑结构 线性表是n个类型相同的数据元素的有限序列&#xff0c;对n>0&#xff0c;除第一元素无直接…

MySQL:关于数据库的一些练习题

文章目录 前面的内容已经把数据库的一些必要知识已经储备好了&#xff0c;因此下面就对于这些语句进行一些练习&#xff1a; 批量插入数据 insert into actor values (1, PENELOPE, GUINESS, 2006-02-15 12:34:33), (2, NICK, WAHLBERG, 2006-02-15 12:34:33);SQL202 找出所有…

学习R语言第二天

R语言可以做什么 1.数据分析 R语言如何使用 1. 请看我的操作方式 2. 如何获取当前路径 -- 获取当前路径 > getwd() [1] "E:/R/RWorkSpace/day01" -- 修改当前路径 > setwd(dir "E:/R") > getwd() [1] "E:/R" 3.查看当下数据值的信…

UT单元测试

Tips&#xff1a;在使用时一定要注意版本适配性问题 一、Mockito 1.1 Mock的使用 Mock 的中文译为仿制的&#xff0c;模拟的&#xff0c;虚假的。对于测试框架来说&#xff0c;即构造出一个模拟/虚假的对象&#xff0c;使我们的测试能顺利进行下去。 Mock 测试就是在测试过程…

【CVE-2023-38831】进行钓鱼攻击的研究

本文仅仅是对相关漏洞利用的学习记录&#xff0c;请各位合法合规食用&#xff01; WinRAR是一款文件压缩器,该产品支持RAR、ZIP等格式文件的压缩和解压等。WinRAR在处理压缩包内同名的文件与文件夹时代码执行漏洞,攻击者构建由恶意文件与非恶意文件构成的特制压缩包文件,诱导受…

C# wpf 嵌入外部程序

WPF Hwnd窗口互操作系列 第一章 嵌入Hwnd窗口 第二章 嵌入WinForm控件 第三章 嵌入WPF控件 第四章 嵌入外部程序&#xff08;本章&#xff09; 第五章 底部嵌入HwndHost 文章目录 WPF Hwnd窗口互操作系列前言一、如何实现&#xff1f;1、定义属性2、进程嵌入&#xff08;1&…

AugmentedReality之路-平面检测(5)

本文介绍通过AR检测水平平面和垂直平面&#xff0c;并将检测到的平面转化为Mesh 1、在首页添加功能入口 在首页添加一个按钮&#xff0c;命名为Start World Track 2、自定义ExecStartAREvent 创建ARSessionConfig并取名为ARSessionConfig_World 自定义ExecStartAREvent&…

大话设计模式之迭代器模式

迭代器模式是一种行为设计模式&#xff0c;它允许客户端逐个访问集合中的元素&#xff0c;而不暴露集合的底层表示。这种模式提供了一种方法来访问聚合对象中的各个元素&#xff0c;而不需要暴露其内部结构。 迭代器模式由以下几个关键角色组成&#xff1a; 迭代器&#xff08…

React 使用 three.js 加载 gltf 3D模型 | three.js 入门

系列文章 示例项目(gitcode)&#xff1a;https://gitcode.com/qq_41456316/simple-react-three-demo 文章目录 系列文章前言一、three.js是什么&#xff1f;二、使用 React 和 three.js 加载 glTF 3D 模型的步骤步骤 1&#xff1a;创建 React 应用步骤 2&#xff1a;安装 thre…

实现ElasticSearch搜索自动补全【同附Java代码实现和拼音分词器安装】

文章目录 1、简介2、拼音分词器3、自定义分词器4、自动补全查询5、实现酒店搜索框自动补全5.1、修改酒店映射结构5.2、修改HotelDoc实体5.3、重新导入5.4、自动补全查询的JavaAPI5.5、实现搜索框自动补全 6、资料分享链接 ​&#x1f343;作者介绍&#xff1a;双非本科大三网络…

linux查看网络连接数

目录 netstat top netstat 1.netstat查看当前主机上网络连接信息&#xff0c;端口号&#xff0c;pid,程序名等等 #直接查看 netstat -anp #一般使用的时候&#xff0c;可能要筛选 #比如8080端口是否被占用 netstat -anp | grep 8080 #minio服务占用了那些端口 netstat -anp …

unity数组

数组的定义 动态初始化:在定义数组时只指定数组的长度&#xff0c;由系统自动为元素赋初值的方式。 静态初始化:定义数组的同时就为数组的每个元素赋值 数组的静态初始化有两种方式 1、类型门数组名new 类型[]{元素&#xff0c;元素&#xff0c;…}; 2、类型[数组名{元素&am…

ubuntu20挂载webdav

WebDAV 是个好东西&#xff0c;尤其是配个自己的 NAS 使用&#xff0c;熟悉以后就再也离不开它啦 sudo apt-get update sudo apt-get install davfs2 上下左右键可以切换到“是”选项 2.创建目录挂载点 sudo mkdir /mnt/webdav 3.配置 davfs2 编辑 davfs2.conf 文件以配置 da…

Node.js 的 5 个常见服务器漏洞

Node.js 是一个强大且广泛使用的 JavaScript 运行时环境&#xff0c;用于构建服务器端应用程序。然而&#xff0c;与任何其他软件一样&#xff0c;Node.js 也有自己的一些漏洞&#xff0c;如果处理不当&#xff0c;可能会导致安全问题。请注意&#xff0c;这些漏洞并不是 Node.…

基于springboot的扶贫产品和扶贫物资捐赠系统(含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的扶贫产品和扶贫物资捐赠系统2拥有管理员和用户角色 管理员&#xff1a;用户管理、扶贫项目管理、物资管理、扶贫产品管理、捐赠管理、资讯管理等 用户&#xff1a;捐赠…