0%

你为什么从事喜剧行业?人们总是嘲笑我,所以我想,去他妈的,干脆收他们点儿钱!
一个简单的下载图片的爬虫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
from bs4 import BeautifulSoup
headers = {'User-Agent':"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
all_url = 'http://www.mzitu.com/all'
start_html = requests.get(all_url, headers=headers)
Soup = BeautifulSoup(start_html.text, 'lxml')

all_a = Soup.find('div', class_='all').find_all('a')
for a in all_a:
title = a.get_text()
href = a.get('href')
html = requests.get(href, headers=headers)
html_Soup = BeautifulSoup(html.text, 'lxml')
max_span = html_Soup.findAll('span')[10].get_text()
for page in range(1, int(max_span) + 1):
page_url = href + '/' + str(page)
img_html = requests.get(page_url, headers=headers)
img_Soup = BeautifulSoup(img_html.text, 'lxml')
img_url = img_Soup.find('div', class_='main-image').find('img')['src']
name = img_url[-9:-4]
img = requests.get(img_url, headers=headers)
f = open(name + '.jpg', 'ab')
f.write(img.content)
f.close()

more less

JWT stand for Json Web Token. JWT will helps to create authentication and connect front-end and back-end function. JWT through we can create login and register API. So first we have to install “tymon/jwt-auth” package in laravel 5.2.

JWT Installation

First fire following command on your terminal.

Installation Package

composer require tymon/jwt-auth
After install this package, Now open config/app.php file and add service provider and aliase.
config/app.php

1
2
3
4
5
6
7
8
'providers' => [
....
'Tymon\JWTAuth\Providers\JWTAuthServiceProvider',
],
'aliases' => [
....
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth'
],

Now we need to publish JWT configration file, that way we can change configration like token expire time etc. so, let’s fire bellow command.

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
At last on installation, we have to generate jwt key, fire bellow command on your terminal.

php artisan jwt:generate

Create API Route

Now we require to create create route for API, in bellow route you can see i use two middleware “api” and “cors”. cors is not mandatory, but when you call api and found like:

“Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://test.com/api/register. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).”

Then you have two must be create cors middleware by following link : Ajax - Cross-Origin Request Blocked in Larave 5?.

app/Http/routes.php

1
2
3
4
5
6
7
Route::group(['middleware' => ['api','cors'],'prefix' => 'api'], function () {
Route::post('register', 'APIController@register');
Route::post('login', 'APIController@login');
Route::group(['middleware' => 'jwt-auth'], function () {
Route::post('get_user_details', 'APIController@get_user_details');
});
});

In above i use also added jwt-auth for token is valid or not. so we must need to create jwt-auth middleware and first fire following command.

php artisan make:middleware authJWT
On now you can check on Middleware(app/Http/Middleware) directory, you can find authJWT.php file and put bellow code on that file.

app/Http/Middleware/authJWT.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace App\Http\Middleware;
use Closure;
use JWTAuth;
use Exception;
class authJWT
{
public function handle($request, Closure $next)
{
try {
$user = JWTAuth::toUser($request->input('token'));
} catch (Exception $e) {
if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){
return response()->json(['error'=>'Token is Invalid']);
}else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){
return response()->json(['error'=>'Token is Expired']);
}else{
return response()->json(['error'=>'Something is wrong']);
}
}
return $next($request);
}
}

Ok, now register new created middleware on Kernel.php(app/Http/Kernel.php) file and append following line.

app/Http/Kernel.php

1
2
3
4
5
6
7
8
9
10
11
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
...
...
protected $routeMiddleware = [
...
'jwt-auth' => \App\Http\Middleware\authJWT::class,
];
}

Create Controller

Here we have to create controller that will manage all route request. so first create “APIController” and put bellow code.

app/Http/Controllers/APIController.php

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
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Hash;
use JWTAuth;
class APIController extends Controller
{

public function register(Request $request)
{
$input = $request->all();
$input['password'] = Hash::make($input['password']);
User::create($input);
return response()->json(['result'=>true]);
}

public function login(Request $request)
{
$input = $request->all();
if (!$token = JWTAuth::attempt($input)) {
return response()->json(['result' => 'wrong email or password.']);
}
return response()->json(['result' => $token]);
}

public function get_user_details(Request $request)
{
$input = $request->all();
$user = JWTAuth::toUser($input['token']);
return response()->json(['result' => $user]);
}

}

Test API from Front-end

Don’t forgot to change http://learnl52.hd = your site url.

Now we are ready to check our API from front-end side. i did make jquery ajax request example but you can also call API in angularjs. first fire register api that will return just success if user created success fully.

Call Register API

1
2
3
4
5
6
7
8
9
$.ajax({
url: "http://learnl52.hd/api/register",
dataType: "json",
type: "POST",
data: {"name":"HD","email":"test@gmail.com","password":"123456"},
success: function (data) {
alert("user created successfully")
}
});

Now you can fire login API, this API will return token in result if, email and password will not wrong. that token you have to pass in all other route that way you can identify this user is current login user so fire following way:

Call Login API

1
2
3
4
5
6
7
8
9
$.ajax({
url: "http://learnl52.hd/api/login",
dataType: "json",
type: "POST",
data: {"email":"test@gmail.com","password":"123456"},
success: function (data) {
alert(data.result)
}
});

At last we can fire get_user_details API, This API will take only one paramete token, token is that you find on login API. this API will return all users details if your token is valid, if token is not valid then return error message. fire ajax like this way:

Call Get User Details API

1
2
3
4
5
6
7
8
9
$.ajax({
url: "http://learnl52.hd/api/get_user_details",
dataType: "json",
type: "POST",
data: {"token":your toke here},
success: function (data) {
console.log(data)
}
});

add

Require the barryvdh/laravel-cors package in your composer.json and update your dependencies.

composer require barryvdh/laravel-cors
Add the Cors\ServiceProvider to yourconfig/app.phpproviders array:

Barryvdh\Cors\ServiceProvider::class,

http://itsolutionstuff.com/post/laravel-52-api-using-jwt-authentication-tutorial-from-scratch-exampleexample.html

 你必须很努力,才能看上去毫不费力
最近学习了微信小程序,才接触到了这一布局方式,大概试了一下,记录之

1. 布局html

1
2
3
4
5
6
7
8
9
10
11
<div class="container">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item4">4</div>
<div class="item item5">5</div>
<div class="item item6">6</div>
<div class="item item7">7</div>
<div class="item item8">8</div>
<div class="item item9">9</div>
</div>

2.order 属性

order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。

1
2
3
4
5
6
.item1{
order: 2;
}
.item2{
order: 1;
}

3. flex-grow属性

即如果子元素在父容器的横向上还没有撑满,左或者右都存在空间
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

1
2
3
4
.item1{
order: 2;
flex-grow: 2;
}

如果三个元素都设置这样的属性,则由这三个元素一起撑满剩余的部分

1
2
3
4
5
6
7
8
9
10
.item1{
flex-grow: 1;
}
.item2{
order: 1;
flex-grow: 1;
}
.item3{
flex-grow: 1;
}

4. flex-shrink属性

如果所有的子元素的宽度已经超过了父容器的宽度,而且设置了不能换行,这时候如果某个元素设置了这样的属性,
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

1
2
3
4
5
6
.item2{
flex-shrink: 2;
}
.item3{
flex-shrink: 2;
}

没有学到死,就往死里学。
最近学习了微信小程序,才接触到了这一布局方式,大概试了一下,记录:

使用方式:

1. html

1
2
3
4
5
6
7
8
9
10
11
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>

2. 定义基本css样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
body{
background: #c0ffb6;
}
.container{
width: 100%;
height: 100%;
}
.item{
width: 150px;
height: 200px;
background-color: #4cae4c;
margin: 2px;
}

3. 设置父容器为flex布局:

  • div 块儿级元素
    1
    2
    3
    4
    5
    .container{
    width: 100%;
    height: 100%;
    display: flex;
    }
  • 或者 行内元素
    1
    2
    3
    4
    5
    .container{
    width: 100%;
    height: 100%;
    display: inline-flex;
    }
    设为Flex布局以后,子元素的float、clear和vertical-align属性将失效

4. flex-direction 属性:

决定容器里面元素的排列方式
横向排列
横向反转排列
纵向排列
纵向反转排列

1
2
3
4
5
6
.container{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}

5. flex-wrap 属性

横向排列的子元素是否换行
在子元素的大小超出了父容器的大小以后是换行显示
不换行: nowrap 设置了不换行以后,子元素的大小将。。

1
2
3
4
5
6
7
8
9
10
11
12
13
.container{
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.item{
width: 650px;
height: 200px;
background-color: #4cae4c;
margin: 2px;
}

6. justify-content 属性

子元素的对齐方式
左对齐
右对齐
居中显示
相等间隔

1
2
3
4
5
6
7
8
.container{
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
}

7. align-items:

决定子元素在垂直位置上的对齐方式

1
2
3
4
5
6
7
8
9
.container{
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-around;
align-items: flex-end;
}

8. align-self 属性

决定当前元素的对齐方式,用于覆盖父容器的align-items 属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.container{
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
}
.item{
width: 450px;
height: 200px;
background-color: #4cae4c;
margin: 2px;
}
.item1{
height: 120px;
align-self: flex-end;
}
.item2{
height: 100px;
}
.item3{
height: 150px;
}

是谁来自山川湖海,却囿于昼夜、厨房与爱。

laravel的404

  • 配置404页面
    resources\views\errors\404.blade.php,如果配置了该页面,那么访问任何一个不存在的路由,就会显示到该页面,同时返回的状态码也会是404,同样,也可以通过代码abort(404);来展示出404页面,如果在你的视图文件中没有配置404.blade.php 页面,那么访问一个不存在的路由就会引起程序报错。

nginx的404

  • 配置404页面
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    server {
    listen 80;
    server_name www.la51.dev la51.dev;
    root "D:/phpStudy/WWW/la51/public";
    fastcgi_intercept_errors on;
    error_page 404 /404.html ;
    location / {
    index index.html index.htm index.php;
    #autoindex on;
    try_files $uri $uri/ /index.php?$query_string;
    }

404.html在网站的根目录下,关键的两句,`fastcgi_intercept_errors on;error_page 404 /404.html ;这样访问一个不存在的页面,即使没有在laravel中做相关的配置,也能在路由不存在时跳转到404页面;

不管我本人多么平庸,我总觉得对你的爱很美。

manifest.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"name": "消息传递",
"version": "1.0",
"manifest_version": 2,
"description": "各个页面JS之间事件的触发和消息的传递",
"browser_action": {
"default_icon": "images/icon38.png",
"default_popup": "popup.html"
},
"background": {
"scripts": ["js/background.js","js/jquery.min.js"],
"persistent": false
},
"permissions": ["tabs", "<all_urls>"]
}
1
2
3
4
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/content.js"></script>

<button id="newtab" >new tab</button>

content.js

1
2
3
4
5
$(document).ready(function () {
$("#newtab").click(function () {
chrome.runtime.sendMessage({action:"new_tab"});
});
});

background.js

1
2
3
4
5
6
7
8
9
10
11
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {

if(request.action != 'new_tab'){
var newURL = "http://stackoverflow.com/";
chrome.tabs.create({ url: newURL });
}else {
var newURL = "http://www.baidu.com/";
chrome.tabs.create({ url: newURL });
}

});

当斧头来到树林里的时候,好多树都说,至少它的把手是我们自己人。
ES中的聚合被分为两大类:Metric度量和bucket桶(原谅我英语差,找不到合适的词语.....就用单词来说吧!)。说的通俗点,metric很像SQL中的avg、max、min等方法,而bucket就有点类似group by了。

Sum 求和

1
2
3
"aggs" : {
"intraday_return" : { "sum" : { "field" : "change" } }
}

Min 求最小值

1
2
3
4
5
{
"aggs" : {
"min_price" : { "min" : { "field" : "price" } }
}
}

cardinality 求唯一值,即不重复的字段有多少

1
2
3
4
5
6
7
8
9
{
"aggs" : {
"author_count" : {
"cardinality" : {
"field" : "author"
}
}
}
}

一次性返回所有指标,count,min,max,avg,sum

1
2
3
4
5
{
"aggs" : {
"grades_stats" : { "stats" : { "field" : "total_price" } }
}
}

先过滤后聚合

1
2
3
4
5
6
7
8
9
10
{
"aggs" : {
"paid_order" : {
"filter" : { "term": { "status_code": "paid" } },
"aggs" : {
"avg_price" : { "avg" : { "field" : "total_price" } }
}
}
}
}

去除结果中的产品

1
2
3
4
5
6
7
8
9
10
11
{
"size":0,
"aggs" : {
"paid_order" : {
"filter" : { "term": { "status_code": "paid" } },
"aggs" : {
"avg_price" : { "avg" : { "field" : "total_price" } }
}
}
}
}

使用区间统计

1
2
3
4
5
6
7
8
9
10
{
"aggs" : {
"prices" : {
"histogram" : {
"field" : "total_price",
"interval" : 1000
}
}
}
}

日期过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"aggs": {
"range": {
"date_range": {
"field": "created_at",
"format": "MM-yyy",
"ranges": [
{ "to": "now-10M/M" },
{ "from": "now-10M/M" }
]
}
}
}
}

受任于败军之际,奉命于危难之间,尔来二十有一年矣。

manifest.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"name" : "Imageinfo",
"version" : "1.0.1",
"description" : "Get image info for images, including EXIF data",
"background" : { "scripts": ["js/background.js"] },
"permissions" : [
"contextMenus",
"tabs",
"http://*/*",
"https://*/*"
],
"minimum_chrome_version" : "6.0.0.0",
"icons" : {
"16" : "images/icon16.png",
"48" : "images/icon48.png",
"128" : "images/icon128.png"
},
"manifest_version": 2
}

background.js

1
2
3
4
5
6
7
8
9
10
11
12
13
function getClickHandler() {
return function(info, tab) {
var url = 'html/index.html#' + info.srcUrl;
chrome.windows.create({ url: url, width: 520, height: 660 });
};
};

chrome.contextMenus.create({
"title" : "Get image info",
"type" : "normal",
"contexts" : ["image"],
"onclick" : getClickHandler()
});

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script type="text/javascript" src="../js/jquery.min.js"></script>
<script type="text/javascript" src="../js/content.js"></script>
<title>Document</title>
</head>
<body>
<h1>tihs is a new page</h1>
<div id="con">

</div>
</body>
</html>

content.js

1
2
3
4
5
$(function () {
url = window.location.href;
kk = url.split('#');
$("#con").html("<img src='"+kk[1]+"' />");
});

她是你姑姑,又是你师父,怎么能做你妻子!

简述

他们的区别是,触发的时机不一样,先触发DOMContentLoaded事件,后触发load事件。

DOM文档加载的步骤为:

  • 解析HTML结构。
  • 加载外部脚本和样式表文件。
  • 解析并执行脚本代码。
  • DOM树构建完成。//DOMContentLoaded
  • 加载图片等外部文件。
  • 页面加载完毕。//load

在第4步,会触发DOMContentLoaded事件。在第6步,触发load事件。
用原生js可以这么写:

1
2
3
4
5
6
7
8
// 不兼容老的浏览器,兼容写法见[jQuery中ready与load事件](http://www.imooc.com/code/3253),或用jQuery
document.addEventListener("DOMContentLoaded", function() {
// ...代码...
}, false);

window.addEventListener("load", function() {
// ...代码...
}, false);

用jQuery这么写:

1
2
3
4
5
6
7
8
9
// DOMContentLoaded
$(document).ready(function() {
// ...代码...
});

//load
$(document).load(function() {
// ...代码...
});

http://www.jianshu.com/p/d851db5f2f30

身不饥寒,天未曾负我;学无长进,我何以对天
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: LoveNight

import requests
import time
import json
import os
import re
import sys
import subprocess
from bs4 import BeautifulSoup as BS


class ZhiHuClient(object):

"""连接知乎的工具类,维护一个Session
2015.11.11

用法:

client = ZhiHuClient()

# 第一次使用时需要调用此方法登录一次,生成cookie文件
# 以后可以跳过这一步
client.login("username", "password")

# 用这个session进行其他网络操作,详见requests库
session = client.getSession()
"""

# 网址参数是账号类型
TYPE_PHONE_NUM = "phone_num"
TYPE_EMAIL = "email"
loginURL = r"http://www.zhihu.com/login/{0}"
homeURL = r"http://www.zhihu.com"
captchaURL = r"http://www.zhihu.com/captcha.gif"

headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate",
"Host": "www.zhihu.com",
"Upgrade-Insecure-Requests": "1",
}

captchaFile = os.path.join(sys.path[0], "captcha.gif")
cookieFile = os.path.join(sys.path[0], "cookie")

def __init__(self):
os.chdir(sys.path[0]) # 设置脚本所在目录为当前工作目录

self.__session = requests.Session()
self.__session.headers = self.headers # 用self调用类变量是防止将来类改名
# 若已经有 cookie 则直接登录
self.__cookie = self.__loadCookie()
if self.__cookie:
print("检测到cookie文件,直接使用cookie登录")
self.__session.cookies.update(self.__cookie)
soup = BS(self.open(r"http://www.zhihu.com/").text, "html.parser")
print("已登陆账号: %s" % soup.find("span", class_="name").getText())
else:
print("没有找到cookie文件,请调用login方法登录一次!")

# 登录
def login(self, username, password):
"""
验证码错误返回:
{'errcode': 1991829, 'r': 1, 'data': {'captcha': '请提交正确的验证码 :('}, 'msg': '请提交正确的验证码 :('}
登录成功返回:
{'r': 0, 'msg': '登陆成功'}
"""
self.__username = username
self.__password = password
self.__loginURL = self.loginURL.format(self.__getUsernameType())
# 随便开个网页,获取登陆所需的_xsrf
html = self.open(self.homeURL).text
soup = BS(html, "html.parser")
_xsrf = soup.find("input", {"name": "_xsrf"})["value"]
# 下载验证码图片
while True:
captcha = self.open(self.captchaURL).content
with open(self.captchaFile, "wb") as output:
output.write(captcha)
# 人眼识别
print("=" * 50)
print("已打开验证码图片,请识别!")
subprocess.call(self.captchaFile, shell=True)
captcha = input("请输入验证码:")
os.remove(self.captchaFile)
# 发送POST请求
data = {
"_xsrf": _xsrf,
"password": self.__password,
"remember_me": "true",
self.__getUsernameType(): self.__username,
"captcha": captcha
}
res = self.__session.post(self.__loginURL, data=data)
print("=" * 50)
# print(res.text) # 输出脚本信息,调试用
if res.json()["r"] == 0:
print("登录成功")
self.__saveCookie()
break
else:
print("登录失败")
print("错误信息 --->", res.json()["msg"])

def __getUsernameType(self):
"""判断用户名类型
经测试,网页的判断规则是纯数字为phone_num,其他为email
"""
if self.__username.isdigit():
return self.TYPE_PHONE_NUM
return self.TYPE_EMAIL

def __saveCookie(self):
"""cookies 序列化到文件
即把dict对象转化成字符串保存
"""
with open(self.cookieFile, "w") as output:
cookies = self.__session.cookies.get_dict()
json.dump(cookies, output)
print("=" * 50)
print("已在同目录下生成cookie文件:", self.cookieFile)

def __loadCookie(self):
"""读取cookie文件,返回反序列化后的dict对象,没有则返回None"""
if os.path.exists(self.cookieFile):
print("=" * 50)
with open(self.cookieFile, "r") as f:
cookie = json.load(f)
return cookie
return None

def open(self, url, delay=0, timeout=10):
"""打开网页,返回Response对象"""
if delay:
time.sleep(delay)
return self.__session.get(url, timeout=timeout)

def getSession(self):
return self.__session

if __name__ == '__main__':
client = ZhiHuClient()

# 第一次使用时需要调用此方法登录一次,生成cookie文件
# 以后可以跳过这一步
client.login("username", "password")

# 用这个session进行其他网络操作,详见requests库
session = client.getSession()