首页 > 技术文章 > Python使用技巧2

hanease 2022-03-17 09:17 原文

python url网址拼接

在做爬虫中,经常会遇到需要把一个域名和网址路径进行拼接,在开发时一时没想到方法,特此记录下来。

利用parse.urljoin方法进行网址拼接

from urllib import  parse

print(parse.urljoin("http://www.chenxm.cc", "abc.html"))
print(parse.urljoin("http://www.chenxm.cc/", "/../../abc.html"))
print(parse.urljoin("http://www.chenxm.cc/post", "./../../abc.html"))

>>> http://www.chenxm.cc/abc.html
>>> http://www.chenxm.cc/abc.html
>>> http://www.chenxm.cc/abc.html

python3 获取当前运行函数名称和类方法名称

如何获取当前运行函数(或方法)的名称呢?

背景:python3.8

第一种方法:

利用__name__获取当前方法名称

def create():
    print("hello word")
    
print(create.__name__)
>>> create

第二种方法:利用sys获取当前方法名称

import sys
def create():
    print(f"当前方法名:{sys._getframe().f_code.co_name}")
    
create()
>>> 当前方法名:create

获取类的名称以及当前方面名称

import sys
class Object():

    def filter(self,*args, **kwargs):
        return Filter(*args, **kwargs)


    def create(self):
        print(f'当前类名称:{self.__class__.__name__}')
        print(f"当前方法名:{sys._getframe().f_code.co_name}")
        

o=Object()
o.create()
>>> 当前类名称:Object
>>> 当前方法名:create

python 字符串转换成字节,字节转换成十六进制

 

python 字符串转换成字节,字节转换成十六进制

背景:

python3.8

s="aaabbbccc"
# 将字符串转换字节
s_bytes=s.encode()
print(f'数据类型:{type(s_bytes)},输出数据:{s_bytes}')
>>> 数据类型:<class 'bytes'>,输出数据:b'aaabbbccc'

# 将十进制字符串转换为十六进制字符串
h_str=s_bytes.hex()
print(f'数据类型:{type(h_str)},输出数据:{h_str}')
>>> 数据类型:<class 'str'>,输出数据:616161626262636363
print(binascii.hexlify(s_bytes))
>>> 616161626262636363

# 将十六进制字符串转换成字节
h_bytes=bytes.fromhex(h_str)
print(f'数据类型:{type(h_bytes)},输出数据:{h_bytes}')
>>> 数据类型:<class 'bytes'>,输出数据:aaabbbccc'
print(binascii.unhexlify(h_str))
>>> aaabbbccc

print(bytes([0,1,2,3,4,5]).hex())
>>> 000102030405

print(bytes.fromhex('000102030405'))
>>> b'\x00\x01\x02\x03\x04\x05'

print(b'abcde'.hex())
>>> 6162636465

print(bytes.fromhex('6162636465'))
>>> b'abcde'

python 把pdf转成图片文件

Wand是ctypes基于Python 的简单ImageMagick绑定。

1. 安装wand包:

pip install Wand

文档网址:http://docs.wand-py.org/en/0.6.1/

2. 安装ImageMagick

window电脑需要预装一个软件:http://docs.wand-py.org/en/latest/guide/install.html#install-imagemagick-on-windows

其他系统ImageMagick请参考文档:http://docs.wand-py.org/en/latest/guide/install.htm

注意:在选择ImageMagick32位还是64位,这个需要和python的位数一致。参考文章:查看python是32位还是64位

2.1 安装时需要注意勾选Install development headers and libraries for C and C++ 。

windows-setup.png

2.2 安装后设置MAGICK_HOME环境变量,值为imagemagick的安装路径,并将安装路径加入path。

环境变量设置流程:我的电脑(右键我的电脑)→属性→高级系统设置→环境变量→新建

TIM截图20200518113847.png

3. 安装ghostscript

下载ghostscript时选择AGPL release,注意32位还是64位。

把pdf转换成图片样例:

from wand.image import Image as wi

pdf=wi(filename='文件.pdf',resolution=300)
pdf_image=pdf.convert('jpeg')
i=1
for img in pdf_image.sequence:
    page=wi(image=img)
    page.save(finename=f'{i}.jpg')
    i+=1

注意:上述把pdf转换成图片代码比较简单,但是只能处理页数较少的pdf还行,如果页数太多会卡住。建议使用pyPDF2分割pdf然后转换再转换成图片。

python python-pptx对pptx文件读取示例

python  python-pptx对pptx文件读取示例,以下是如何使用pptx.Presentation()的代码示例。

python-pptx安装:

pip install python-pptx

官网文档:

https://python-pptx.readthedocs.io/en/latest/index.html

代码:

from pptx import Presentation

# 打开pptx文件
prs=Presentation(r'C:\Users\admin\Desktop\test\演示文稿1.pptx')

# 遍历每一页的幻灯片
for slide in prs.slides:
    # 遍历每一个幻灯片的形状
    for shape in slide.shapes:
        # 判断该形状是否是一个文字框架
        if not shape.has_text_frame:
            continue

        for paragraph in shape.text_frame.paragraphs:
            # 拼接文字
            print(''.join(run.text for run in paragraph.runs))

参考文章:

https://www.programcreek.com/python/example/105890/pptx.Presentation

python 读取word文件 docx2txt和textract

python 读取word文件 docx2txt和textract

docx2txt安装

pip install docx2txt

docx2txt代码:

import docx2txt

my_text=docx2txt.process(r'C:\test\疫情防控思政大课观后感.docx')


print(my_text)

注意:docx2tx只支持word后缀为docx,不支持doc

如果需要支持doc,建议使用模块:textract

textract安装:

pip install textract

官方文档:https://textract.readthedocs.io/en/stable/

使用代码:

import textract

text = textract.process("path/to/file.extension")

python 复杂递归问题 汉诺塔

汉诺塔问题是法国数学家Edouard Lucas于1883年,根据传说提出来的。

传说在一个印度教寺庙里,有3根柱子,其中一根套着64个有小到大的黄金盘片,僧侣们的任务就是把这一叠黄建盘从一根柱子搬到另一根,但有两个规则:

  • 一次只能搬一个板子

  • 大盘子不能叠在小盘子上

神的旨意说一旦这些盘子完成迁移,寺庙将会坍塌,世界将会毁灭。

递归逻辑

 将盘片塔从开始柱,经由中间柱,移动到目标柱

  • 将上层N-1个盘片的盘片塔,从开始柱,经由目标柱,移动到中间柱;

  • 将第N个(最大的)盘片,从开始柱,移动到目标柱;

  • 最后将放置在中间柱的N-1个盘片的盘片塔,经由开始柱,移动到目标柱。

基本结束条件,也就是最小规模问题:

  • 一个盘片的移动

代码:

def move_tower(height,from_pole,with_pole,to_pole):
    if height>=1:
        move_tower(height-1,from_pole,to_pole,with_pole)
        move_disk(height,from_pole,to_pole)
        move_tower(height-1,with_pole,from_pole,to_pole)


def move_disk(disk,from_pole,to_pole):
    print(f'moving disk {disk} from {from_pole} to {to_pole}')


move_tower(3,'#1','#2','#3')

输出结果

moving disk 1 from #1 to #3
moving disk 2 from #1 to #2
moving disk 1 from #3 to #2
moving disk 3 from #1 to #3
moving disk 1 from #2 to #1
moving disk 2 from #2 to #3
moving disk 1 from #1 to #3

调整python中的递归深度限制

调整python中的递归深度限制

import sys

# 获取当前最大递归深度
sys.getrecursionlimit()
>>> 1000

# 设置当前你最大递归深度
sys.setrecursionlimit(3000)
sys.getrecursionlimit()
>>> 3000

递归 数列求和

递归三大定律

  1. 递归算法必须有一个基本结束条件(最小规模问题的直接解决)

  2. 递归算法必须能改变状态向基本结束条件演进(减少问题规模)

  3. 递归算法必须调用自身(解决减少了规模的相同的问题)

递归 数列求和

def listSum(li):
    if len(li)==1:
        return li[0] #最小规模
    return li[0]+listSum(li[1:]) # 调用自身


print(listSum([1,2,3]))
print(listSum([1,2,3,4,5]))
print(listSum([1,2,3,4,5,6,7]))

输出结果:

6
13
28

python 读取指定文件夹下所有文件名

递归获取指定文件下的所有文件的绝对路径

import os


def get_files(dir_path, file_names=[]):
    """获取某路径下所有文件列表
    :type dir_path: str
    :param dir_path: 真实存在的路径
    :type file_names: list
    :param file_names: 文件名保存列表,依赖调用端构造传递
    :return:
    """

    # 绝对路径
    if not os.path.isabs(dir_path):
        dir_path = os.path.abspath(dir_path)

    for (path_name, dirs, files) in os.walk(dir_path):

        if files:  # 文件,则添加进列表
            for f in files:
                file_names.append(os.path.join(path_name, f))
        if dirs:  # 目录,递归获取
            for dir_ in dirs:
                get_files(os.path.join(path_name, dir_), file_names)
        else:
            return file_names
            
file_li=get_files(r'C:\Users\pala\Downloads')
print("-"*100)
print(len(file_li),file_li)

python 更快创建一个随机整数的列表

python 如何更快创建一个随机整数的列表?

普通方法(最慢):

import random

li=[random.randint(0, 1000) for r in xrange(10000)]

利用random.sample(中等):

import random

random.sample(range(10000), 10000)

利用numpy.random(最快):

import numpy.random as nprnd
nprnd.randint(1000, size=10000)

测试结果如下:

import numpy.random as nprnd
import timeit

t1 = timeit.Timer('[random.randint(0, 1000) for r in xrange(10000)]', 'import random') # v1

t2 = timeit.Timer('random.sample(range(10000), 10000)', 'import random') # v2

t3 = timeit.Timer('nprnd.randint(1000, size=10000)', 'import numpy.random as nprnd') # v3

print t1.timeit(1000)/1000
print t2.timeit(1000)/1000
print t3.timeit(1000)/100

具体时间如下:

0.0131397729926
0.00475841206447
0.00055090731109

python获取当前计算机的cpu数量

 

python获取当前计算机的cpu数量

import multiprocessing

print(multiprocessing.cpu_count())

>>> 16

selenium 实现上传图片/文件多种方法

个人在写脚本时遇到需要selenium来上传图片。

第一种方法:

一般比较简单的网站可以使用以下方法(只使用非常简单的网站):

browser.find_element_by_id("IdOfInputTypeFile").send_keys(os.getcwd()+"/image.png")

browser.find_element_by_xpath("IdOfInputTypeFile").send_keys(os.getcwd()+"/image.png")

第二种方法 使用pyautogui或者是autoit

import autoit

autoit.win_active("Open")
autoit.control_send("Open","Edit1",r"C:\Users\uu\Desktop\TestUpload.txt")
autoit.control_send("Open","Edit1","{ENTER}")

# 建议使用control_set_text 因为control_send会发送错误的文本
autoit.control_set_text("Open","Edit1",r"C:\Users\uu\Desktop\TestUpload.txt")

或者是

 

import autoit
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys

ActionChains(driver).move_to_element( driver.find_element_by_xpath("//path/to/upload/button")).click().perform()
handle = "[CLASS:#32770; TITLE:Open]"
autoit.win_wait(handle, 60)
autoit.control_set_text(handle, "Edit1", "\\file\\path")
autoit.control_click(handle, "Button1")

 

第三种方法 使用pywin32

import win32com.client

shell = win32com.client.Dispatch("WScript.Shell")   
shell.Sendkeys("C:\text.txt")  
shell.Sendkeys("~")

第二和第三种方法都有一点小问题时,就是当电脑在被使用时,会影响实际操作的结果。

python 判断年份是否为闰年

判断闰年的标准是:1、能整除4且不能整除100 2、能整除400

if year % 4 == and year % 100 != 0:
  print 'yes'
elif year % 400 == 0:
  print u"yes"
else:
  print u"no"

python并发编程--多进程模块 multiprocessing

由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。

multiprocessing包是Python中的多进程管理包。与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。

一、进程调用方法两种方法:

第一种代码示例:

from multiprocessing import Process
import time
def f(name):
    time.sleep(1)
    print('hello', name,time.ctime())
if __name__ == '__main__':
    p_list=[]
    for i in range(3):
        p = Process(target=f, args=('alvin',))
        p_list.append(p)
        p.start()
    for i in p_list:
        p.join()
    print('end')

第二种代码示例:

from multiprocessing import Process
import time
class MyProcess(Process):
    def __init__(self):
        super(MyProcess, self).__init__()
        #self.name = name
    def run(self):
        time.sleep(1)
        print ('hello', self.name,time.ctime())
if __name__ == '__main__':
    p_list=[]
    for i in range(3):
        p = MyProcess()
        p.start()
        p_list.append(p)
    for p in p_list:
        p.join()
    print('end')

显示单个进程的ID代码示例:

from multiprocessing import Process
import os
import time
def info(title):
  
    print("title:",title)
    print('parent process:', os.getppid())
    print('process id:', os.getpid())
def f(name):
    info('function f')
    print('hello', name)
if __name__ == '__main__':
    info('main process line')
    time.sleep(1)
    print("------------------")
    p = Process(target=info, args=('yuan',))
    p.start()
    p.join()

输出结果:

title: main process line
parent process: 8368        # 在pycharm中运行,所以该线程是pycharm
process id: 8756            # info 进程
------------------
title: yuan
parent process: 8756        # info创建的进程
process id: 4300

二、Process类

构造方法:

Process([group [, target [, name [, args [, kwargs]]]]])

group: 线程组,目前还没有实现,库引用中提示必须是None; 

target: 要执行的方法; 

name: 进程名; 

args/kwargs: 要传入方法的参数。

实例方法:

is_alive():返回进程是否在运行。

join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。

start():进程准备就绪,等待CPU调度

run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。

terminate():不管任务是否完成,立即停止工作进程

属性:

daemon:和线程的setDeamon功能一样

name:进程名字。

pid:进程号。

 

 

推荐阅读