Python 爬取途虎养车 全系车型 轮胎 保养 数据
1.获取全系车型品牌名称
def get_brand(self):
"""
获取品牌名称,用来拼接车型列表url
:return:
"""
url = 'https://by.tuhu.cn/baoyang'
self.driver.get(url)
letters = self.wait.until(EC.presence_of_all_elements_located((By.XPATH, '//div[@id="div2"]/ul/li')))
for i in range(1, len(letters)):
letters[i].click()
brands = self.wait.until(EC.presence_of_all_elements_located((By.XPATH, '//div[@id="CarBrands"]/ul/li')))
brands = [i.get_attribute('data-brand') for i in brands]
print(brands)
for u in brands:
with open('品牌名称.txt', 'a+', encoding='utf-8') as f:
f.write(u)
f.write('\n')
2.获取车型信息
@retry(stop_max_attempt_number=3)
def get_model(self, cond_brand):
"""
获取车型列表, 用来拼接排量url
:return:
"""
url = f'https://item.tuhu.cn/Car/SelOneBrand?callback=__GetCarBrands__&Brand={cond_brand}'
res = requests.get(url, headers=self.headers, timeout=5)
content = res.text.replace('__GetCarBrands__(', '').strip(')')
content = json.loads(content)
models = content['OneBrand']
for model in models:
try:
first = model['Brand'].split(' ')[0] # 首字母
brand = model['Brand'].split(' ')[2] # 品牌
BrandType = model['BrandType'] # 车厂
CarName = model['CarName'] # 型号
ProductID = model['ProductID'] # 型号ID 获取车型详细信息用
Tires = model['Tires'] # 轮胎尺寸
print(f'{first} {brand} {BrandType} {CarName} {ProductID} {Tires}')
# 首字母 品牌 车厂 型号 型号ID 轮胎尺寸
yield first, brand, BrandType, CarName, ProductID, Tires
except Exception as e:
print(f'解析车型数据错误:{e}')
continue
3.获取排量信息
@retry(stop_max_attempt_number=3)
def get_displacement(self, ProductID):
"""
获取排量, 用来拼接年份url
:return:
"""
url = f'https://item.tuhu.cn/Car/SelectVehicle?callback=__GetCarBrands__&VehicleID={ProductID}'
res = requests.get(url, headers=self.headers, timeout=5)
content = res.text.replace('__GetCarBrands__(', '').strip(')')
content = json.loads(content)
displas = content['PaiLiang']
for i in displas:
displa = i['Value'] # 排量
yield displa
4.获取年份信息
@retry(stop_max_attempt_number=3)
def get_year(self, ProductID, displa):
"""
获取年份, 用来拼接保养信息url
:return:
"""
url = f'https://item.tuhu.cn/Car/SelectVehicle?callback=__GetCarBrands__&VehicleID={ProductID}&PaiLiang={displa}'
res = requests.get(url, headers=self.headers, timeout=5)
content = res.text.replace('__GetCarBrands__(', '').strip(')')
content = json.loads(content)
years = content['Nian']
for i in years:
year = i['Value'] # 年份
yield year
5.获取保养信息
def get_maintenance(self, url):
session = HTMLSession()
r = session.get(url, verify=True)
try:
r.html.render(retries=5)
dosage = r.html.xpath('//p[@class="pack_tt2"]', first=True)
if dosage:
dosage = dosage.text.strip('(').strip(')')
else:
dosage = '官方暂无数据'
engine_model = r.html.xpath('//div[@class="pack_biaoti"]')
if engine_model:
engine_model = [i.text for i in engine_model]
motor_oil = engine_model[0].split('\n')[0]
level = engine_model[0].split('\n')[1] if len(engine_model[0].split('\n')) > 1 else '暂无数据'
machine_filter = engine_model[-1]
else:
motor_oil = level = machine_filter = '官方暂无数据'
prices = r.html.xpath('//div[@class="pck_price"]')
if prices:
prices = [i.text for i in prices]
motor_oil_money = prices[0]
machine_filter_money = prices[-1]
else:
motor_oil_money = machine_filter_money = '官方暂无数据'
session.close()
return dosage, motor_oil, motor_oil_money, level, machine_filter, machine_filter_money
except Exception as e:
session.close()
print(f'{url}数据获取失败 原因:{e}!!!')
with open('错误记录.txt', 'a+', encoding='utf-8') as f:
f.write(url)
f.write('\n')
6.数据保存
def save_xls(self, data):
"""
保存数据
data : 字典格式 必须和表头长度一样
:return:
"""
path = os.path.abspath('.') + r'/全系车型机油数据.xls'
if not os.path.exists(path):
Header = ['首字母', '品牌', '厂商', '型号', '型号ID', '排量', '年份', '轮胎尺寸', '机油容量',
'机油型号', '机油价格', '合成级别', '机滤型号', '机滤价格', '获取时间']
df = pd.DataFrame(columns=Header)
else:
df_read = pd.read_excel(path)
df = pd.DataFrame(df_read)
new = pd.DataFrame(data, index=[1])
df = df.append(new, ignore_index=True)
df.to_excel(path, sheet_name='data', index=False, header=True)
ContOS服务器相关
-
centos后台运行Python
nohup python -u test.py > test.log 2>&1 &
nohup 不挂起的意思
-u 代表程序不启用缓存,也就是把输出直接放到log中,没这个参数的话,log文件的生成会有 延迟
test.log 将输出日志保存到这个log中
2>1 2与>结合代表错误重定向,而1则代表错误重定向到一个文件1,而不代表标准输出;
2>&1 换成2>&1,&与1结合就代表标准输出了,就变成错误重定向到标准输出.
& 最后一个& ,代表该命令在后台执行*命令运行后会有提示,示例:
[1] 2880
代表进程2880中运行。*查看nohub命令下运行的所有后台进程:
jobs
*查看后台运行的所有进程:
ps -aux*查看后台运行的所有python 进程:
ps aux |grep python
或者
ps -ef | grep python 杀死进程
kill -9 pid # 根据进程id杀死进程
sudo kill -9 $(pidof 进程名关键字) # 根据程序名杀死进程
踏坑:
- URL请求数据时需先编码 from urllib.parse import quote
- 保养页面分析后发现是js加载后数据,直接请求获取不到数据,使用requests_html模块二次加载页面后可正常返回数据,requests_html首次安装会自动下载chrome
- ContOS启动Chromeium 报错缺少 libXcomposite.so.1
错误提示:/root/.local/share/pyppeteer/local-chromium/575458/chrome-linux/chrome: error while loading shared libraries: libXcomposite.so.1: cannot open shared object file: No such file or directory
原因:这是由于是最小化安装的centos,缺少相关的依赖
解决:yum install libXcomposite libXcursor libXi libXtst libXScrnSaver libXrandr atk at-spi2-atk gtk3 -y - ContOS 报错:[Errno 12] Cannot allocate memory!!! 内存不足
echo 3 > /proc/sys/vm/drop_caches # 释放内存缓存数据
os.system('echo 3 > /proc/sys/vm/drop_caches') # python 调用系统命令 - CentOS查看 占用 内存 最多的 进程
ps -aux | sort -k4nr | head 5 # 查看内存使用最多的5个进程
或者
top (然后按下M,注意大写)
ps -aux | sort -k3nr | head 5 # 查看CPU使用最多的5个进程
或者
top (然后按下P,注意大写)
本文仅供学习交流使用,如侵立删!
企鹅 : 1033383881