改寫爲普通類方法:python3將pos系統在線產品信息到excel表,以及封面圖和詳情圖下載到本地

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()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章