使用 Travis 自动部署静态网站到 GitHub Pages

GitHub Pages 可以用来托管静态网站,而 Jekyll,Gitbook 等等程序都可以生成静态网站,那么如果使用 master 分之托管源码的话, gh-pages 分支就可以用来托管静态网站。而使用 Travis 就可以将每一次 master 分支的提交,自动编译静态站点之后提交到 gh-pages 分支。

既然要使用到 git 的推送,那么必然避不了需要验证,Travis 提供很多验证方式,这里有两种:

Encryption keys

加密 TOKEN,需要使用到 GitHub 提供的 Personal API tokens,Token 与 帐号密码 以及 SSH Keys 同样具有 Github 写入能力,因此只要使用 Travis CI 提供的加密工具来加密这个 Token 即可。

Travis CI 会使用一对密钥中的 Public Key 来加密提供的 TOKEN,然后得到的 secure token 可以安全地放在 .travis.yml 文件中,在 Build 的时候 Travis 会使用 Private Key 来解密这个 Secure Token 获取最初提供的 Github Personal Access Token,并使用该 TOKEN 来进行一系列操作。

操作具体步骤:

  1. 获取 GitHub Personal access tokens https://github.com/settings/tokens, Github 帐号 Settings 页面侧边栏最下面 Developer 中有 Personal access tokens。新建一个 token,只需要选择 repo 相关权限。创建完的 token 只会显示一次,保存好该 token 下面需要使用。
  2. 安装 travis 工具,需要提前安装好 Ruby 环境 gem install travis
  3. 使用 GitHub TOKEN 来登录 travis login --github <token>
  4. 生成 secure token travis encrypt GH_TOKEN=<token> ,使用 travis encrypt ... 命令会生成加密的字符串,把字符串添加到 .travis.yml 文件中

或者使用额外的参数 --add ... 比如 travis encrypt <token> --add deploy.github-token 可以自动添加到 .travis.yml 文件中,会自动在 deploy 下创建 github-token 来存放加密字符串。

更多的 travis 的使用可以 travis -h 来查看。

下面以 Gitbook 使用 Travis 自动编译部署到 GitHub Pages 为例,这里使用到了 Travis 的发布到 GitHub Pages 的功能

language: node_js

node_js:
  - "8"

before_install:
  - export TZ='Asia/Shanghai' # 更改时区

# 依赖安装
install:
  - npm install gitbook-cli -g
  # 安装 gitbook 插件
  - gitbook install

# 构建脚本
script:
    # 自定义输出目录 gitbook build src dest
    # 默认会输出到 _book 目录下
  - gitbook build .

# 分支白名单
branches:
  only:
    - master # 只对 master 分支进行构建

before-deploy:
- git config --local user.name "Ein Verne"
- git config --local user.email "git@einverne.info"

# GitHub Pages 部署
deploy:
  provider: pages
  skip_cleanup: true
  github_token:
    secure: <secure token>
  # 将下面的目录中内容推送到 gh-pages 分支
  local_dir: build
  fqdn: $CUSTOM_DOMAIN
  name: $GIT_NAME
  email: $GIT_EMAIL
  on:
    branch: master

大概原理就是如此,记住 skip_cleanup: true 这个一定要写上,否则 Travis 在 build 的时候会自动清理掉 repo 中编译生成的内容。

  • before_install 在安装之前,设置时区
  • install 安装依赖
  • script 执行真正的脚本
  • before_deploy 部署之前做的事情
  • deploy 部署发布内容

验证 travis 配置

本地使用命令

travis lint .travis.yml

实例使用可以参考这个例子

reference

  • https://www.jianshu.com/p/5f96c27baaa5

2018-04-06 github , git , travis , github-pages , jekyll , gitbook

Gitbook 使用记录

Git 本来是一个版本控制工具,多人协作工具,但却爆发出无限的潜能,于是有人开始使用Gitbook来写书,设计师们用Git来管理版本。这篇文章主要就是想要介绍一下 Gitbook 的简单使用。

Gitbook 使用 Markdown 作为书写格式,Git 来做版本控制,结合两者来编排书籍。Gitbook 的安装非常方便,在本地有 Node.js 和 npm 的环境下

npm install gitbook-cli -g
gitbook -V  # 检查版本

就能够安装 gitbook 命令。

Gitbook.com 是一个发布 gitbook 编写书籍的在线网站,提供公开和私有的托管服务,和 GitHub 一样,私有的 Gitbook 是需要付费使用的。但是公开的书籍是无上限的,使用在线的 Gitbook 可以让未接触过 Git 和 Markdown 的作者轻松的创建书籍,并且在线的编辑器可以让作者安心的只关心内容,而不必在意排版,并且支持多人协作编写。

  • GitBook项目官网:http://www.gitbook.io
  • GitBook Github地址:https://github.com/GitbookIO/gitbook

使用

gitbook 的使用可以简单的归纳为如下两步:

  • 使用 gitbook init 初始化书籍目录
  • 使用 gitbook build 编译书籍到静态网站
  • 使用 gitbook serve 本地访问书籍

在使用 gitbook init 之后本地会生成两个文件 README.mdSUMMARY.md ,这两个文件都是必须的,一个为本书介绍,一个为本书目录结构。

gitbook 插件

Gitbook 拥有很多插件来扩展 Gitbook 的功能,比如支持数学公式,支持Google统计,评论等等。插件可以在 https://plugins.gitbook.com/ 找到。

插件安装比较简单,在目录下添加 book.json 文件,填写下面格式

{
    "plugins": ["plugins1", "plugins2"],
    "pluginsConfig": {
        "plugins1": {...}
    }
}

注册完插件之后,安装插件 gitbook install。 插件开发可以参考官方文章

常用插件

如果不需要使用 Gitbook 自带的插件可以使用 - 来排除

"plugins" : [ "-search" ]

如果想知道更多关于 Gitbook 的使用,以及各种插件,主题的使用,可以具体参考 https://einverne.github.io/gitbook-tutorial

reference


2018-04-05 gitbook , git , github , book , publish

每天学习一个命令:vmstat 查看系统资源使用情况

vmstat 是一个收集和报告系统内存,swap,处理器资源的工具。

vmstat reports information about processes, memory, paging, block IO, traps, disks and cpu activity.

使用

vmstat 的使用非常简单,直接运行

vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0   9496 1632720 1179760 4628968    0    0     9    37   55   12  3  1 96  0  0

输出一大串数据,这一串数据是 vmstat 从开机到运行命令之间记录的平均数据。

vmstat [delay] [count]

第一行会打印平均值,之后每隔 [delay] 的时间,打印一次报告,在打印 [count] 次之后停止。

输出值解释

Procs
   r: The number of runnable processes (running or waiting for run time).
   b: The number of processes in uninterruptible sleep.

Memory
   swpd: the amount of virtual memory used.
   free: the amount of idle memory.
   buff: the amount of memory used as buffers.
   cache: the amount of memory used as cache.
   inact: the amount of inactive memory.  (-a option)
   active: the amount of active memory.  (-a option)

Swap
   si: Amount of memory swapped in from disk (/s).
   so: Amount of memory swapped to disk (/s).

IO
   bi: Blocks received from a block device (blocks/s).
   bo: Blocks sent to a block device (blocks/s).

System
   in: The number of interrupts per second, including the clock.
   cs: The number of context switches per second.

CPU
   These are percentages of total CPU time.
   us: Time spent running non-kernel code.  (user time, including nice time)
   sy: Time spent running kernel code.  (system time)
   id: Time spent idle.  Prior to Linux 2.5.41, this includes IO-wait time.
   wa: Time spent waiting for IO.  Prior to Linux 2.5.41, included in idle.
   st: Time stolen from a virtual machine.  Prior to Linux 2.6.11, unknown.

2018-04-04 linux , vmstat , memory , swap , processor

每天学习一个命令:parted 在 Linux 下给硬盘分区

parted 是 GNU 组织开发的一款功能强大的磁盘分区和分区大小调整工具,命令可以对磁盘进行分区和管理,和 fdisk 相比,能够支持 2T 以上磁盘。它可以处理最常见的分区格式,包括:ext2、ext3、fat16、fat32、NTFS、ReiserFS、JFS、XFS、UFS、HFS 以及 Linux 交换分区。

功能特点:

  • 能够创建、清除、调整、移动和复制 ext2, ext3, ext4, linux swap, fat32, ntfs 等分区
  • 能够重新分配磁盘使用情况

parted 有两种使用方式

命令行方式

定义分区表格式

parted -s /dev/sda mklabel gpt

划分主分区

parted -s /dev/sda mkpart primary ext4 1 10G

划分逻辑分区

parted -s /dev/sda mkpart logic 10G 20G

查看分区情况

parted -s /dev/sda p

直接使用一行命令来完成分区操作

parted /dev/sdb mklabel gpt mkpart 1 ext4 1 5T

交互命令方式

使用 parted /dev/sdb 来进入对 /dev/sdb 硬盘的管理。

在交互命令下可以使用如下命令

交互命令 功能
mklabel gpt 定义分区表格式,常用的有 msdos 和 gpt 分区格式,2T 以上硬盘选用 gpt
mkpart p1 创建第一个分区,名称为 p1,在使用该命令后会选择分区的格式,分区起始位置,分区的结束位置
print 查看当前分区情况
rm 删除分区,之后会选择想要删除的分区‘
help 帮助

在划分分区之后,可以使用

mkfs.ext4 /dev/sdb1

来针对 sdb 磁盘上第一块分区进行格式化。然后挂载分区 mount /dev/sdb1 /mnt/sdb1

对于一块新的硬盘,如果没有 GUI 的界面来进行格式化,就需要用到这个命令了。


2018-04-03 linux , parted , gparted , partition , clonezilla

Linux 交换分区

Linux 内核为了提高读写效率与速度,会将文件在内存中进行缓存,这部分内存就是 Cache Memory(缓存内存)。即使你的程序运行结束后,Cache Memory 也不会自动释放。这就会导致你在 Linux 系统中程序频繁读写文件后,你会发现可用物理内存变少。

Linux divides its physical RAM (random access memory) into chucks of memory called pages. Swapping is the process whereby a page of memory is copied to the preconfigured space on the hard disk, called swap space, to free up that page of memory. The combined sizes of the physical memory and the swap space is the amount of virtual memory available.

Swap space in Linux is used when the amount of physical memory (RAM) is full. If the system needs more memory resources and the RAM is full, inactive pages in memory are moved to the swap space. While swap space can help machines with a small amount of RAM, it should not be considered a replacement for more RAM. Swap space is located on hard drives, which have a slower access time than physical memory.Swap space can be a dedicated swap partition (recommended), a swap file, or a combination of swap partitions and swap files.

Linux 通过一个参数 swappiness 来控制 swap 分区使用情况,swappiness 是控制系统使用 swap 分区的频率阈值,当 swappiness = 100 时,系统会积极使用 swap 分区,而当 swappiness = 0 时,系统会最大限度的使用物理内存。

Swappiness is a property for the Linux kernel that changes the balance between swapping out runtime memory, as opposed to dropping pages from the system page cache. Swappiness can be set to values between 0 and 100 inclusive. A low value means the kernel will try to avoid swapping as much as possible where a higher value instead will make the kernel aggressively try to use swap space. The default value is 60, and for most desktop systems, setting it to 100 may affect the overall performance, whereas setting it lower (even 0) may improve interactivity (decreasing response latency.)[1]
In short:
vm.swappiness = 0 - it will swap only to avoid an out of memory condition
vm.swappiness = 60 - default value
vm.swappiness = 100 - it will swap aggressvely
To temporarily set the swappiness in Linux, as root you set the value to 100 with the following command: echo 100 > /proc/sys/vm/swappiness
Permanent changes are made in /etc/sysctl.conf via the following configuration line (inserted if not present previously): vm.swappiness = 100

临时修改 swappiness 值可以通过以下两种方式:

手动修改文件

vim /proc/sys/vm/swappiness
# or
echo 10 > /proc/sys/vm/swappiness

或者

sysctl vm.swappiness=10

永久修改 swappiness 参数的方法就是在配置文件 /etc/sysctl.conf 里面修改 vm.swappiness 的值,然后重启系统

echo 'vm.swappiness=10' >>/etc/sysctl.conf

swap 分区操作

查看 swap 分区大小及使用情况,使用 free 命令

free -h

也可以使用 swapon 查看 swap 分区信息

swapon -s                   # --summary 显示 swap 的使用情况
swapon --show               # 显示结果更好看

也可以直接查看文件

cat /proc/swaps             # 和 swapon -s 相同

关闭交换分区

swapoff /dev/mapper/VolGroup00-LogVol01

缩小 swap 分区

lvreduce -L 8G /dev/mapper/VolGroup00-LogVol01

格式化 swap 分区

mkswap /dev/mapper/VolGroup00-LogVol01

启动 swap 分区,并增加到 /etc/fstab 自动挂载

swapon /dev/mapper/VolGroup00-LogVol01

swap 分区建立

在装完 Linux 系统之后,建立 Swap 分区有两种方法:

  1. 新建磁盘分区作为 swap 分区
  2. 用文件作为 swap 分区

swap 分区大小设置

4G 以内的物理内存,SWAP 设置为内存的 2 倍。
4-8G 的物理内存,SWAP 等于内存大小。
8-64G 的物理内存,SWAP 设置为 8G。
64-256G 物理内存,SWAP 设置为 16G。

新建磁盘分区作为 swap 分区

以 root 身份登入控制台,输入

swapoff -a              #停止所有的 swap 分区

用 fdisk 命令对磁盘进行分区,添加 swap 分区,新建分区,在 fdisk 中用”t”命令将新添的分区 id 改为 82(Linux swap 类型),最后用 w 将操作实际写入硬盘

fdisk /dev/sdb

格式化 swap 分区,这里的 sdb2 要看您加完后 p 命令显示的实际分区设备名

mkswap /dev/sdb2

启动新的 swap 分区

swapon /dev/sdb2

为了让系统启动时能自动启用这个交换分区,可以编辑 /etc/fstab, 加入下面一行

/dev/sdb2 swap swap defaults 0 0

使用文件作为 swap 分区

创建要作为 swap 分区的文件:增加 1GB 大小的交换分区,则命令写法如下,其中的 count 等于想要的块的数量(bs*count= 文件大小)。

dd if=/dev/zero of=/root/swapfile bs=1M count=1024

格式化为交换分区文件:

mkswap /root/swapfile #建立 swap 的文件系统

启用交换分区文件:

swapon /root/swapfile #启用 swap 文件

使系统开机时自启用,在文件 /etc/fstab 中添加一行:

/root/swapfile swap swap defaults 0 0

2018-04-02 linux , swap , partition

使用 Phabricator 来review

Phabricator 是最早发源于 Facebook 的代码review工具, 后来创始人离开 Facebook 独立开发这款工具. Phabricator 和同类型的 Google 的 gerrit 有着相似的功能

  1. Phabricator 会将所有文件diff直接展开, 而Gerrit只有一个文件列表,需要点每一个文件看具体修改;
  2. admin的权限设置区别
  3. Phabricator 可以附加 unit test和以及格式检查和规范的工具(e.g. JSLint), 然后用户在上传diff的时候, Phabricator会自动用新版本代码去跑unit tests,以及运行JSLint, 然后在code review里面就可以看到unit tests有几个failure和error,以及JSLint的报警信息

Arcanist

Phabricator 提供了个命令行叫 arc (Arcanist),使用 arc 命令来连接开发者和 Phabricator 服务器。

安装 Arcanist

Mac OS

brew install node
npm install -g arcanist
arc help
arc upgrade

Ubuntu/Debian/Linux Mint

在 Linux 下使用

sudo apt update && sudo apt-get install php7.0-cli php7.0-curl php-pear

# 任意其它目录也可以
mkdir ~/phabricator
cd ~/phabricator
# 如果下载慢的话,可以先尝试设置一下proxy: export https_proxy="ip:3128"
git clone https://github.com/facebook/libphutil.git
git clone https://github.com/facebook/arcanist.git

# 编辑~/.bashrc,加入如下一行,之后source ~/.bashrc
export PATH="$PATH:$HOME/phabricator/arcanist/bin/"
# 如果没有项目配置,可以运行下面的命令设置全局的参数:
arc set-config default https://<phabricator server address>
arc install-certificate
# 按照屏幕提示,访问http://<phabricator server address>/conduit/token/ ,把token copy/paste下来
# 在~/.bashrc里添加下面两行
export EDITOR=vim
alias arc='LC_ALL=C arc'
# 并在命令行执行
source ~/.bashrc

Windows

自行处理: https://www.jianshu.com/p/a6ee738da1aa

配置

一般情况下在 HOME 目录下会产生一个 .arcrc 配置文件,格式类似下方:

{
  "config": {
    "default": "https://<phabricator server address>",
    "editor": "vim"
  },
  "hosts": {
    "https://<phabricator server>/api/": {
      "token": "cli-rdm2xxxxxxxxxxxx"
    }
  }
}

可以使用如下命令来更改该配置

arc set-config phabricator.uri "<phabricator server>"
arc set-config editor "vim"

本地开发流程

如下:

# 本地开发,新建feature
arc feature feature_1
# 或 git checkout -b feature_1
# 修改本地文件,然后提交
git add
git commit
 
# 提交code review
arc diff
# 通过--reviewers name参数可以指定reviewer
 
# 这里可以和一个Task(比如T123)关联起来,在Summary那个域里填上Ref T123,或者Fixes T123
# 两者的区别是Fixes在代码提交后会自动关闭Task,Ref不会
# 也可以提交code review之后,在浏览器里操作
 
# 本地修改后再次提交code review(这个revision是上次创建code review时的id,比如D1252)
arc diff --update 1252
# --update 1252 也可以不加,默认会合到上一个review中
 
# reviewer已经Accept之后,提交代码(不要用git push!):
arc land feature_1
# 如果报错找不到对应的revision,带上revision号(比如1252)运行:
arc land --revision 1252
# land之后,feature branch会被自动删除
# land 使用后会将当前分支 merge 或者squash merge 到master分支,提供详细的提交信息,推送到master并且删除本地分支

QA

问题: No changes found. (Did you specify the wrong commit range?)

答: Arcanist(arc) 是一个 pre-commit 或者说 pre-push 代码审查工具,一旦本地分支被push到origin,这就打破了 Arcanist 工具的意义,但是可以用以下方法来补救:

  • 删除当前分支的远端分支 git push origin --delete branch_name
  • 在使用 arc diff 时告诉分支需要和哪一个分支对比 arc diff origin/master
  • 或者显示指定 land 的目的地 arc land --onto master

2018-03-29 code review , git , version control , php , mysql , gerrit

使用 click 构造漂亮的Python命令行程序

Click 是 Python 下一款命令行库,可以用来快速轻松实现Python命令行程序。之前也介绍过一个 argparse ,但是要比 click 复杂很多,至少从代码上看。但是 click 其实也说了1 argparse 在标准库中,click 是依赖于 optparse 的,至于不基于 argparse 是因为 argparse 不支持嵌套,并且在 POSIX 兼容上有问题。

Click 被设计用来快速构建命令行程序,因此缺乏一些扩展性,比如他不允许高度定制help介绍。Click 是用来支持 Flask 开发框架的。

官网地址: http://click.pocoo.org

基本使用

# hello.py
import click
@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

if __name__ == '__main__':
    hello()

然后可以这样运行该脚本 python hello.py --count=3,并且 Click 还会自动生成 help 信息。

Option 参数

Click 使用基本可以归纳为

  • 使用 @click.command() 装饰一个函数,使之成为命令行接口;
  • 使用 @click.option() 等装饰函数,为其添加命令行选项等。

最基础的用法, option 接受一个变量

@click.command()
@click.option('--n', default=1)
def hello(n):
    click.echo('hello' * n)

使用 --n=2 输出两遍

接受多个变量,需要使用 nargs 指定数量

@click.command()
@click.option('--pos', nargs=2, type=float)
def cal(pos):
    click.echo('%s / %s' % pos)

使用 --pos 5.0 4.0

如果参数是固定的几个值,可以使用可选项

@click.command()
@click.option('--hash-type', type=click.Choice(['md5', 'sha1']))
def digest(hash_type):
    click.echo(hash_type)

使用 --hash-type=md5 参数只能为 md5 或者 sha1,否则报错。

option 还有其他一些参数,比如 prompt 当用户忘记该参数时,将错误报出来,hide_input 可以隐藏输入,常用于密码输入,confirmation_prompt 验证输入等等。

Click 封装了

@click.password_option()
@click.confirmation_option(prompt='Are you sure you want to drop the db?')

argument 参数

和 Option 一样,Argument 最基础的应用就是传递一个简单变量值

@click.command()
@click.argument('input', type=click.File('rb'))
@click.argument('output', type=click.File('wb'))
def inout(input, output):
    while True:
        chunk = input.read(1024)
        if not chunk:
            break
        output.write(chunk)

reference

  1. http://click.pocoo.org/6/why/ 


2018-03-27 python , flask , click , command

每天学习一个命令:vnstat 统计服务器网卡流量

vnStat 是一款开源的网络流量统计工具,可以方便的查看当天,当月流量统计。官网地址:

https://humdi.net/vnstat/

安装

在 Debian/Ubuntu 下非常简单

sudo apt install vnstat vnstati

假设网卡名为 eth0,该配置在 /etc/vnstat.conf 中,安装结束后初始化数据库

sudo vnstat -u -i eth0

添加为开机启动

sudo update-rc.d vnstat enable

使用

直接输入 vnstat

vnstat -l  # 或者 `--live` 实时流量
vnstat -h  # 显示小时流量
vnstat -d  # 显示日流量信息
vnstat -w  # 显示周流量信息
vnstat -m  # 显示月流量信息
vnstat -t  # 显示流量最高top10天

图形化输出可以使用 vnstati ,将月流量统计图输出到图片

vnstati -i eth0 - -months - -output /dir/month.png

2018-03-26 linux , vnstat , network

Jigsaw Outline 部署和使用

官方主页: https://getoutline.org/en/home 项目地址: https://github.com/Jigsaw-Code

Outline 细分有三部分,分别是 Outline Manager, Outline Server 和 Outline Client。

  • Outline Manager:方便用户管理所有的 Outline Server,可以使用图形化界面快捷部署 Outline Server ,然后为每一位用户生成连接秘钥,使得用户可以安全连接 Outline Server 。
  • Outline Server:用来提供安全代理的服务,响应、验证 Outline Client 的所有请求,仅此而已。
  • Outline Client:用来向 Outline Server 发起请求,或接受其返回的数据,仅此而已。

部署服务端

在安装 Docker 之后安装

wget -qO- https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh | bash

在脚本安装结束后会生成一段配置,复制并保存该配置,在客户端配置中需要使用。

客户端使用

先下载 Outline Manager,地址

https://github.com/Jigsaw-Code/outline-releases

下载其中的 Outline-Manager.AppImage ,这是 Linux 下的客户端,不同系统中下载不同客户端。然后在 Manager 中粘贴上面服务端配置,完成 Manager 配置。然后在 Manager 中点击 ADD KEY 生成可用的 KEY。点击分享将生成一个托管在 Amazon S3 上的静态网页,其中有 Shadowsocks 客户端的配置,将该字符串发送给客户端即可。

然后再下载 client 客户端,目前暂时 Jigsaw 还没提供 iOS 和 Mac 版本,但是 Windows 和 Android 客户端可以在 GitHub 和 Play Store 链接 找到。

在手机上输入上面 Manager 生成的 SS 配置即可连接。安装配置过程将 Shadowsocks 的部署配置流程完全简化了。期待Google Jigsaw 能够将这个项目继续维护下去吧。


2018-03-26 linux , docker , socks , google , vpn

使用 Python 下载抖音无水印视频

抖音 APP 中保存到本地就是无水印版本的,所以头条的服务器肯定是保存有无水印版本的抖音视频的,所以只要找到接口地址就可以搞定。先在网上搜罗了一圈,确实有人已经做了解析,还提供了收费解析服务

搜索之后发现又发现了同类型的其他

  • http://douyin.iiilab.com/
  • http://www.dyapp.cc/
  • https://app886.cn/douyin_video

分析接口

分析这几个页面就会发现他们通过分享的链接就能够拿到视频的直接链接肯定是通过接口获取的,所以通过 Android 抓包能找到类似下面的接口

https://aweme.snssdk.com/aweme/v1/play/?
video_id=v0200fd80000bejku38697aj8tin1brg
&line=0
&ratio=720p
&watermark=1
&media_type=4
&vr_type=0
&test_cdn=None
&improve_bitrate=0
&version_code=270

这个请求返回状态码是 302,返回的 response header 中 Location 标示了该视频的真实地址。

后来分析抖音的 Feed 流设计,又发现了另外一个接口

https://api.amemv.com/aweme/v1/play/?video_id=v0200fd80000bejhsoir863vmi5add60&line=0&ratio=720p&media_type=4&vr_type=0&test_cdn=None&improve_bitrate=0

也类似于上面的接口不过域名不同,参数也类似。

入手

入手的几个页面,分享页

https://www.iesdouyin.com/share/video/6604280853952466190/?region=CN&mid=6601014204340275975&u_code=df31b2ff&titleType=title
http://v.douyin.com/dqv3dv/

第二条是短链接,展开就是上面的长链接了。

在分享页面获取视频的 id,然后使用上面的链接获取视频的播放地址。

大致的思路如下

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import re
from urllib.request import urlopen

import requests
from tqdm import tqdm


class DouyinVideoInfo:
    def __init__(self, vid, title='', nickname=''):
        self.video_id = vid
        self.title = title
        self.nickname = nickname


def download(url, filename, name):
    """
    :param url: 视频直接链接
    :param filename: 保存文件名
    :param name: 进度条内容
    :return:
    """
    file_size = int(urlopen(url).info().get('Content-Length', -1))

    if os.path.exists(filename):
        first_byte = os.path.getsize(filename)
    else:
        first_byte = 0
    if first_byte >= file_size:
        return file_size
    header = {"Range": "bytes=%s-%s" % (first_byte, file_size),
              'User-Agent': 'okhttp/3.10.0.1'}
    pbar = tqdm(total=file_size, initial=first_byte,
                unit='B', unit_scale=True,
                desc=name)
    req = requests.get(url, headers=header, stream=True)
    with(open(filename, 'wb')) as f:
        for chunk in req.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)
                pbar.update(1024)
    pbar.close()
    return file_size


def down_by_vid(info: DouyinVideoInfo):
    r = requests.get('https://api.amemv.com/aweme/v1/play/', params={
        'video_id': info.video_id,
        'line': 0,
        'ratio': '720p',
        'watermark': 0,
        'media_type': 4,
        'vr_type': 0,
        'test_cdn': 'None',
        'improve_bitrate': 0,
        'logo_name': 'aweme'
    }, headers={
        'Host': 'api.amemv.com',
        'sdk-version': '1',
        'X-SS-TC': '0'
    }, allow_redirects=False)
    print(r.headers['Location'])
    download(r.headers['Location'], '{}.mp4'.format(info.video_id), info.title)


def get_video_info(long_url) -> DouyinVideoInfo:
    Headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'max-age=0',
        'upgrade-insecure-requests': '1',
        'user-agent': 'Mozilla/5.0 (Linux; U; Android 5.1.1; zh-cn; MI 4S Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.146 Mobile Safari/537.36 XiaoMi/MiuiBrowser/9.1.3',
    }
    r = requests.get(long_url, headers=Headers)
    video_id = re.findall("(?<=video_id=).+?(?=&amp)", r.text)[0]
    title_name = re.findall("(?<=desc\">).+?(?=</p>)", r.text)[0]
    nick_name = re.findall("(?<=bottom-user\">).+?(?=</p>)", r.text)[0]
    info = DouyinVideoInfo(video_id, title_name, nick_name)
    return info


if __name__ == '__main__':
    d1 = 'https://www.iesdouyin.com/share/video/6604280853952466190/?region=CN&mid=6601014204340275975&u_code=df31b2ff&titleType=title'
    d2 = 'https://www.douyin.com/share/video/6536906252729978119/?region=CN&mid=6441083920867035918&titleType=title&timestamp=1522052360&utm_campaign=client_share&app=aweme&utm_medium=ios&iid=27151889375&utm_source=copy'
    info = get_video_info(d2)
    down_by_vid(info)

2018-03-25 douyin , 抖音 , python

电子书

最近文章

  • MySQL 中的日志配置和管理 MySQL 中默认是没有开启日志记录的,所以需要手动修改配置文件开启日志。而在 MySQL 中我们需要关心的有三类日志:
  • Java 查漏补缺之:ThreadLocal 使用 ThreadLocal 线程本地变量,每个线程保存变量的副本,对副本的改动,对其他的线程而言是透明的。
  • 为知笔记导出和备份 WizNote 已经用了好几年,虽然也一直在续费,但总感觉将死不死,基于整理这几年近 4000 条的笔记的目的,也一方面为迁移出 WizNote 的目的,研究一下 WizNote 笔记导出和备份的方法。
  • Nginx location 匹配规则 之前的关于 Nginx Config 的文章是当时看 Nginx 书记录下来的笔记,很大略,没有实际操作,等终究用到 location 的时候发现还是有很多需要注意的问题,比如匹配的优先顺序,比如 root 和 alias 的区别等等,所以单独拿一篇文章来记录一下目前遇到的问题,并来解决一下。
  • koajs 简单使用 Koa 是一个背靠 Express 的团队设计的全新的 Web 框架,旨在使之成为一个更轻量,更丰富,更加 robust 的基础框架。通过促进异步方法的使用,Koa 允许使用者抛弃 callback 调用,并且大大简化了错误处理。Koa 并没有将中间件绑定到核心代码,而是提供了一组优雅的方法让编写服务更加快速,通过很多第三方的扩展给 Koa 提供服务,从而实现更加丰富完整的 HTTP server。