爬虫笔记16——异步爬取二手汽车数据去重存入MySQL

需要用到的库

#异步数据库
pip install aiomysql
#reids数据库进行去重
pip install redis
#用hashlib进行md5加密
pip install hashlib
#基于异步IO的网络请求库
pip install aiohttp
#xpath获取静态页面数据
pip install lxml

目标网站

目标网站:https://www.che168.com/china/a0_0msdgscncgpi1ltocsp1exf4x0/?pvareaid=102179#currengpostion
获取汽车具体数据的api:https://cacheapigo.che168.com/CarProduct/GetParam.ashx?specid={}
其中{}方便使用format进行格式化

思路分析

1、要获取详细的汽车数据,需要在首页点击某个汽车进入到详情页面数据,这个过程会携带该汽车类型的specid跳转到详情数据页面,并请求对应的接口返回具体数据信息。
2、那我们需要在这个首页的罗列数据提取到每个汽车对应的specid,因为这是一个静态页面,使用xpath获取每个汽车的specid。
3、在详情数据页面,获取汽车的具体数据需要分析对应的接口进行请求,这个请求的过程需要携带前面获取到的specid。
4、最后获取数据成功进行提取,去重,存储即可

代码示例

值得注意的是:这个网页有反爬机制,他的页面编码格式会切换,如果返回的编码格式是UTF-8-SIG,是获取不到网页数据的,也就是提取不到specid,那后面也就获取不了汽车详细数据,所以我们要验证页面编码格式,这里要用到chardet包

pip install chardet

代码实现:

# -*- coding: utf-8 -*-
# @Time:      2024/06/24 12:51
# @File:       二手车.pyimport aiomysql
import aiohttp
import redis
import hashlib
import chardet
import asyncio
from lxml import etreeclass SpiderCar:def __init__(self):self.redis = redis.Redis()self.url = 'https://www.che168.com/china/a0_0msdgscncgpi1ltocsp{}exf4x0/?pvareaid=102179#currengpostion'self.api_url = 'https://cacheapigo.che168.com/CarProduct/GetParam.ashx?specid={}'self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"}async def get_car_id(self, page, session, pool):async with session.get(self.url.format(page), headers=self.headers) as response:content = await response.read()encoding = chardet.detect(content)["encoding"]if encoding == 'GB2312':html = content.decode('gbk')else:html = content.decode(encoding)print('被反爬了...')tree = etree.HTML(html)car_id_list = tree.xpath("//ul[@class='viewlist_ul']/li/@specid")if car_id_list:car_info_tasks = [asyncio.create_task(self.get_car_info(car_id, session, pool)) for car_id in car_id_list]await asyncio.wait(car_info_tasks)async def get_car_info(self, car_id, session, pool):async with session.get(self.api_url.format(car_id), headers=self.headers) as response:car_info = await response.json()# print(car_info)if car_info["result"]["paramtypeitems"]:item = dict()item['name'] = car_info['result']['paramtypeitems'][0]['paramitems'][0]['value']item['price'] = car_info['result']['paramtypeitems'][0]['paramitems'][1]['value']item['brand'] = car_info['result']['paramtypeitems'][0]['paramitems'][2]['value']item['altitude'] = car_info['result']['paramtypeitems'][1]['paramitems'][2]['value']item['breadth'] = car_info['result']['paramtypeitems'][1]['paramitems'][1]['value']item['length'] = car_info['result']['paramtypeitems'][1]['paramitems'][0]['value']await self.save_car_info(item, pool)@staticmethoddef md5_hash(item):hash_obj = hashlib.md5()hash_obj.update(str(item).encode())return hash_obj.hexdigest()async def save_car_info(self, item, pool):async with pool.acquire() as connect:async with connect.cursor() as cursor:hash_item = self.md5_hash(item)obj = self.redis.sadd('car_info:filter', hash_item)if obj:sql = """insert into car_info value (%s, %s, %s, %s, %s, %s, %s);"""try:await cursor.execute(sql, (0, item['name'], item['price'], item['brand'], item['altitude'], item['breadth'], item['length']))await connect.commit()print('插入成功')except Exception as e:print('插入失败!', e)await connect.rollback()else:print('数据重复,跳过该条数据')async def main(self):async with aiomysql.create_pool(user='root', password='root', db='py_spider') as pool:async with pool.acquire() as connect:async with connect.cursor() as cursor:# sql = """#     create table if not exists car_info (#         id int primary key auto_increment,#         name varchar(100),#         price varchar(100),#         brand varchar(100),#         altitude varchar(100),#         breadth varchar(100),#         length varchar(100)#     )# """# await cursor.execute(sql)# 创建表create_table_sql = """create table car_info(id int primary key auto_increment,name varchar(100),price varchar(100),brand varchar(100),altitude varchar(100),breadth varchar(100),length varchar(100));"""# 在异步代码中必须先要检查表是否存在, 直接使用if not语句无效check_table_query = "show tables like 'car_info'"result = await cursor.execute(check_table_query)  # 如果表存在返回1 不存在返回0if not result:await cursor.execute(create_table_sql)async with aiohttp.ClientSession() as session:car_id_tasks = [asyncio.create_task(self.get_car_id(page, session, pool)) for page in range(1, 100)]await asyncio.wait(car_id_tasks)if __name__ == '__main__':spider_car = SpiderCar()loop = asyncio.get_event_loop()loop.run_until_complete(spider_car.main())

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

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

相关文章

高考专业组 07组 08组 武汉大学

武汉大学的招生都什么废物点心,搜个专业组都没官方解释! 07组:理学,详见下表专业代码07xxxx,例如数学、物理、化学 08组:工学,详见下表专业代码08xxxx,例如机械、电子信息、自动化、…

每天一个数据分析题(三百七十八)- 系统聚类

在系统聚类方法中,哪种系统聚类是直接利用了组内的离差平方和? A. 最长距离法 B. 重心法 C. Ward法 D. 类平均法 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专项练习题库 内容涵盖Python&#…

R语言做图

目录 1. 图形参数 2. 低级图形 3. 部分高级图形 参考 1. 图形参数 图形参数用于设置图形中各种属性。 有些参数直接用在绘图函数内,如plot函数可以用 pch(点样式)、col(颜色)、cex(文字符号大小倍数&…

ONLYOFFICE 桌面编辑器 8.1

ONLYOFFICE 简介 ONLYOFFICE 是一个开源的办公套件,它提供了在线文档编辑器、表格编辑器和演示文稿编辑器,这些编辑器能够兼容 Microsoft Office 格式(.docx, .xlsx, .pptx)以及其他流行的标准格式。ONLYOFFICE 的核心功能包括多…

Spcok测试代码抛异常场景

测试代码抛异常场景 ‍ class ExceptionSpec extends Specification {def validateService new ValidateService()Unrolldef "验证UserInfo"() {when: "调用校验方法"validateService.validateUser(user)then: "捕获异常并设置需要验证的异常值&qu…

注意力机制的原理

注意力机制的原理 注意力机制是深度学习中的一种关键组件,尤其是在处理序列数据,如自然语言处理任务时,它允许模型关注输入序列的不同部分,而不是对所有元素赋予相同的权重。其基本思想是为每个输入位置赋予一个权重,…

分类预测 | ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别

分类预测 | ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别 目录 分类预测 | ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别分类效果基本描述程序设计参考资料 分类效果 基本描述 1.ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融…

《2024天猫618大促-首波男装销售报告》

这份报告主要分析了2024年天猫618大促期间的首波男装销售情况,从多个维度进行了深入的复盘和分析。报告中不仅包含了销售数据的统计分析,还对消费者行为、品牌表现、产品趋势等方面进行了详细的解读。通过对这些数据和信息的深入挖掘,报告揭示了当前男装市场的一些重要趋势和特…

qt经典界面框架

目的 其实就是一个简单的界面显示,是很常用的形式。 说起来简单也是简单,但当初,刚开始做时,感觉非常的复杂,不知如何下手。 现在感觉简单多了。 这个框架利用了QT的现成的MainWindow与QDockWidget,这样就…

Vue3 + TS 防抖动

目录 一、防抖动 1、概念 2、原理 3、应用场景 1、概念 通过将多次连续触发的函数调用合并成一次来减少函数的执行次数。防抖的核心思想是在某个时间段内,只执行一次函数,而忽略在此时间段内的其他触发。 2、原理 (1)、定时器; (2)、重…

java基于ssm+jsp 人才公寓管理系统

1管理员功能模块 管理员登录,通过填写用户名、密码进行登录,如图1所示。 图1管理员登录界面图 管理员登录进入人才公寓管理系统可以查看个人中心、住户管理、小区公告管理、停车位管理、安保人员管理、安保值班管理、房屋信息管理、外来登记管理、物品…

把STL容器放入共享内存,重用STL allocator,传入模板参数Allocator,可以实现

问题 Q: 如何用共享内存来存放C STL中中的容器? A: 传入自定义的申请共享内存上空间的allocator,见模板参数Allocator 参考 https://www.zhihu.com/question/319108981/answer/649050789 https://en.cppreference.com/w/cpp/container/vector http://…

自定义User-Agent:使用Python Requests进行网络请求

在网络编程和数据采集领域,HTTP请求是与服务器交互的基本方式。User-Agent(用户代理)是HTTP请求中的一个重要字段,它告诉服务器发起请求的客户端类型和版本信息。在某些情况下,自定义User-Agent可以帮助我们模拟不同的…

CodeIgniter学习笔记 Item6--CI中的常规主题_ci中parent __construct();

$route[default\_controller] welcome; $route[404\_override] ;更重要的功能是,如果我们要实现通过/index.php/news/4.html访问/index.php/article/show/1这样一个需求,可以在routes.php定义路由关系,将原始的URL转换成需要样式 $route[n…

QtSingleApplication

​​​​​​/qtsingleapplication/ qtSingleApplication使用总结-CSDN博客 示例&#xff1a; #include "mainwindow.h" #include <QApplication> #include <QMessageBox> #include "qtsingleapplication/qtsingleapplication.h" int main(…

正向代理与反向代理:深入解析与实例讲解

代理服务器是一种网络实体&#xff0c;它充当客户端与服务器之间的中介&#xff0c;负责转发请求和响应。代理服务器可以根据其使用方式和功能的不同&#xff0c;分为正向代理和反向代理。 转转的面试中问到了正向代理和反向代理。所以本篇文章将详细解析这两种代理方式&#…

产品干货 | 如何通过Power Platform快速创建自定义连接器,让开发集成更简单

引言 Introduction&#xff1a; 最近&#xff0c;微软推出了许多新产品功能。迅易科技作为微软13年来紧密的生态合作伙伴&#xff0c;为300行业头部客户实施1000项目。为此&#xff0c;我们总结了多年的项目经验且产品学习心得&#xff0c;邀请了迅易技术专家为大家持续分享微软…

Oracle数据库之PL/SQL例外(二十三)

在Oracle PL/SQL中&#xff0c;例外&#xff08;或异常&#xff09;是程序设计语言提供的一种功能&#xff0c;旨在增强程序的健壮性和容错性。Oracle PL/SQL中的例外可以分为两大类&#xff1a;系统定义例外和自定义例外。 1. 系统定义例外 系统定义例外是Oracle数据库预先定…

不同系統和流覽器如何檢查代理設置(Mac/Windows/Linux)

本文將詳細介紹如何檢查代理設置&#xff0c;並提供一些建議&#xff0c;幫助你更好地管理和優化代理使用體驗。 為什麼需要檢查代理設置&#xff1f; 代理伺服器的主要功能之一是保護用戶的隱私。如果代理設置不正確&#xff0c;可能會暴露你的真實IP地址&#xff0c;導致隱…

如何自己录制教学视频?零基础也能上手

随着在线教育的蓬勃发展&#xff0c;录制教学视频成为了教师和教育工作者们不可或缺的一项技能。无论是为了远程教学、课程分享还是知识普及&#xff0c;教学视频的录制都变得愈发重要。可是如何自己录制教学视频呢&#xff1f;本文将介绍两种录制教学视频的方法&#xff0c;这…