解决cURL error 60: SSL certificate problem

今天在做本地环境开发阿里云短信验证时报错:cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)

解决办法

进入:https://curl.se/docs/caextract.html

下载最新版Cacert.pem
复制这个文件到php的安装目录下,如下图所示

打开php.ini文件,搜索curl.cainfo 去掉前面的#注释 填上该文件的绝对路径,如下图所示: 

*注意:如果按照上面这个方式还报错的可能就是openssl没有开启,php的openssl扩展需要开启 

调用Yii::getAlias与Yii::setAlias的用法

别名用来表示文件路径和URL,简化引用,避免在代码中编码一些绝对路径和URL。一个别名必须以‘@’字符开头,以区别于传统的文件路径和URL。
定义别名:调用Yii::setAlias()给文件路径或URL定义别名:
// 文件路径的别名
Yii::setAlias(‘@foo’, ‘/path/to/foo’);
// URL 的别名
Yii::setAlias(‘@bar’, ‘http://www.example.com’);
注意:别名所指向的文件路径或 URL 不一定是真实存在的文件或资源。
可以通过在一个别名后面加斜杠 / 和一至多个路径分段生成新别名(无需调用 Yii::setAlias())。我们把通过 Yii::setAlias() 定义的别名称为根别名,而用他们衍生出去的别名成为衍生别名。例如,@foo 就是根别名,而 @foo/bar/file.php 是一个衍生别名。
你还可以用别名去定义新别名(根别名与衍生别名均可):
Yii::setAlias(‘@foobar’, ‘@foo/bar’);
解析别名:调用Yii::getAlias解析别名到对应的文件路径或URL:如
// echo Yii::getAlias(‘@webroot’); // D:/path/yiibasic/web
// echo Yii::getAlias(‘@app’); // D:\path\yiibasic
// echo Yii::getAlias(‘@web’); // /yiibasic/web
注意:Yii::getAlias() 并不检查结果路径/URL 所指向的资源是否真实存在。
系统定义的路径别名:
@yii – BaseYii.php 文件所在的目录(也被称为框架安装目录)
@app – 当前运行的应用程序的基本路径 yii\base\Application::basePath
@common – 公共文件目录
@frontend – 前端web应用程序目录
@backend – 后端web应用程序目录
@console – 控制台目录
@runtime – 当前运行的应用的 yii\base\Application::runtimePath
@vendor – yii\base\Application::vendorPath
@webroot – 当前运行应用的 Web 入口目录
@web – 当前运行应用的根 URL

命令行写入host

echo 182.141.134.64 www.yii2-sns.com >> C:\Windows\System32\drivers\etc\hosts

若不能正常写入,查看一下属性,是否勾选了只读,如果勾选则去掉,然后保存,即可。

uniapp实现tabs切换(可滑动)效果实例

<template>
	<view class="body-view">
		<!-- 使用scroll-view实现tabs滑动切换 -->
		<scroll-view class="top-menu-view" scroll-x="true" :scroll-into-view="tabCurrent">
			<view class="menu-topic-view" v-for="item in tabs" :id="'tabNum'+item.id" :key="(item.id - 1)" @click="swichMenu(item.id - 1)">
				<view :class="currentTab==(item.id - 1) ? 'menu-topic-act' : 'menu-topic'">
					<text class="menu-topic-text">{{item.name}}</text>
					<view class="menu-topic-bottom">
						<view class="menu-topic-bottom-color"></view>
					</view>
				</view>
			</view>
		</scroll-view>
		<!-- 内容 -->
		<swiper class="swiper-box-list" :current="currentTab" @change="swiperChange">
			<swiper-item class="swiper-topic-list" v-for="item in swiperDateList" :key="item.id">
				<view class="swiper-item">
					{{item.content}}
				</view>
			</swiper-item>
		</swiper>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				tabs: [{
						id: 1,
						name: '推荐'
					},
					{
						id: 2,
						name: '交通交通'
					},
					{
						id: 3,
						name: '住房'
					},
					{
						id: 4,
						name: '社会保障'
					},
					{
						id: 5,
						name: '民生热点'
					},
					{
						id: 6,
						name: '即日头条'
					},
					{
						id: 7,
						name: '新闻联播'
					},
				],
				currentTab: 0,
				tabCurrent: 'tabNum1',
				// Tab切换内容
				swiperDateList: [{
						id: 1,
						content: '推荐'
					},
					{
						id: 2,
						content: '交通交通'
					},
					{
						id: 3,
						content: '住房'
					},
					{
						id: 4,
						content: '社会保障'
					},
					{
						id: 5,
						content: '民生热点'
					},
					{
						id: 6,
						content: '即日头条'
					},
					{
						id: 7,
						content: '新闻联播'
					},
				],
			}
		},
		onLoad() {
		},
		methods: {
			swichMenu(id) {
				this.currentTab = id
				console.log(11,id)
				this.tabCurrent = 'tabNum'+ id
			},
			swiperChange(e) {
				console.log(22,e.detail.current)
				let index = e.detail.current
				this.swichMenu(index)
			}
		}
	}
</script>
<style scoped lang="scss">
	.body-view {
		height: 100vh;
		width: 100%;
		display: flex;
		flex: 1;
		flex-direction: column;
		overflow: hidden;
		align-items: flex-start;
		justify-content: center;
	}
	.top-menu-view {
		display: flex;
		position: fixed;
		top: 100rpx;
		left: 0;
		white-space: nowrap;
		width: 100%;
		background-color: #FFFFFF;
		height: 86rpx;
		line-height: 86rpx;
		border-top: 1rpx solid #d8dbe6;
		.menu-topic-view {
			display: inline-block;
			white-space: nowrap;
			height: 86rpx;
			position: relative;
			.menu-topic-text {
				font-size: 30rpx;
				color: #303133;
				padding: 10rpx 40rpx;
			}
			// .menu-topic-act {
			// 	margin-left: 30upx;
			// 	margin-right: 10upx;
			// 	position: relative;
			// 	height: 100%;
			// 	display: flex;
			// 	align-items: center;
			// 	justify-content: center;
			// }
			.menu-topic-bottom {
				position: absolute;
				bottom: 0;
				width: 100%;
				.menu-topic-bottom-color {
					width: 40rpx;
					height: 4rpx;
				}
			}
			.menu-topic-act .menu-topic-bottom {
				display: flex;
				justify-content: center;
			}
			.menu-topic-act .menu-topic-bottom-color {
				background: #3d7eff;
			}
		}
	}
	.swiper-box-list {
		width: 100%;
		padding-top: 200rpx;
		flex:1;
		background-color: #FFFFFF;
		.swiper-topic-list {
		     width: 100%;
		 }
	}
</style>

传递access_token参数的正确方式

在OAuth中, access_token参数的传递如何才能更安全呢? 不知你有没有具体去研究过, 在此总结传递access_token的正确方式,

(所谓正确方式是指传递方式更安全, 更隐匿, 更不容易被网络拦截,网络攻击的方式)

在 spring-oauth-server 与 oauth2-shiro 中均支持以下提到的传递access_token的方式.

1. 通过Header传递 access_token; [推荐]

在请求URL的Header中, 添加header -> Authorization: bearer access_token,  示例代码(Java):postHandler.addHeader(“Authorization”, “bearer 0fe12a74-e613-4d1b-9785-f96847bad346”);

一般在代码中使用httpclient或URLConnection来实现,如Android, IOS客户端, 不适用于浏览器传递access_token

2.若请求URL使用POST方式提交, 将access_token放在请求body中而不是拼接在URL上, 示例代码(HTML):<form action=”db_table_description” method=”post”> <input type=”hidden” name=”access_token” value=”0fe12a74-e613-4d1b-9785-f96847bad346″/> <input type=”text” name=”username”/> <button type=”submit”>Submit</button> </form>

3.最后的选择, 通过URL拼接参数access_token, 示例代码:http://monkeyk.com/oauth_test?access_token=0fe12a74-e613-4d1b-9785-f96847bad346

一般使用在GET请求, POST等其他请求方式也支持

以上三种方式, 优先选择第一,第二种, 少用第三种方式.这些方式都是基于HTTP请求下所采用的.
更安全的传递access_token的方式是启用HTTPS连接,保证网络传输安全.

文件批量处理

  1. 批量重命名文件
    在这里最核心的就是os.listdir(),这个函数可以返回文件夹里所有文件的文件名. 有了这个我们才能进行其他操作,包括遍历。
import sys
import os                                 #OS库是文件处理中经常用到的库
import comtypes.client
#单个word转PDF
wdFormatPDF = 17
addr = 'C:\\Users\\wang\\Desktop\\G13-a\\'   #文件夹的绝对路径

names = os.listdir(addr)                        # 读取文件夹下的所有文件名

#进行遍历
for name in names:                         
    old_name = addr + name                 #注意rename函数里要放完整的路径,不能只放新旧名字
    new_name = addr + name[:13]            #这是当时甲方要求去除后缀,故只取旧题目的前13位
    os.rename (old_name, new_name)      

2. 文件分类
在tender的最后提交时,甲方要求按工作编号进行提交,这里需要按照register里的编号进行分类。

首先读取文档,观察数据形式

import pandas as pd
df = pd.read_excel('C:\\Users\\wang\\Desktop\\DCC_file.xlsx')
通过读取register发现我们需要根据“DCC”列进行分类,而对应的文件名在“NATIVE”列

接下来,需要完成的就是:(1) 获取每一类DCC编码下的文件名;(2)复制对应文件名至相应文件夹。

其中文档的复制移动主要依靠shutil模块.

import os
import shutil 

file_dir = r'C:\Users\wang\Desktop\All file'     #这里是存放所有文件的位置,它们需要进行分类

os.chdir(file_dir)    

numb = '10-01902-0002-050'   #这是其中一个DCC 编码
os.mkdir(numb)          #在当前路径下创建对应的文件夹 

filenames = df.loc[(df['DCC']== numb)]['NATIVE']    #利用loc函数筛选出 '10-01902-0002-050' 对应的所有文件名

# 这里操作是因为DC部门在命名文件时,Pdf, Word 和drawing的文件名后三位分别是“P00”,“W00”和“V00”,
# 所以通过这个,为对应的文件名加上对应的后缀,来构成完整的文件名

for name in filenames:      
 
    if name[-3] == 'X':
        fname = name + '.xls'
    if name[-3] == 'V':
        fname = name + '.dgn'
    if name[-3] == 'W':
        fname = name + '.doc'
    
    if os.path.exists(fname) ==1:        #判断文件是否存在
        shutil.copy(fname,numb)         #复制文件至文件夹
    else:
        print(fname)                     #输出不存在的文件名,用来检查

3. 批量Word转PDF

这个很常见的需求,需要将word转为PDF,但传统的Adobe转PDF需要一个一个点,比较慢,而网上大部分批量转PDF的软件基本收费,所以也是临时想起用python写个小程序。

这里呢,如前面提到的DC要求,转换得到的PDF,名字后三位需要时“P00″, 例如C860040001W00.doc 转换后的PDF应该是 C860040001W00.pdf.

所以这里目标有两个:

(1) 遍历,也就是达到批量处理的目的

(2) 重命名后三位为”P00″

这里用到的库是 comtypes.client,用它访问COM组件达到转PDF的目的。

import sys
import os
import comtypes.client

wdFormatPDF = 17

addr = 'C:\\Users\\wang\\Desktop\\doc\\10-01902-0002-711\\' # 目标路径,存放word的位置

doc_names = os.listdir(addr)  #读取文件夹里所有文件的名字
pdf_names = []              #将用来存放转换后PDF的名字

#开始遍历
for name in doc_names:     
    pdf_name = name[:10] +'P00.pdf'    #实现文件名转换:C860040001W00.doc 到 C860040001W00.pdf.
    pdf_names.append(pdf_name)  #存放新的PDF文档文件名
    in_file = os.path.abspath(addr + name)  #构造完整路径的文件名
    out_file = os.path.abspath(addr + pdf_name)
    word = comtypes.client.CreateObject('Word.Application')
    doc = word.Documents.Open(in_file)
    doc.SaveAs(out_file, FileFormat=wdFormatPDF)   #转换为PDF
    doc.Close()
    word.Quit()

有了这些小程序,基本可以处理工作中的文档操作了!感谢Python让我现在有时间喝咖啡写文章,而不用继续click,click,click.

实践美文 (一)

层次看鞋子,卫生看指甲

人品看眼神,自律看身材

格局看买单,家教看坐姿

性格看笑声,脾气看语气

境界看表情,态度看嘴角

pycharm激活

pycharm激活码最新提取方式:www.ajihuo.com

如果不好用了可以到www.ajihuo.com中提取)