2025年3月16日 星期日 甲辰(龙)年 月十五 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Python

改写为普通类方法:python3将pos系统在线产品信息到excel表,以及封面图和详情图下载到本地

时间:12-10来源:作者:点击数:16

1、登录POS后台,获取企业在线的产品信息,包含规格、价格、封面图、详情页图等信息到本地中

2、登录成功后需输入要查询的企业名字,然后再根据提示输入相应企业的ID号即可下载 

  • #!/usr/bin/env python
  • # coding=utf-8
  • # 有选择性的获取POS后台企业的产品信息并下载到excel表格中以及图片到本地
  • import requests
  • import re
  • from lxml import etree
  • from openpyxl import Workbook
  • import time,os
  • class POS_crawl(object):
  • def __init__(self, username, password):
  • # 初始化登录headers实例
  • self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0",
  • "Referer": "https://pos.XXXX.com/item/pf.html"
  • }
  • # 核实界面
  • self.post_url = "https://pos.XXXX.com/j_spring_"
  • # 创建session对象,可以保存Cookie值
  • self.session = requests.session()
  • self.username = username
  • self.password = password
  • # 构建一个厂商信息的列表,每组数据用字典保存:[{"105080":"某某企业公司"},{"105082":"某某企业公司"}]
  • self.company_list = []
  • self.data = ['序号', 'ID', '品牌', '产品名称',
  • '商家分类', '平台分类', '销售情况', '销售标题',
  • '价格','促销价', '规格', '起订量', '适应区域'
  • ]
  • self.wb = Workbook()
  • # 提取表单登录信息(可以和模拟登陆合并成一个)
  • def get_login_info(self):
  • data = {
  • "j_username": self.username,
  • "j_password": self.password
  • }
  • return data
  • # 模拟登录
  • def login(self):
  • data = self.get_login_info()
  • headers = {
  • 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0);',
  • "Referer": self.post_url,
  • "X-Requested-With": "XMLHttpRequest",
  • }
  • try:
  • # 发送附带用户名和密码的请求,并获取登录后的Cookie值,保存在session里
  • login_page = self.session.post(self.post_url, data=data, headers=headers)
  • # print(login_page.text)
  • if "loginerror" in login_page.text:
  • print("登录失败,错误的手机号码或密码!")
  • if "</span>首页" in login_page.text:
  • print("欢迎您'%s',成功登陆POS管理系统!"%self.username)
  • self.get_key()
  • except Exception as e:
  • print(e)
  • # 先获取提交表单数据的key值,也就是企业的ID列表
  • def get_key(self):
  • on_list_url = "https://pos.XXXX.com/item/lis.html"
  • # 调取process_session_get方法
  • selector = self.process_session_get(on_list_url)
  • # 获取厂商的名字
  • company_name = selector.xpath('//select[@id="sel_company"]/option/text()')
  • # 获取厂商的ID
  • company_id = selector.xpath('//select[@id="sel_company"]/option/@value')
  • # 先构建一个厂商信息的列表,每组数据用字典保存:[{"105080":"某某企业公司"},{"105082":"某某企业公司"}]
  • for i in range(len(company_id)):
  • # 创建空字典存储每一个企业信息
  • dic = {}
  • # 这里排除掉一些无用的企业,后续可以不断增加
  • if company_id[i] not in ['109102','109085','109904','109086','105342','3','107084','0']:
  • dic[company_id[i]] = company_name[i]
  • self.company_list.append(dic)
  • self.company_info()
  • # 这个方法来处理用户输入的企业名称,并返回相应企业名称的ID
  • def company_info(self):
  • while True:
  • key_company = input("请输入要获取的企业名称:")
  • key_list =[]
  • value_list = []
  • # 这个一定要判断,防止用户直接输入回车,否则会导致所有企业信息全部显示出来
  • if key_company != "":
  • for company_dic in (self.company_list):
  • # company_dic就是每组企业信息的字典
  • # 遍历企业信息字典的value值,并和输入的比对
  • for value_company in company_dic.values():
  • if key_company in value_company:
  • for key,value in company_dic.items():
  • # 保存key值
  • key_list.append(int(key))
  • # 保存value值
  • value_list.append(value)
  • if len(key_list) != 0:
  • print("====================共%s条相关企业信息===================="%(len(key_list)))
  • print("{:^10}\t{:^23}".format("企业ID", "企业名称"))
  • for i in range(len(key_list)):
  • print("{:^10}\t{:^23}".format(key_list[i], value_list[i]))
  • # 判断开关,如果有企业信息,才会去提示用户输入ID号
  • switch=True
  • break
  • else:
  • print("ERROR:未找到相关的企业信息,请重试!")
  • else:
  • print("ERROR:输入有误,请重试!")
  • print("=" * 54)
  • while True:
  • if switch:
  • try:
  • ID_key = int(input("请输入相应企业一模一样的ID号:"))
  • # 防止用户输入回车
  • if ID_key != "":
  • if ID_key in key_list:
  • formdata = self.form_process(str(ID_key))
  • self.item_on_list(formdata,str(ID_key))
  • break
  • else:
  • print("ERROR:您输入的ID号不在以上企业信息中,请重试!")
  • else:
  • print("ERROR:输入有误,请重试!")
  • except:
  • print("ERROR:输入有误,请重试!")
  • def form_process(self,ID_key,page=0):
  • # 后台需提交的表单数据
  • formdata = {
  • "cate1": "-1",
  • "cate2": "-1",
  • "cate3": "-1",
  • "province": "-1",
  • "city": "-1",
  • "dist": "-1",
  • "pf.companyId": ID_key,
  • "pf.sortTime": "onlineTime",
  • "pf.salesType": "0",
  • "pf.isSales": "0",
  • "pf.isExtend": "0",
  • "pf.homeExtend": "0",
  • "pf.name": "",
  • "pf.startDate": "",
  • "pf.endDate": "",
  • "page": page,
  • "pf.region": "-1",
  • "pf.categoryId": "-1",
  • }
  • return formdata
  • # 发送session.pos请求的方法
  • def process_session_pos(self,on_list_url,formdata):
  • item_list = self.session.post(on_list_url, data=formdata, headers=self.headers)
  • # 利用etree.HTML,将响应内容解析为HTML文档,并返回
  • html = etree.HTML(item_list.text)
  • return html
  • # 发送session.get请求的方法
  • def process_session_get(self,get_url):
  • content_item = self.session.get(get_url, headers=self.headers)
  • # 利用etree.HTML,将响应内容解析为HTML文档,并返回
  • html = etree.HTML(content_item.content)
  • return html
  • # 获取商品查询页面,发送请求
  • def item_on_list(self,formdata,ID_key):
  • on_list_url = "https://pos.XXXX.com/item/lis.html"
  • html = self.process_session_pos(on_list_url,formdata)
  • # 利用xpath规则获取几页数据,是一个列表[1/3]
  • result_list = html.xpath("//div[@class='centercontent']/div[@id='contentwrapper']/p/span[2]/span/text()")
  • # 获取总共多少产品>>查询结果:共 5649 条数据
  • total_product = html.xpath("//div[@class='centercontent']/div[@id='contentwrapper']/p/span[1]/text()")[0]
  • # 将查询结果里面的数字提取出来
  • # pattern = re.compile(r'\d+')
  • # result_number = pattern.findall(result_list[0])
  • if len(result_list) !=0:
  • # 获取总共多少页
  • page = result_list[0].split("/")[1]
  • print("=========该企业的%s,共%s页========="%(total_product,page))
  • company_name = ''
  • for i in range(1,int(page)+1):
  • formdata = self.form_process(ID_key,i)
  • time.sleep(1)
  • html = self.process_session_pos(on_list_url, formdata)
  • # 获取企业名称
  • company_name = html.xpath('//div[@class="pt5 pb5 pl10 pr10"]/p/span[@class="l orange ff f18"]/text()')[0]
  • # 获取产品名称
  • product_name_list = html.xpath('//div[@class="pt5 pb5 pl10 pr10"]/dl/dt/a/text()')
  • # 获取产品ID,需要处理,javascript:show('105813')
  • id_list = html.xpath('//div[@class="pt5 pb5 pl10 pr10"]/dl/dt/a/@href')
  • pattern_id = re.compile(r"javascript:show\('(\d+)'\)")
  • end_id_list = []
  • for i in range(len(id_list)):
  • end_id = pattern_id.search(id_list[i]).group(1)
  • end_id_list.append(end_id)
  • # 调取获取产品描述、价格、规格等信息页面方法
  • total_list = self.process_product(end_id_list,company_name,product_name_list)
  • # 处理表格数据
  • self.process_excel(total_list,company_name)
  • print("数据保存到本地中....")
  • # 保存表格名称为企业名字和当天的日期
  • file_end_name = company_name + time.strftime("%Y-%m-%d", time.localtime())
  • self.wb.save(file_end_name + '.xlsx')
  • address = os.path.abspath(file_end_name + '.xlsx')
  • print("以上数据处理完毕,表格已经保存到该路径下:%s" % address)
  • else:
  • print("该企业未有在线产品!")
  • # 获取产品描述、价格、规格等信息方法
  • def process_product(self,end_id_list,company_name,product_name_list):
  • # 计数器,也就是序号
  • count = 0
  • # 列表嵌套,目的是里面的每一个列表都是一个要写入表格的完整信息
  • total_list = []
  • for k in range(len(end_id_list)):
  • # 商品弹框地址
  • id_url = 'https://pos.XXXX.com/item/sho.html?item.id=' + end_id_list[k]
  • time.sleep(1)
  • selector = self.process_session_get(id_url)
  • # 获取产品名称
  • # product_name = selector.xpath('//div[@id="tabs-1"]/p[1]/span/text()')[0].strip().split(" ")[1]
  • product_name = product_name_list[k].strip()
  • print("正在处理产品:%s" % product_name)
  • # 获取品牌,需要处理,有空格
  • brand_list = selector.xpath('//div[@id="tabs-1"]/p[1]/span/text()')[0].strip().split(" ")[0]
  • # 获取商家分类
  • company_class = selector.xpath('//div[@id="tabs-1"]/p[4]/span/text()')[0].strip()
  • # 获取适应区域
  • product_area = selector.xpath('//div[@id="tabs-1"]/p[2]/span/text()')[0].strip()
  • # 获取平台分类
  • platform_class = selector.xpath('//div[@id="tabs-1"]/p[3]/span/text()')[0].strip()
  • # 是否销售
  • sale_list = selector.xpath('//div[@id="tabs-1"]/p[6]/span/text()')[0].strip()
  • # 销售标题
  • sales_title = selector.xpath('//div[@id="tabs-1"]/p[8]/span/text()')[0].strip()
  • # 规格,可能为多个
  • product_size = selector.xpath('//div[@id="tabs-5"]/table[@id="item"]/tbody/tr/td[1]/text()')
  • # skuid,可能为多个:[10001162,10001163]
  • skuid_list = selector.xpath('//div[@id="tabs-5"]/table[@id="item"]/tbody/tr/td[1]/input/@value')
  • # 起订量,可能为多个
  • product_quantity = selector.xpath('//div[@id="tabs-5"]/table[@id="item"]/tbody/tr/td[8]/text()')
  • # 封面图链接地址,lookPic('http://isi14735834071051.jpg')需要正则去处理
  • cover_image_list = selector.xpath('//div[@id="tabs-3"]/div/span/img/@onclick')
  • patt = re.compile(r"lookPic\('(.*)'\)")
  • # 封面图链接地址存放列表
  • cover_image_link = []
  • for i in range(len(cover_image_list)):
  • cover_image = patt.match(cover_image_list[i]).group(1)
  • cover_image_link.append(cover_image)
  • # 详情页图链接地址
  • detail_image_link = selector.xpath('//div[@id="tabs-4"]/img/@src')
  • # 存放封面图和详情页图
  • image_list = cover_image_link + detail_image_link
  • # 调用图片处理方法
  • self.process_image(image_list,company_name,product_name)
  • for j in range(len(skuid_list)):
  • # 用规格的skuid来计数,正好是产品序号,包含多个规格
  • count += 1
  • # 存储每个信息的列表
  • product_list = []
  • # 包含产品价格、规格网址
  • end_skuid_url = "https://pos.XXXX.com/item/showi.html?sku.id=" + skuid_list[j]
  • skuid_selector = self.process_session_get(end_skuid_url)
  • # 获取零售价,将重复的价格筛选掉,用set去掉重复项,并转换为列表
  • retail_price_list = skuid_selector.xpath('//div[@id="tabs-1"]/table[@id="item"]/tbody/tr/td[2]/text()')
  • retail_price = list(set(retail_price_list))
  • for i in range(len(retail_price)):
  • if retail_price[i] == "0.0":
  • retail_price[i] = '零售价待定'
  • elif retail_price[i] == "0.00":
  • retail_price[i] = '零售价数据0.00有误'
  • # 如果是多个价格,用分号隔开
  • if len(retail_price) > 1:
  • retail_price = ";".join(retail_price)
  • elif len(retail_price) == 1:
  • retail_price = retail_price[0]
  • # 获取零售促销价,将重复的促销价筛选掉,用set去掉重复项,并转换为列表
  • promotion_price_list = skuid_selector.xpath( '//div[@id="tabs-1"]/table[@id="item"]/tbody/tr/td[3]/text()')
  • promotion_price = list(set(promotion_price_list))
  • for i in range(len(promotion_price)):
  • if promotion_price[i] == "0.0":
  • promotion_price[i] = '无促销价'
  • elif promotion_price[i] == "0.00":
  • promotion_price[i] = '促销价数据0.00有误'
  • # 如果是多个促销价格,用分号隔开
  • if len(promotion_price) > 1:
  • promotion_price= ";".join(promotion_price)
  • elif len(promotion_price) == 1:
  • promotion_price = promotion_price[0]
  • # 将每个规格的数据,组成一个完整的列表,最后再装进total_list
  • product_list.append(count)
  • product_list.append(end_id_list[k])
  • product_list.append(brand_list)
  • product_list.append(product_name)
  • product_list.append(company_class)
  • product_list.append(platform_class)
  • product_list.append(sale_list)
  • product_list.append(sales_title)
  • product_list.append(retail_price)
  • product_list.append(promotion_price)
  • product_list.append(product_size[j])
  • product_list.append(product_quantity[j])
  • product_list.append(product_area)
  • # 目的是列表嵌套,里面的每一个列表都是一个要写入表格的完整信息
  • total_list.append(product_list)
  • return total_list
  • # 图片处理
  • def process_image(self,image_list,company_name,product_name):
  • for i in range(len(image_list)):
  • # 存放文件的目录
  • file_path = "./"+company_name +"/"+ product_name + "/"
  • if (not os.path.exists(file_path)):
  • os.makedirs(file_path)
  • html = requests.get(image_list[i])
  • print("图片-%s下载中....."%(i+1))
  • if image_list[i][-4:].lower() in ['.jpg', '.gif', '.png']:
  • with open(file_path +"图片-"+str(i+1)+image_list[i][-4:],"wb")as f:
  • f.write(html.content)
  • # 表格处理
  • def process_excel(self,total_list,company_name):
  • # print("数据保存到本地中....")
  • ws = self.wb.active
  • ws.title = '企业在线产品列表' # 修改第一个sheet表名为企业在线产品列表
  • # 先写入表头数据
  • for head in range(1, len(self.data) + 1):
  • _ = ws.cell(row=1, column=head, value=self.data[head - 1])
  • for product_fullList in total_list:
  • ws.append(product_fullList)
  • # # 保存表格名称为企业名字和当天的日期
  • # file_end_name = company_name +time.strftime("%Y-%m-%d", time.localtime())
  • # self.wb.save(file_end_name + '.xlsx')
  • # address = os.path.abspath(file_end_name + '.xlsx')
  • # print("以上数据处理完毕,表格已经保存到该路径下:%s"%address)
  • if __name__ == "__main__":
  • username = input("请输入登录账号:")
  • password = input("请输入登录密码:")
  • az = POS_crawl(username, password)
  • az.login()

 

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐