pyqt5练手项目-抖音小姐姐短视频下载

pyqt5=Python+ qt,这块的资料现在慢慢多起来了,这里给大家送一个小的demo用来练手。

里面技术点:

1)控件 Pushbutton的使用;

2)pyqt5线程的用法;

3)界面和逻辑分离;

4)pyqt5  控制台日志重定向到editText控件中;这块比较有意思,大家可以学学;

界面如下:

另外打个广告:这段时间闲着没事,自己弄了个淘客网站。领取天猫淘宝优惠券的,和一般的找券网不同,采集下来的天猫淘宝产品都是经过我的大数据模型筛选的,希望大家帮忙测试下,网页右上角有安卓app下载。

网站链接:http://www.0k8gj.cn/

接下来是正题:

一共四个文件,大家可以分别拷贝到自己工程里面调试一下,可以直接运行:

work.py

# -*- coding: utf-8 -*-
	
from PyQt5.QtGui import  *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import sys
from ui_main import Ui_MainWindow

import threading
import time
import os
import inspect
import ctypes
import re
from  tools import *
from douyin import *


gMaxThreadNum = 2 # 最大线程数目
gWorkingThreadNum = 0


gThreadsList = []   #存放线程ID

gThreadLock = threading.Lock()   #获取发帖内容时,需要加锁
gTotalLink = []
gThreadCountLock = threading.Lock()
#@函数介绍:启动多个线程进行发帖   
#@返回值: True/False
#@data: 20180803  
def mainTask():
    global gMaxThreadNum  #最大线程个数
    global gWorkingThreadNum  #正在运行的工作线程的个数
    global gThreadCountLock  #全局锁
    global gTotalLink 
    gWorkingThreadNum = 0
     
    ipublishIndex = 1
    while True:
        if gWorkingThreadNum < gMaxThreadNum:
            
            if ipublishIndex > len(gTotalLink):
                printStr('所有任务完成,等待各个子线程完成后,退出........')
                break;
            ipublishIndex = ipublishIndex +1
            #启动一个线程
            t = threading.Thread(target=workThread)
            t.start()
            gThreadsList.append(t)
            
            gThreadCountLock.acquire()
            gWorkingThreadNum = gWorkingThreadNum +1
            gThreadCountLock.release()
            
        time.sleep(0.1)
    return True   
#@函数介绍: 退出线程
#@返回值: true/false, 成功/失败
#@data: 20180806
def stop_thread(thread):
    tid = thread.ident
    exctype = SystemExit
    ret = True
    """raises the exception, performs cleanup if needed"""

    tid = ctypes.c_long(tid)

    if not inspect.isclass(exctype):

        exctype = type(exctype)

    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))

    if res == 0:
        ret = False
        #raise ValueError("invalid thread id")
        strs = '%s子线程已经退出'%tid
        printStr(strs)

    elif res != 1:

        # """if it returns a number greater than one, you're in trouble,

        # and you should call it again with exc=NULL to revert the effect"""
        ret = False

        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)

        raise SystemError("PyThreadState_SetAsyncExc failed")
    else:
        ret = True
        strs = '%s 线程被Kill'%tid
        printStr(strs)
    return ret

def workThread():
    global gTotalLink
    global gThreadLock
    global gWorkingThreadNum

    gThreadCountLock.acquire()
    video_url = gTotalLink.pop()
    gThreadCountLock.release()
    
    printStr('video_url:%s'%video_url)
    #video_url = 'http://v.douyin.com/dU2Dsn/'
    handle  = douyin()
    downloadUrl ,  name = handle.downloadUrlGet(video_url)
    

    if  True == os.path.exists(name+'.mp4'):
        name = name + str(randomInt(2))+'.mp4'
    handle.video_downloader(downloadUrl,  name+'.mp4')
    
    gThreadCountLock.acquire()
    gWorkingThreadNum = gWorkingThreadNum +1
    gThreadCountLock.release()

class EmittingStream(QObject):  
        textWritten = pyqtSignal(str)  #定义一个发送str的信号
        def write(self, text):
            self.textWritten.emit(str(text))  
#@类介绍:主类
#@返回值: 
#@data: 20180801 
class mainForm(QMainWindow,  Ui_MainWindow):
    def __init__(self):
        super(mainForm,  self).__init__()
        self.setupUi(self)
        #self.setWindowFlags(Qt.WindowMinimizeButtonHint)  
        #禁止调整窗口大小
        self.setFixedWidth(848)
        self.setFixedHeight(588)
        #信号槽,点击开始会去连接startTask
        self.pushButton_startRun.clicked.connect(self.startTask)
        #信号槽,暂停
        self.pushButton_stopRun.clicked.connect(self.stopTask)
        self.spinBox_maxThreadNum.valueChanged['int'].connect(self.threadNumSet)
        #编辑内容
        #self.pushButton_editFileContent.clicked.connect(self.editContent)
        #下面将输出重定向到textEdit中
        sys.stdout = EmittingStream(textWritten=self.outputWritten)  
        sys.stderr = EmittingStream(textWritten=self.outputWritten)  
        self.initPara()
        
    #编辑内容
    def editContent(self):
        dig = QFileDialog()
        dig.getOpenFileName(self,  'Open file',  '', "") 
        
    def initPara(self):
        global gTotalLink
        file = open('需要下载的的链接.txt',  'a+')
        file.close()
        
        #读取内容
        file = open('需要下载的的链接.txt',  'r')
        strContent = file.read()
        file.close()
        resultList = re.findall('(?<=###).+?(?=###)', strContent, re.S)
        for item in resultList:
            if '\n' == item:
                pass
            else:
                p = item.find('http') 
                item = item[p: item.find(' 复',  p)]
                if item == '':
                    continue
                gTotalLink.append(item)
        printStr('gTotalLink:%s'%gTotalLink)
     #@data: 20180801
    def startTask(self):
        global gThreadsList
        
        
        if len(gThreadsList) != 0:
            for t in gThreadsList:
                stop_thread(t)
        #运行主任务

        printStr('开启工作任务...')
        t = threading.Thread(target=mainTask)
        t.start()
        gThreadsList.append(t)

    #@函数介绍: 主函数入口
    #@返回值: 无
    #@data: 20180801
    def stopTask(self):
        global gThreadsList
        
        for t in gThreadsList:
            stop_thread(t)
        
        #清空gThreadsList
        gThreadsList = []
        
    def threadNumSet(self):
        global gMaxThreadNum
        gMaxThreadNum = self.spinBox_maxThreadNum.value()
        printStr('设置参数->线程个数:%s'%gMaxThreadNum)
        
        
         #@函数介绍:接收信号str的信号槽   
    #@返回值: 无
    #@data: 20180803
    def outputWritten(self,  text):
      
        self.textEditLog.setReadOnly(True)
        cursor = self.textEditLog.textCursor()  
        cursor.movePosition(QTextCursor.End)  
        cursor.insertText(text)  
        self.textEditLog.setTextCursor(cursor)  
        self.textEditLog.ensureCursorVisible()   
          
        
if __name__  =="__main__":
    app = QApplication(sys.argv)
    mainHandle = mainForm()
    mainHandle.show()
    sys.exit(app.exec())

ui_main.py:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'main.ui'
#
# Created by: PyQt5 UI code generator 5.9
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(815, 588)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget_fullInterface = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget_fullInterface.setEnabled(True)
        self.tabWidget_fullInterface.setGeometry(QtCore.QRect(20, 0, 841, 561))
        self.tabWidget_fullInterface.setStyleSheet("font: 12pt \"Arial\";")
        self.tabWidget_fullInterface.setObjectName("tabWidget_fullInterface")
        self.tab_startInterface = QtWidgets.QWidget()
        self.tab_startInterface.setObjectName("tab_startInterface")
        self.pushButton_startRun = QtWidgets.QPushButton(self.tab_startInterface)
        self.pushButton_startRun.setGeometry(QtCore.QRect(90, 430, 131, 51))
        self.pushButton_startRun.setStyleSheet("font: 87 14pt \"Arial\";color: white;background-color: rgb(218,181,150)")
        self.pushButton_startRun.setObjectName("pushButton_startRun")
        self.label_37 = QtWidgets.QLabel(self.tab_startInterface)
        self.label_37.setGeometry(QtCore.QRect(40, 395, 81, 21))
        self.label_37.setStyleSheet("color:rgb(255, 0, 0)")
        self.label_37.setObjectName("label_37")
        self.line_5 = QtWidgets.QFrame(self.tab_startInterface)
        self.line_5.setGeometry(QtCore.QRect(10, 485, 821, 41))
        self.line_5.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_5.setObjectName("line_5")
        self.line_7 = QtWidgets.QFrame(self.tab_startInterface)
        self.line_7.setGeometry(QtCore.QRect(120, 390, 711, 31))
        self.line_7.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_7.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_7.setObjectName("line_7")
        self.pushButton_stopRun = QtWidgets.QPushButton(self.tab_startInterface)
        self.pushButton_stopRun.setGeometry(QtCore.QRect(290, 430, 131, 51))
        self.pushButton_stopRun.setStyleSheet("font: 87 14pt \"Arial\";color: white;background-color: rgb(218,181,150)")
        self.pushButton_stopRun.setObjectName("pushButton_stopRun")
        self.line_6 = QtWidgets.QFrame(self.tab_startInterface)
        self.line_6.setGeometry(QtCore.QRect(-20, 405, 61, 101))
        self.line_6.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_6.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_6.setObjectName("line_6")
        self.line_8 = QtWidgets.QFrame(self.tab_startInterface)
        self.line_8.setGeometry(QtCore.QRect(10, 395, 31, 20))
        self.line_8.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_8.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_8.setObjectName("line_8")
        self.line_11 = QtWidgets.QFrame(self.tab_startInterface)
        self.line_11.setGeometry(QtCore.QRect(820, 410, 20, 101))
        self.line_11.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_11.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_11.setObjectName("line_11")
        self.spinBox_maxThreadNum = QtWidgets.QSpinBox(self.tab_startInterface)
        self.spinBox_maxThreadNum.setGeometry(QtCore.QRect(670, 440, 61, 22))
        self.spinBox_maxThreadNum.setMinimum(1)
        self.spinBox_maxThreadNum.setMaximum(10)
        self.spinBox_maxThreadNum.setProperty("value", 3)
        self.spinBox_maxThreadNum.setObjectName("spinBox_maxThreadNum")
        self.label_41 = QtWidgets.QLabel(self.tab_startInterface)
        self.label_41.setGeometry(QtCore.QRect(580, 440, 81, 21))
        self.label_41.setObjectName("label_41")
        self.textEditLog = QtWidgets.QTextEdit(self.tab_startInterface)
        self.textEditLog.setGeometry(QtCore.QRect(0, 10, 781, 371))
        self.textEditLog.setObjectName("textEditLog")
        self.tabWidget_fullInterface.addTab(self.tab_startInterface, "")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 815, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget_fullInterface.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "抖音短视频下载"))
        self.pushButton_startRun.setText(_translate("MainWindow", "开始运行"))
        self.label_37.setText(_translate("MainWindow", "运行控制"))
        self.pushButton_stopRun.setText(_translate("MainWindow", "停止运行"))
        self.label_41.setText(_translate("MainWindow", "线程个数"))
        self.tabWidget_fullInterface.setTabText(self.tabWidget_fullInterface.indexOf(self.tab_startInterface), _translate("MainWindow", "启动界面"))

 douyin.py:

# -*- coding:utf-8 -*-
from splinter.driver.webdriver.chrome import Options, Chrome
from splinter.browser import Browser
from contextlib import closing
import requests, json, time, re, os, sys

class douyin():
    def __init__(self):
        pass
    """
    视频下载
    Parameters:
        video_url: 带水印的视频地址
        video_name: 视频名
    Returns:
        无
    """
    def video_downloader(self,  video_url, video_name=r'douyinsss.mp4'):
    
        size = 0
        headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.3.2.1000 Chrome/30.0.1599.101 Safari/537.36"}
        try:
           with closing(requests.get(video_url, headers = headers,  stream=True, verify = False)) as response:
                chunk_size = 1024
                #print(response.text)
                content_size = int(response.headers['content-length']) 
                if response.status_code == 200:
                    sys.stdout.write('  [文件大小]:%0.2f MB\n' % (content_size / chunk_size / 1024))
                    """
                    with open(video_name, 'ab') as file:
                        file.write(response.content)
                        file.flush()
                        print('receive data,file size : %d   total size:%d' % (os.path.getsize(video_name), content_size))
                    """
                    with open(video_name, "wb") as file:  
                        for data in response.iter_content(chunk_size = chunk_size):
                            file.write(data)
                            size += len(data)
                            file.flush()
        
                            #sys.stdout.write('  [下载进度]:%.2f%%' % float(size / content_size * 100) + '\r')
                            #sys.stdout.flush()
                    print('视频下载完了...')
        except Exception as e:
            print(e)
            print('下载出错啦.....')
       
    """
    视频下载地址获取
    Parameters:
        video_url: 带水印的视频地址
    Returns:
        视频下载链接,视频名字
    """
    def downloadUrlGet(self,  video_url):
        name = ''
        downloadUrl = ''
        headers = {
                'Proxy-Connection':'keep-alive', 
                'Host': 'v.douyin.com', 
                'Upgrade-Insecure-Requests':'1', 
                'Accept-Encoding': 'gzip, deflate', 
                'Accept-Language': 'zh-CN,zh;q=0.9', 
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36", 
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'
            }
        req = requests.get(url = video_url, headers = headers,  verify = False)
        newUrl = req.url
        
        #print(req.text)
        print('newUrl:%s'%newUrl)
        print(req.history)
        #302重定向后的请求
        headers = {
                'Proxy-Connection':'keep-alive', 
                'Host': 'www.iesdouyin.com', 
                'Upgrade-Insecure-Requests':'1', 
                'Accept-Encoding': 'gzip, deflate', 
                'Accept-Language': 'zh-CN,zh;q=0.9', 
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36", 
                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8'
            }
        req = requests.get(url = newUrl, headers = headers,  verify = False)
        reply = req.text
        #print(reply)
        p = reply.find('playAddr: "') +   len('playAddr: "')
        downloadUrl = reply[p: reply.find('"',  p)]
        print('downloadUrl:%s'%downloadUrl)
        p = reply.find('"name nowrap">') + len('"name nowrap">')
        name = reply[p: reply.find('<',  p)]
        print(name)
        return downloadUrl,  name


url = 'http://v.douyin.com/dU2Dsn/'
handel = douyin()
downloadUrl,  name = handel.downloadUrlGet(url)
handel.video_downloader(url, name)


"""
def do_load_media(url, path):
    try:
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.3.2.1000 Chrome/30.0.1599.101 Safari/537.36"}
        pre_content_length = 0
        # 循环接收视频数据
        while True:
            # 若文件已经存在,则断点续传,设置接收来需接收数据的位置
            if os.path.exists(path):
                headers['Range'] = 'bytes=%d-' % os.path.getsize(path)
            res = requests.get(url, stream=True, headers=headers)

            content_length = int(res.headers['content-length'])
            print(content_length)
            # 若当前报文长度小于前次报文长度,或者已接收文件等于当前报文长度,则可以认为视频接收完成
            if content_length < pre_content_length or (
                    os.path.exists(path) and os.path.getsize(path) == content_length):
                break
            pre_content_length = content_length

            # 写入收到的视频数据
            with open(path, 'ab') as file:
                file.write(res.content)
                file.flush()
                print('receive data,file size : %d   total size:%d' % (os.path.getsize(path), content_length))
    except Exception as e:
        print(e)


downloadUrl = 'http://www.gifshow.com/s/mDg7eWq9'
path = r'test.mp4'
do_load_media(download_url, path)
"""

这是我自己写的一个工具库,tools.py:

# -*- coding:utf-8 -*-

import requests
import json
import random
import datetime
import os
import time
import hashlib
import string
import base64
import execjs

import re

gIpLink = ''
gDialName = ''
gDialAccount = ''
gDialPasswd =''
openDebug = False
gIpList = []

gStatusCode = ''
gUsername = ''

header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                        'AppleWebKit/537.36 (KHTML, like Gecko) '
                        'Chrome/64.0.3282.186 Safari/537.36'}
	
def  dict2proxy(dic):
    url = dic['type'] + '://' + dic['ip']  + ':' + str(dic['port'])
    return {'http':url,  'https':url}


#@函数介绍: 检验Ip是否是好的
#@返回值: ip是好的/坏的: True/false
#@data: 20180801
def check_ip(ipDict):
    
    try:
        proxie = dict2proxy(ipDict)
        #printStr(proxie)
        if ipDict['type'] == 'https':
            url = 'https://www.ipip.net/'
        else:
            #url = "http://www.discuz.net/forum.php"
            url = 'http://www.lvye.cn/'
        r = requests.get(url, headers=header, proxies=proxie, timeout=15)
        r.raise_for_status()
        isOk =  True
    except Exception as e:
        printStr('经过测试IP无效...') 
        isOk =  False
    else:
        printStrDebug('经过测试,IP有效...')
        #printStr(ipDict)
    return isOk

        
#@函数介绍: 获取一个可用的代理Ip
#@返回值: 可用的代理Ip
#@data: 20180801
# freeProxieIpGet()
def getProxieIp():
    cycleFlag = True
    count = 0
    #打开代理ip文件
    with  open('数据文件夹\proxies.json',  'r') as file:
        jsonStr = file.read()
    dataList = json.loads(jsonStr)    #data 是个list
    
    listLen = len(dataList)
    maxCount = listLen +  5 
    if listLen == 0:
        printStr('proxies.json文件中没有可用ip....')
        return 'null'
    printStr('可用ip个数:%d'%listLen)
    #读取dict格式的ip
    while cycleFlag == True:
        index = random.randint(0,  listLen-1)   #随机生成一个Ip
        printStr('随机生成第%d个ip'%index)
        ipDict = dataList[index]
        flag = check_ip(ipDict)
        if flag == True:
           cycleFlag = False
        if count > maxCount:    #如果循环次数超过maxCount次,则暂停循环
            cycleFlag = False
            ipDict = 'null'
        count = count + 1

    return ipDict


#@函数介绍: 格式化打印输出
#@返回值: 无
#@data: 20180807
def printStr(str):
    nowTime=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')#现在
    print('[%s]>>>>%s'%(nowTime,  str))

def printStrDebug(str):
    if openDebug == True:
        nowTime=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')#现在
        print('[%s]>>>>%s'%(nowTime,  str))
    else:
        pass

#@函数介绍: 检测代理IP地址 全局变量是否已经设置
#@返回值: True/False
#@data: 20180810 stefan1240
def payPorxieIpSettingCheck():
    global gIpLink
    if gIpLink == '':
        return False
    else:
        return True
        
#功能未完成
def payPorxieIpLinkMake(httpType):
    if gIpLink == '':
        printStr('IP代理链接为空...')
        return 'null'

#@函数介绍: 付费代理Ip池清零
#@返回值:无
#@data: 20180813,stefan1240
def payProxieIpsClear():
    global gIpList
    gIpList = []
    return 
    
#@函数介绍: 付费代理Ip池设定
#@返回值:无
#@data: 20180809,stefan1240
def payProxieIpsUpdate(httpType):
    global gIpList
    global gIpLink
    #初始值判断
    if gIpLink == '':
        return 
    #判断是哪个平台的代理IP
    if 'zhimacangku' in gIpLink:   #
        #判断是需要哪种代理ip
        if httpType == 'http':
            if 'port=2' in gIpLink:  #port  代表IP协议(1:HTTP 2:SOCK5 11:HTTPS )
                gIpLink = gIpLink.replace('port=2',  'port=1')
            if 'port=11' in gIpLink:
                gIpLink.replace('port=3',  'port=1')
        else: #https
            if 'port=1' in gIpLink:  #port  代表IP协议(1:HTTP 2:SOCK5 11:HTTPS )
                gIpLink.replace('port=1',  'port=2')
            if 'port=11' in gIpLink:
                gIpLink.replace('port=11',  'port=2')
        #修改返回IP的数据格式,这里使用txt
        if 'type=2' in gIpLink:    #type数据格式(1TXT 2JSON 3html)
            gIpLink = gIpLink.replace('type=2', 'type=1')
        if 'type=3' in gIpLink:    
            gIpLink.replace('type=3', 'type=1')
        if 'num=1' in gIpLink:   #一次性获取的IP个数设置为20
            gIpLink = gIpLink.replace('num=1',  'num=20')
        #获取一批量ip,并存于全局变量
        r = requests.get(gIpLink)
        ipStr = r.text
        #IP数据处理
        if  'false' in ipStr:    #获取太频繁
            printStr('代理平台返回结果:%s'%ipStr)
            return 
        elif 'balde' in ipStr:    #欠费了,直接返回False
            printStr('代理IP欠费了,请到相应平台续费')
            return
        else:
            tmpIpList = ipStr.splitlines()   #按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。
            for strs in tmpIpList:
                tmpIpDict = {}
                if strs.count(':') >1:
                    printStr('IP代理格式设置不正确,请核对.')
                    return
                if ":" not in strs:
                    printStr('可能是IP代理格式设置不正确,返回结果请设置为txt格式.')
                    return
                ip,  port = strs.split(':')
                tmpIpDict['ip'] = ip
                tmpIpDict['port'] = port
                tmpIpDict['type'] = httpType
                #printStrDebug(tmpIpDict)
                gIpList.append(tmpIpDict)
    elif 'xdaili' in gIpLink:  #讯代理    可以直接按照以下格式组装所需的API链接:http://api.xdaili.cn/xdaili-api/greatRecharge/getGreatIp?spiderId=xx&orderno=xx&returnType=2&count=xx
        if 'spiderId' in gIpLink:
            p = gIpLink.find('spiderId') + len('spiderId=')
            spiderId = gIpLink[p: gIpLink.find('&',  p)]      
        if 'orderno' in gIpLink:
            p = gIpLink.find('orderno') + len('orderno=')
            orderno = gIpLink[p: gIpLink.find('&',  p)]      
        fullLink = 'http://api.xdaili.cn/xdaili-api/greatRecharge/getGreatIp?spiderId='+spiderId+'&orderno='+ orderno+'&returnType=1&count=15'
        #获取一批量ip,并存于全局变量
        r = requests.get(fullLink)
        ipStr = r.text
        if 'ERRORCODE' in ipStr:
            p = gIpLink.find('ERRORCODE') + len('ERRORCODE":"')
            replyCode = gIpLink[p: gIpLink.find('"',  p)]      
            if (replyCode == '10036' )| (replyCode == '10038') |(replyCode =='10055'):
                printStr('提取代理IP太频繁,请按规定频率提取!')
            if replyCode == '10032':
                printStr('今日代理IP提取已达上限,请隔日提取或额外购买')
        else:
            tmpIpList = ipStr.splitlines()   #按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。
            for strs in tmpIpList:
                tmpIpDict = {}
                if strs.count(':') >1:
                    printStr('IP代理格式设置不正确,请核对.')
                    return
                if ":" not in strs:
                    printStr('可能是IP代理格式设置不正确,返回结果请设置为txt格式.')
                    return
                ip,  port = strs.split(':')
                tmpIpDict['ip'] = ip
                tmpIpDict['port'] = port
                tmpIpDict['type'] = httpType
                #printStrDebug(tmpIpDict)
                gIpList.append(tmpIpDict)
    
    else:  #别的类型平台
        #获取一批量ip,并存于全局变量
        r = requests.get(gIpLink)
        ipStr = r.text
        printStr(ipStr)
        #IP数据处理
        if  'false' in ipStr:    #获取太频繁
            printStr('获取IP太过频繁,平台给予拒绝...')
            time.sleep(2)
            r = requests.get(gIpLink)
            ipStr = r.text
        elif 'balde' in ipStr:    #欠费了,直接返回False
            printStr('代理IP欠费了,请到相应平台续费')
            return
        else:
            tmpIpDict = {}
            tmpIpList = ipStr.splitlines()   #按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。
            for strs in tmpIpList:
                if ":" not in strs:
                    printStr('IP代理格式设置不正确,返回结果请设置为txt格式.')
                    return
                ip,  port = strs.split(':')
                tmpIpDict['ip'] = ip
                tmpIpDict['port'] = port
                tmpIpDict['type'] = httpType

                gIpList.append(tmpIpDict)
    #printStrDebug('gIpList:%s'%gIpList)
    return 

#@函数介绍: 付费代理Ip获取
#@返回值: isGetIpSucess,  tmpIpDict
#@data: 20180809,stefan1240
def payProxieIpGet(httpType):
    isGetIpSucess = False
    tmpIpDict = {}
    ret = False

    while ret == False:
        if len(gIpList) == 0:
            payProxieIpsUpdate(httpType)
        if len(gIpList) == 0:
            isGetIpSucess = False
            break
        tmpIpDict = gIpList.pop()  #弹出一个IP,
        ret = check_ip(tmpIpDict)
        if ret == True:
            isGetIpSucess = True
        
    return isGetIpSucess,  tmpIpDict
    

#@函数介绍: 付费代理Ip获取
#@返回值: 返回一个可用的dictIp
#@data: 20180809,stefan1240
def payProxieIpGet_old(httpType):
    global gIpLink
    isSucess = False
    isGetIpSucess = True
    iCirclMax = 50   #最多循环5次获取
    circleIndex = 0
    gIpLink = 'http://webapi.http.zhimacangku.com/getip?num=1&type=1&pro=&city=0&yys=0&port=1&pack=25657&ts=0&ys=0&cs=0&lb=1&sb=0&pb=4&mr=1&regions='
    """  Ip的格式是这样的:
    http://webapi.http.zhimacangku.com/getip?num=1&type=1&pro=&city=0&yys=0&port=1&time=1&ts=0&ys=0&cs=0&lb=1&sb=0&pb=4&mr=1&regions=
    """
    ipDict = {}
        
    while isSucess == False:
        if circleIndex > iCirclMax:
            isGetIpSucess = False
            break;
        circleIndex = circleIndex + 1
        
        r = requests.get(gIpLink)
        ipStr = r.text
        printStr('get:%s'%ipStr)
        if  'false' in ipStr:    #获取太频繁
            isSucess = False
            time.sleep(1)
        elif 'balde' in ipStr:    #欠费了,直接返回False
            isGetIpSucess = False
            break
        else:
            ipStr = ipStr.strip('\r\n')
            ip,  port = ipStr.split(':')
            ipDict['ip'] = ip
            ipDict['port'] = port
            ipDict['type'] = httpType
            #ret = True
            ret = check_ip(ipDict)
            if ret == True:
                isSucess = True
            else:
                isSucess = False
    return isGetIpSucess,  ipDict
    
#@函数介绍: 付费IP代理链接设置
#@返回值: 成功/失败: True/False
#@data: 20180809, stefan1240
def payPorxieIplinkSet(ipAddrsLink):
    global gIpLink
    if ipAddrsLink == '':
        printStr('未输入代理IP链接,请输入有效的IP代理链接...')
        return False
    elif not ipAddrsLink.startswith(('http://', 'https://')):
        printStr('你输入的IP代理链接格式不对,请检查一下格式...')
        return False
    else:
        gIpLink = ipAddrsLink
    return True
    
    
#@函数介绍: 宽带参数设置
#@返回值: 成功/失败: True/False
#@data: 20180809, stefan1240
def dialParaSet(dialName, dialAccount,  dialPasswd):
    global gDialName 
    global gDialAccount
    global gDialPasswd
    gDialName = dialName
    gDialAccount = dialAccount
    gDialPasswd = dialPasswd
    return True

#@函数介绍: 宽带连接
#@返回值: 成功/失败: True/False
#@data: 20180809, stefan1240
def dialConnect():
    global gDialName 
    global gDialAccount
    global gDialPasswd
    if gDialName == '':
        return False
    cmdStr = 'rasdial %s %s %s'%(gDialName,  gDialAccount,  gDialPasswd)
    ret = os.system(cmdStr)
    if ret == 0:
        isSucess = True
    else:
        isSucess = False
        printStr('拨号失败,错误代码:%s'%ret)
    return isSucess
    
#@函数介绍: 宽带断开
#@返回值: 成功/失败: True/False
#@data: 20180809, stefan1240
def dialDisconnect():
    global gDialName
    cmdStr = 'rasdial %s /disconnect'%gDialName
    ret = os.system(cmdStr)
    if ret == 0:
        isSucess = True
    else:
        isSucess = False
    return isSucess

#@函数介绍: 宽带重连
#@返回值: 无
#@data: 20180809, stefan1240
def dialReconnect():
    ret = dialDisconnect()
    if ret == True:
        time.sleep(3)
        dialConnect()
        time.sleep(1)
      
#@函数介绍: 随机生成n个中文字符
#@返回值: 中文字符串
#@data: 20180814, stefan1240
def randomChineseGet(num):
    strs = ''
    for i in range(num):
        val = random.randint(0x4e00, 0x9fbf)
        strs = strs + chr(val)
    return strs
   
def randomChar(num):
       return ''.join(random.choice(string.ascii_letters) for x in range(num))
       
def randomInt(num):
    strs = ''
    for i in range(num):
       number = random.randint(1, 9)
       strs = strs+ str(number)
    return strs

#@函数介绍: md5加密
#@输入: 字符串型
#@返回值: md5加密后的字符串
def genearteMD5(strs):
    # 创建md5对象
    hl = hashlib.md5()

    # Tips
    # 此处必须声明encode
    # 否则报错为:hl.update(str)    Unicode-objects must be encoded before hashing
    hl.update(strs.encode(encoding='utf-8'))

    return hl.hexdigest()

#@函数介绍: sh256加密
#@输入: 字符串型
#@返回值: sh256加密后的字符串
def genearteSH256(strs):
    sha256 = hashlib.sha256()
    sha256.update(strs.encode('utf-8'))
    return sha256.hexdigest()
   
#@函数介绍: base64加密
#@输入: 字符串型
#@返回值: base64加密后的字符
def genearteBase64(strs):
    strEncode =  base64.b64encode(strs.encode('utf-8'))
    return strEncode.decode()

#@函数介绍: 新浪web加密某个字段需要调用JS代码
#@输入: servertime,  nonce,  passwd,  pubkey
#@返回值: base64加密后的字符
def xinlanJsEcode(servertime,  nonce,  passwd,  pubkey):
    xinlanJsStr = xinlanJsStrGet()
    handle = execjs.compile(xinlanJsStr)
    ret = handle.call('Getsp',  servertime,  nonce,  passwd,  pubkey)
    return ret
#@data: 20180814, stefan1240
#dic = {'ip':'182.244.109.222', 'port':'4230', 'type':'https'}
#check_ip(dic)

#------------------------易游对接相关API---------------------------------------------------------------
#@函数介绍:从配置文件获取登录用户信息相关
#@输入值:  
#@返回值: gStatusCode, gUsername
#@data: 201808022
def  loingAccountInfoGet():
    global gStatusCode
    global gUsername
    
    file = open('系统文件(勿动)\para.ini',  'r')
    for line in file.readlines():
        line = line.strip('\n')
        if '<registerInfo>' in line:
            para = re.findall("<registerInfo>(.+?)<registerInfo>",  line)
            gUsername, passwd = para[0].split(':')
        if '<retCodeInfo>' in line:
            para = re.findall("<retCodeInfo>(.+?)<retCodeInfo>",  line)
            gStatusCode = para[0]
    file.close()
#@函数介绍:获取用户状态
#@输入值:  statusCode:登录成功后返回的状态码,  userName:用户名
#@返回值: 成功的返回1或者错误代码,代码含义:http://dev.eydata.net/webapi/errorlist
#@data: 201808021
def checkUserStatus():
    global gStatusCode
    global gUsername
    
    url = 'https://w.eydata.net/aec651134b90f1ab'
    data = {
        "StatusCode": gStatusCode,
        "UserName": gUsername
    }
    r = requests.post(url,  data)
    return r.text

#@函数介绍:退出接口
#@输入值: 
#@返回值: 成功的返回1或者错误代码,代码含义:http://dev.eydata.net/webapi/errorlist
#@data: 201808021
def logOut():
    statusCode = ''
    userName = ''
    
    file = open('系统文件(勿动)\para.ini',  'r')
    for line in file.readlines():
        line = line.strip('\n')
        if '<registerInfo>' in line:
            para = re.findall("<registerInfo>(.+?)<registerInfo>",  line)
            userName, passwd = para[0].split(':')
        if '<retCodeInfo>' in line:
            para = re.findall("<retCodeInfo>(.+?)<retCodeInfo>",  line)
            statusCode = para[0]
    file.close()
    
    url = 'https://w.eydata.net/a8a66a6329265b37'
    data = {
        "StatusCode": statusCode,
        "UserName": userName
    }
    r = requests.post(url,  data)
    return r.text

#-----------------------------------------------------------------------------------
#@函数介绍:把代理IP链接写入到配置文件
#@输入值:  statusCode:登录成功后返回的状态码,  userName:用户名
#@返回值: 成功的返回1或者错误代码,代码含义:http://dev.eydata.net/webapi/errorlist
#@data: 201808021
def writeIpLinkIntoFile():
    global gIpLink
    needWrite = True
    if gIpLink == '':
        printStr('代理IP链接为空,停止写入到配置文件...')
    ipAddresLink = gIpLink
    #写入配置文件
    strs = '<IplinkInfo>%s<IplinkInfo>\n'%ipAddresLink
    #使用w模式会将原本的文件清空/覆盖。可以先用读(r)的方式打开,写到内存中,然后再用写(w)的方式打开。
    with open('系统文件(勿动)\para.ini',  'r' ,encoding="utf-8") as file:
        lines = file.readlines()
    with open('系统文件(勿动)\para.ini',  'w',encoding="utf-8") as file:
        for line in lines:   #替换
            if '<IplinkInfo>' in line:
                s = line.replace(line,   strs)
                file.write(s)
                needWrite = False
            else:
                file.write(line)
    printStrDebug('needWrite=%s'%needWrite)
    if needWrite == True:   #首次写入
        with open('系统文件(勿动)\para.ini',  'a+',encoding="utf-8") as file:
            file.write(strs)
"""
articleBody ='hello'
articleTitle = 'hello'
deviceid = 'ab56b4d92b40713acc5af89985d4b786'
uid = '6611942773'


str1 ="act=1&allow_comment=1&allow_repost=1&appid=2&appver=3.0.2&article_body=" + articleBody + "&article_title="+articleTitle 
str2 = "&chno=515_112&class_id=0&deviceid=" + deviceid + "&is_secret=0&is_to_weibo=0&login_uid=" +uid 
str3 = "&signkey=e3eb41c951f264a6daa16b6e4367e829&sort_id=117"
body = str1 + str2 + str3

sign = genearteSH256(body)
print(sign)

"""

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值