小田'blog

前端小菜鸡(〃∀〃)

0%

node爬虫 简易版【站酷】

简单的学习一下node爬虫, 抓取站酷(本来想抓花瓣的,但是因为花瓣是接口调用的 而我想抓dom所以选择了站酷 :)

Read more »

资料

题目: https://www.spoj.com/problems/PT07Z/

https://zh.wikipedia.org/wiki/%E6%A0%91_(%E5%9B%BE%E8%AE%BA)

谢谢岛老师的教学

岛娘blog

岛娘Github

岛娘Youtube

code source

Go

下面根据上面资料的wiki图来生成的点和边 看不见可能需要科学上网

点: 1 2 3 4 5 6

边: 14 24 34 45 56

设置顶点

使用 Map https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map

1
2
let vertexLen = 6; // 顶点数
let vertex = new Map(); // 顶点数据集合 map 可以设置键对值 0 1 2 3 4 5 or 1 2 3 4 5 6 or A B C D E F G ... ...

设置顶点和边

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
/**
* 设置顶点
* @param {String || Number} v 顶点
*/
const setVertex = v => vertex.set(v, []);
/**
* 设置边
* @param {String || Number} v1 点
* @param {String || Number} v2 点
*/
const setVertexEdge = (v1, v2) => {
vertex.get(v1).push(v2);
vertex.get(v2).push(v1);
};

// 设置点
for (let i = 1; i <= vertexLen; i++) setVertex(i);

// 定义边
let vertexEdge = [[1, 4], [2, 4], [3, 4], [4, 5], [5, 6]];

// 设置边
for (let i = 0; i < vertexEdge.length; i++)
setVertexEdge(vertexEdge[i][0], vertexEdge[i][1]);

得到的集合

1
2
3
4
5
6
7
Map {
1 => [ 4 ],
2 => [ 4 ],
3 => [ 4 ],
4 => [ 1, 2, 3, 5 ],
5 => [ 4, 6 ],
6 => [ 5 ] }

dfs

vertex 结构目前是这样点 ⬆️️️️️️️️️️ ⬆️️️️️️️️️️ ⬆️️️️️️️️️️

这个方法主要通过存放一个map保存访问状态

参考地址 https://www.geeksforgeeks.org/implementation-graph-javascript/

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
/**
* dfs
* @param {String || Number} startNode 开始点
*/
const dfs = startNode => {
let visited = new Map(); // 保持和顶点结构一样
for (let i = 1; i <= vertexLen; i++) visited.set(i, false); // 设置访问状态

// dfs 方法
const dfsFunc = (startNode, visited) => {
let z = 0; // 长度
visited.set(startNode, true); // 第一个点设置已访问
let get_next = vertex.get(startNode); // 获得顶点的所有临接点
for (let i = 0; i < get_next.length; i++) {
// 循环临接点
let get_elem = get_next[i]; // 得到元素
if (!visited.get(get_elem)) {
// 是否访问
z = Math.max(z, dfsFunc(get_elem, visited) + 1); // 增加边数
}
}
return z;
};
return dfsFunc(startNode, visited);
};

dfs

下面这个是岛老师👨‍🏫教我方法

主要通过存父节点来判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* dfs
* @param {String || Number} startNode 开始点
*/
const dfs1 = startNode => {
// 记录开始点和父级节点
const dfsFunc = (startNode, parentNode = -1) => {
let z = 0; // 记录长度
let get_next = vertex.get(startNode); // 得到相邻节点
for (let i = 0; i < get_next.length; i++) { // 循环点
let get_elem = get_next[i]; // 得到点
if (get_elem === parentNode) continue; // 如果是父节点 跳过
z = Math.max(z, dfsFunc(get_elem, startNode) + 1); // 递归添加长度
}
return z;
};
return dfsFunc(startNode);
};

查看所有代码
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
let vertexLen = 6; // 顶点数
let vertex = new Map(); // 顶点数据集合 map 可以设置键对值 0 1 2 3 4 5 or 1 2 3 4 5 6 or A B C D E F G ... ...

/**
* 设置顶点
* @param {String || Number} v 顶点
*/
const setVertex = v => vertex.set(v, []);
/**
* 设置边
* @param {String || Number} v1 点
* @param {String || Number} v2 点
*/
const setVertexEdge = (v1, v2) => {
vertex.get(v1).push(v2);
vertex.get(v2).push(v1);
};

// 设置点
for (let i = 1; i <= vertexLen; i++) setVertex(i);

// 定义边
let vertexEdge = [[1, 4], [2, 4], [3, 4], [4, 5], [5, 6]];

// 设置边
for (let i = 0; i < vertexEdge.length; i++)
setVertexEdge(vertexEdge[i][0], vertexEdge[i][1]);

/**
* dfs
* @param {String || Number} startNode 开始点
*/
const dfs = startNode => {
let visited = new Map(); // 保持和顶点结构一样
for (let i = 1; i <= vertexLen; i++) visited.set(i, false); // 设置访问状态

// dfs 方法
const dfsFunc = (startNode, visited) => {
let z = 0; // 长度
visited.set(startNode, true); // 第一个点设置已访问
let get_next = vertex.get(startNode); // 获得顶点的所有临接点
for (let i = 0; i < get_next.length; i++) {
// 循环临接点
let get_elem = get_next[i]; // 得到元素
if (!visited.get(get_elem)) {
// 是否访问
z = Math.max(z, dfsFunc(get_elem, visited) + 1); // 增加边数
}
}
return z;
};
return dfsFunc(startNode, visited);
};

/**
* dfs
* @param {String || Number} startNode 开始点
*/
const dfs1 = startNode => {
// 记录开始点和父级节点
const dfsFunc = (startNode, parentNode = -1) => {
let z = 0; // 记录长度
let get_next = vertex.get(startNode); // 得到相邻节点
for (let i = 0; i < get_next.length; i++) { // 循环点
let get_elem = get_next[i]; // 得到点
if (get_elem === parentNode) continue; // 如果是父节点 跳过
z = Math.max(z, dfsFunc(get_elem, startNode) + 1); // 递归添加长度
}
return z;
};
return dfsFunc(startNode);
};

let z = dfs(1);
console.log(z);

let z1 = dfs1(1);
console.log(z1);

console.log(vertex);


— 分割线 —

很遗憾上面的是有问题的

岛老师的作业批改

  • 数据没有从 IO 读入读出。

  • 第一个 dfs 求出的不是最远的端点。

正确的解法应该是先求最深的一个端点,然后用从这个端点再搜索一次.

  因为 js 在 https://www.spoj.com 跑不过, 在http://codeforces.com 可以跑但是没找到题目,然后就选用了c++

在codeforces js输入输出

http://codeforces.com/blog/entry/10594

http://codeforces.com/blog/entry/64707


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// u 开始点 p 父节点
pair<int, int> dfs(int u, int p = -1) {
// z first 长度 z second 最深点
// first += 1 second 为 u
pair<int, int> z = {0, u};
// for edge u 的 边
for(auto v: edge[u]) {
// 如果是父级点 跳过
if (v == p) continue;
z = max(z, dfs(v, u));
}
// 边+1
z.first += 1;
return z;
}
查看所有代码
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
#include <iostream>
#include <vector>
using namespace std;

const int N = 1e6;
vector<int> edge[N];

// u 开始点 p 父节点
pair<int, int> dfs(int u, int p = -1) {
// z first 长度 z second 最深点
// first += 1 second 为 u
pair<int, int> z = {0, u};
// for edge u 的 边
for(auto v: edge[u]) {
// 如果是父级点 跳过
if (v == p) continue;
z = max(z, dfs(v, u));
}
// 边+1
z.first += 1;
return z;
}


int main() {
int n;
// 输入
cin >> n;

// 输入端点循环下面的边
for(int i = 0; i < n - 1; i++) {
int v, u;
cin >> v >> u;
edge[v].push_back(u);
edge[u].push_back(v);
}

// 得到最深的端点
pair<int, int> z = dfs(1);
// 从最深的端点搜索
z = dfs(z.second);

// 边-1
cout << z.first-1 << endl;
}

希望看到的大佬可以多多指点迷津!!! 右边有我的联系方式💗💗

今天产品反馈了一个Bug说是鼠标经过,图片会 圆角=》无圆角=》圆角 的过程来变化

懒得贴图, 搜到这个文章肯定就会发生了hhh

增加解决方案,方便更快搜到问题

解决方案

给他的父级添加 transform

1
2
transform: rotate(0deg);
/* 懒得加 -webkit */

结论

我还不知道为什么会这样(可能是浏览器的解析不同???)

脑洞

猜测影响失效的原因

  • transition 去掉这个可以解决!!!但是没有动画只会很难看 不可取
  • transform 猜测
  • xxxxx

如果大佬知道问题和原理所在,请告知菜🐔我!!!, 右侧和其他文章有联系方式!!!

搬砖系列

multi-line-truncation-with-pure-css

个人平时截断用的第三方库(为了兼容吧), -webkit-line-clamp 这个属性也不错!!!

下面是按照自己的理解来的2333

使用行高

比如一个元素 line-height: 1.4rem, 确保只显示三行. max-height 设置为 1.4rem * 3.

设置一个全局变量line-height

1
2
3
4
html {
--lh: 1.4rem;
line-height: var(--lh);
}

设置最大高度

1
2
3
4
5
.truncate-overflow {
--max-lines: 3;
max-height: calc(var(--lh) * var(--max-lines));
overflow: hidden;
}

如果你不关心省略号,这可能就足够了

当你想显示省略号的东西时,剩下的技巧就出现了

如果position: relative在元素上设置,则可以将省略号放在右下角

1
2
3
4
5
6
.truncate-overflow::before {
content: "...";
position: absolute;
bottom: 0;
right: 0;
}

当文本太短时,让我们掩盖省略号

制作一个与背后的背景相同的小盒子,并将其设置在省略号的顶部以覆盖它。我们可以用其他伪元素做到这一点:

1
2
3
4
5
6
7
8
.truncate-overflow::after {
content: "";
position: absolute;
right: 0; /* note: not using bottom */
width: 1rem;
height: 1rem;
background: white;
}

https://css-tricks.com/multi-line-truncation-with-pure-css/

建议大家看原文吧,按照个人理解(后续有空会重写或者更新)

搬砖系列

Managing Multiple Backgrounds with Custom Properties

防止大家打不开Page,我特地复制了下来(偷懒添加内容)

强烈建议大家看原文

One cool thing about CSS custom properties is that they can be a part of a value. Let’s say you’re using multiple backgrounds to pull off a a design. Each background will have its own color, image, repeat, position, etc. It can be verbose!

关于CSS自定义属性的一个很酷的事情是它们可以成为值的一部分。假设您使用多个背景来实现设计。每个背景都有自己的颜色,图像,重复,位置等。它可以是冗长的!

You have four images:

你有四张图片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
body {

background-position:
top 10px left 10px,
top 10px right 10px,
bottom 10px right 10px,
bottom 10px left 10px;

background-repeat: no-repeat;

background-image:
url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg),
url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg),
url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg),
url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg);

}

You want to add a fifth in a media query:

您想在媒体查询中添加第五个:

1
2
3
4
5
@media (min-width: 1500px) {
body {
/* REPEAT all existing backgrounds, then add a fifth. */
}
}

That’s going to be super verbose! You’ll have to repeat each of those four images again, then add the fifth. Lots of duplication there.

这将是超级冗长的!你将不得不再次重复这四个图像中的每一个,然后添加第五个。那里有很多重复。

One possibility is to create a variable for the base set, then add the fifth much more cleanly:

一种可能性是为基本集创建一个变量,然后更干净地添加第五个变量:

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

body {
--baseBackgrounds:
url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg),
url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg),
url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg),
url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg);

background-position:
top 10px left 10px,
top 10px right 10px,
bottom 10px right 10px,
bottom 10px left 10px;

background-repeat: no-repeat;

background-image: var(--baseBackgrounds);
}
@media (min-width: 1500px) {
body {
background-image:
var(--baseBackgrounds),
url(added-fifth-background.svg);
}
}

But, it’s really up to you. It might make more sense and be easier manage if you made each background image into a variable, and then pieced them together as needed.

但是,这完全取决于你。如果将每个背景图像变为变量,然后根据需要将它们拼接在一起,则可能更有意义并且更容易管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
body {
--bg1: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg);
--bg2: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg);
--bg3: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg);
--bg4: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg);
--bg5: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg);

background-image: var(--bg1), var(--bg2), var(--bg3), var(--bg4);
}
@media (min-width: 1500px) {
body {
background-image: var(--bg1), var(--bg2), var(--bg3), var(--bg4), var(--bg5);
}
}

Here’s a basic version of that, including a supports query:

这是它的基本版本,包括支持查询:

— 懒得用他的codepen了

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
body {
margin: 0;
height: 100vh;

--cloud-1: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/cloud.png);

--cloud-2: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/cloud.png);

--sky: linear-gradient(
to bottom,
#80D8FF,
#40C4FF
);
--skyDark: linear-gradient(
to bottom,
#333,
#111
);

background-size:
1000px, 1000px, cover;

background-position:
top 25% right 20%, top -5% left 20%, center;

background-repeat:
repeat-x, repeat-x, no-repeat;
}

@supports (background-image: url(foo.jpg), url(bar.jpg)) {
body {
background-image:
var(--cloud-1), var(--cloud-2), var(--sky);
}
@media (min-width: 700px) {
body {
background-image:
var(--cloud-1), var(--cloud-2), var(--skyDark);
}
}
}

Dynamically changing just the part of a value is a huge strength of CSS custom properties!

动态更改值的一部分是CSS自定义属性的巨大优势!

Note, too, that with backgrounds, it might be best to include the entire shorthand as the variable. That way, it’s much easier to piece everything together at once, rather than needing something like…

另请注意,对于背景,最好将整个速记包含为变量。这样,一次将所有东西拼凑起来要容易得多,而不是需要……

1
2
3
4
--bg_1_url: url();
--bg_1_size: 100px;
--bg_1_repeat: no-repeat;
/* etc. */

It’s easier to put all of the properties into shorthand and use as needed:

将所有属性放入速记并根据需要使用会更容易:

1
2
3
4
5
6
7
8
9
body {  
--bg_1: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-left.svg) top 10px left 10px / 86px no-repeat;
--bg_2: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-top-right.svg) top 10px right 10px / 86px no-repeat;
--bg_3: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-right.svg) bottom 10px right 10px / 86px no-repeat;
--bg_4: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/angles-bottom-left.svg) bottom 10px left 10px / 86px no-repeat;

background:
var(--bg_1), var(--bg_2),var(--bg_3),var(--bg_4);
}

记录自己开发chrome extension中遇到的坑(🍑

开发环境

vue

使用下面资料提供的模版, 快速入坑(🍑

Dev

1
2
3
npm i

npm run watch:dev

会自动build, 使用dist目录即可

Build

1
2
3
npm run build/npm run build:dev

npm run build-zip

资料

https://developer.chrome.com/extensions

https://github.com/sxei/chrome-plugin-demo

https://github.com/Kocal/vue-web-extension (模版)

希望大家多看看文档和第二个连接的文章写的非常好(Good ❗️️️❗️❗️️)

— 2019-7-15 —