Toffee's Blog

  • 首页

  • 归档

  • 搜索

使用Github WebHooks监听提交实现hexo自动部署

发表于 2019-09-02

Webhooks

Webhooks允许在发生特定事件时通知外部服务。当指定的事件发生时,将向设置好的URL地址发送POST请求。

在GitHub中设置webhooks首先进入项目的设置页面,在左侧找到Webhooks选项,点击add进入新增设置

首先设置Payload URL,这是你的服务器地址,每当有提交动作就会像这个地址发送post请求

Content type可以设置表单或者json格式

Secret密钥,用于服务器验证请求是否有Github服务器发送

所有设置完毕后,就可以进行下一步

服务器监听

这里推荐使用github-webhook-handler这个库,可以很方便帮助我们完成服务端的配置
示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var http = require('http')
var createHandler = require('github-webhook-handler')
var handler = createHandler({path: '这里填写在github上配置的路径地址', secret: '这里填写上面项目上配置的密钥'})
const {exec} = require('child_process') // 执行本地命令

http.createServer(function(req, res) {
handler(req, res, function(err) {
res.statusCode = 404
res.end('no such location')
})
}).listen('配置的端口')

handler.on('error', function(err) {
console.error('Error:', err.message)
})

handler.on('push', function(event) {
console.log('Received a push event for %s to %s',
event.payload.repository.name,
event.payload.ref)
exec('cd /www/wwwroot/default/blog && git pull', (err, stdout, stderr) => {
if (err) {
console.log(err)
}
else {
console.log('updated success')
}
})
})

结束

这样,在服务端部署好这个小的程序后(注意开放相关端口),每次在本地执行hexo g -d命令后,服务端接收到钩子信息就会自动从master分支拉取最新的代码,实现自动更新

【翻译】如何用puppeteer通过slider滑块认证

发表于 2019-08-22

image

Photo by James Pond on Unsplash

垃圾邮件对于网站所有者来说是个大问题。另一方面,划块验证让我发疯,他们对用户体验不太友好。

划块验证虽然很糟糕但是我们还是要面对它,有很多种方法可以人机验证,但是他们一般来说都不太好。

近年来爬虫变得越来越智能并且网站很难去识别,在拥有大量的时间以及足够的资源后,我们几乎可以通过任何人机验证。现在有插件可以防止使用puppeteer被检测并解决人机验证,甚至出现了专门的公司。我们无法检测到被puppeteer控制的无头chrome浏览器。

有些网站使用了滑块验证来作为人机验证的一种方案,但是为什么有人会使用这么简单的东西来绕过它:

  • 大多数爬虫不执行js代码
  • 用户体验更好
  • 滑块的方式天然适合手机用户

所以,滑块验证对于用户来说是美好且亲切的,但是如果只有滑块验证的话那就象手拿木棒赤裸地进入战场了。

让我们来通过滑块验证吧!

滑动提交

有一种jquery插件是专门为这种防止垃圾邮件的表单服务的
image

首先我们计算出滑块区域的边界信息,为了移动滑块,我们要做以下这些事:

  • 把鼠标放在要操作元素的中心
  • 按下鼠标
  • 移动
  • 在合适的位置松开鼠标
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const puppeteer = require('puppeteer')

async function run() {
const browser = await puppeteer.launch({
headless: false,
defaultViewport: { width: 1366, height: 768 }
})
const page = await browser.newPage()
await page.goto('http://kthornbloom.com/slidetosubmit/')
await page.type('input[name="name"]', 'Puppeteer Bot')
await page.type('input[name="email"]', 'js@automation.com')

let sliderElement = await page.$('.slide-submit')
let slider = await sliderElement.boundingBox()

let sliderHandle = await page.$('.slide-submit-thumb')
let handle = await sliderHandle.boundingBox()

await page.mouse.move(handle.x + handle.width / 2, handle.y + handle.height / 2)
await page.mouse.down()
await page.mouse.move(handle.x + slider.width, handle.y + handle.height / 2, { steps: 10 })
await page.mouse.up()

await page.waitFor(3000)

// success!

await browser.close()
}

run()
阅读全文 »

纯css实现动态天气效果代码

发表于 2019-08-21

预览效果

image

代码

html代码

1
2
3
4
<div class="weather sunny"></div>
<div class="weather cloudy"></div>
<div class="weather rainy"></div>
<div class="weather snowy"></div>

css 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
.weather {
position: relative;
display: inline-block;
width: 180px;
height: 240px;
background: #23b7e5;
border-radius: 8px;
}
.sunny:before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60px;
height: 60px;
background: #F6D963;
border-radius: 50%;
box-shadow: 0 0 20px #ff0;
z-index: 2;
}
.sunny:after {
content: "";
position: absolute;
top: 50%;
left: 50%;
margin: -45px 0 0 -45px;
width: 90px;
height: 90px;
background: #FFEB3B;
clip-path: polygon(
50% 0%,
65.43% 25%,
93.3% 25%,
78.87% 50%,
93.3% 75%,
64.43% 75%,
50% 100%,
35.57% 75%,
6.7% 75%,
21.13% 50%,
6.7% 25%,
35.57% 25%);
z-index: 1;
animation: sunScale 2s linear infinite;
}
@keyframes sunScale {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
.cloudy:before,
.rainy:before,
.snowy:before {
content: "";
position: absolute;
top: 50%;
left: 25%;
transform: translate(-50%, -50%);
width: 36px;
height: 36px;
background: #fff;
border-radius: 50%;
box-shadow:
#fff 22px -15px 0 6px,
#fff 57px -6px 0 2px,
#fff 87px 4px 0 -4px,
#fff 33px 6px 0 6px,
#fff 61px 6px 0 2px,
#ccc 29px -23px 0 6px,
#ccc 64px -14px 0 2px,
#ccc 94px -4px 0 -4px;
z-index: 2;
}
.cloudy:before {
animation: cloudMove 2s linear infinite;
}
@keyframes cloudMove {
0% {
transform: translate(-50%, -50%);
}
50% {
transform: translate(-50%, -60%);
}
100% {
transform: translate(-50%, -50%);
}
}
.rainy:after {
content: "";
position: absolute;
top:50%;
left: 25%;
width: 4px;
height: 14px;
background: #fff;
border-radius: 2px;
box-shadow:
#fff 25px -10px 0,
#fff 50px 0 0,
#fff 75px -10px 0,
#fff 0 25px 0,
#fff 25px 15px 0,
#fff 50px 25px 0,
#fff 75px 15px 0,
#fff 0 50px 0,
#fff 25px 40px 0,
#fff 50px 50px 0,
#fff 75px 40px 0;
animation: rainDrop 2s linear infinite;
}
@keyframes rainDrop {
0% {
transform: translate(0, 0) rotate(10deg);
}
100% {
transform: translate(-4px, 24px) rotate(10deg);
box-shadow:
#fff 25px -10px 0,
#fff 50px 0 0,
#fff 75px -10px 0,
#fff 0 25px 0,
#fff 25px 15px 0,
#fff 50px 25px 0,
#fff 75px 15px 0,
rgba(255, 255, 255, 0) 0 50px 0,
rgba(255, 255, 255, 0) 25px 40px 0,
rgba(255, 255, 255, 0) 50px 50px 0,
rgba(255, 255, 255, 0) 75px 40px 0;
}
}
.snowy:after {
content: "";
position: absolute;
top:50%;
left: 25%;
width: 8px;
height: 8px;
background: #fff;
border-radius: 50%;
box-shadow:
#fff 25px -10px 0,
#fff 50px 0 0,
#fff 75px -10px 0,
#fff 0 25px 0,
#fff 25px 15px 0,
#fff 50px 25px 0,
#fff 75px 15px 0,
#fff 0 50px 0,
#fff 25px 40px 0,
#fff 50px 50px 0,
#fff 75px 40px 0;
animation: snowDrop 2s linear infinite;
}
@keyframes snowDrop {
0% {
transform: translateY(0);
}
100% {
transform: translateY(25px);
box-shadow:
#fff 25px -10px 0,
#fff 50px 0 0,
#fff 75px -10px 0,
#fff 0 25px 0,
#fff 25px 15px 0,
#fff 50px 25px 0,
#fff 75px 15px 0,
rgba(255, 255, 255, 0) 0 50px 0,
rgba(255, 255, 255, 0) 25px 40px 0,
rgba(255, 255, 255, 0) 50px 50px 0,
rgba(255, 255, 255, 0) 75px 40px 0;
}
}

vue transition实现原生页面跳转效果

发表于 2019-08-21

代码

使用Vue <transition> 组件过渡

1
2
3
<transition :name="this.$store.routeAction">
<router-view/>
</transition>

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
.push-enter-active,.push-leave-active
, .pop-enter-active,.pop-leave-active{
transition: all 0.4s;
}

.push-leave-to{
transform: translate(-20%,0);
}

.push-enter {
transform: translate(100%, 0);
}
.push-enter-active {
z-index: 10;
}
.push-leave-active {
z-index: 0;
}
.pop-leave-active {
transform: translate(100%, 0);
z-index: 11;
}

.pop-enter{
transform: translate(-20%,0);
}

效果

image

chrome快捷键太反人类?不想安装额外插件?那就用TamperMonkey写个脚本

发表于 2019-07-19

Chrome快捷键

对于一天用到将近百余次的ctrl+w的我来说,一直觉得chrome原本的ctrl+w的按键有点别扭,终于在今天忍不住了,开始寻找如何去修改chrome默认的快捷键。在设置里找了一圈,发现没有,无奈google了一下,发现有这么几种办法

  • 安装chrome插件 如Shortkeys等
  • 修改chrome系统文件
    我综合了一下,发现我只需要实现alt + w关闭浏览器TAB的功能,这么折腾似乎不太经济,突然想到我有安装TamperMonkey油猴插件,于是便想到自己动手写个js脚本完事

TamperMonkey

TamperMonkey是一个浏览器插件,它是一个脚本管理器,通过脚本市场安装第三方js脚本,可以实现非常多的拓展功能,可以就不展开了
我们新建一个脚本文件,注意脚本文件开头 match选项表示脚本应用的范围,这里我们应用所有网站

1
2
// @match        http://*/*
// @match https://*/*

编写脚本

好了,下面就开始编写我们的脚本,TamperMonkey脚本文件实质就是输出个js IFFE(立即执行函数),
脚本内容都编写在里面,我们只需要全局监听onkeydown事件,判断是否同时按下alt + w,然后执行window.close()关闭页面就可以了

1
2
3
4
5
6
7
8
(function() {
window.addEventListener('keydown',function(event){
if (event.altKey && event.keyCode == 87) {
window.location.href = "about:blank"
window.close()
    }
})
})()

1…345…9
Toffee

Toffee

44 日志
GitHub E-Mail 我的网站 StackOverflow
0%
© 2018 – 2021 Toffee