Web自动化

自动化测试

自动化测试是软件开发过程中的一个重要环节,它有许多好处,主要有:

1.持续集成和持续部署:自动化测试是实现持续集成(CI)和持续部署(CD)的关键。在每次代码提交后,自动化测试可以立即运行,确保新的改动没有破坏现有的功能。

2.回归测试:当代码发生更改时,自动化测试可以帮助检查现有功能是否仍然正常工作。

3.提高软件质量:通过自动化测试,可以更早地发现和修复问题,从而提高软件的总体质量。

4.节省成本:虽然自动化测试需要一定的初期投入,但是长期来看,它可以减少因为错误和问题而产生的维护成本。

总的来说,前端自动化测试可以提高开发团队的效率,提高软件质量,减少错误,帮助团队更快地发布更高质量的产品。

接口自动化测试

除了传统用代码写测试用例外,市面上有很多产品可以直接进行接口测试如:

postman

https://www.postman.com/downloads/

PostmanCanary

https://www.postman.com/downloads/canary/

insomnia

https://insomnia.rest/download/

ApiPost

https://www.apipost.cn/download.html

https://www.eolink.com/

apifox

https://www.apifox.cn/

前端web自动化测试

实现Web自动化同样有很多工具,如模拟图形化操作的xdotool,常见Playwright、Puppeteer、selenium,或者DrissionPage:

xdotool

参考这份笔记:http://git.malu.me/xdotool自动化工具笔记/

Playwright

Python版文档:https://playwright.dev/python/docs/intro

Playwright 是一个开源的自动化测试工具,由 Microsoft 发布,专为测试现代 Web 应用而设计。它支持多种浏览器,包括 Chromium(Chrome 和 Edge)、Firefox 和 WebKit(Safari),使得跨浏览器测试变得简单。Playwright 允许开发者编写用于自动化浏览器操作的脚本,包括页面导航、元素选择、输入、文件上传下载等操作,以及捕捉网络活动、模拟移动设备、地理位置等高级功能。

Playwright 的主要特点包括:

  1. 跨浏览器支持:能够在所有主流浏览器上运行相同的测试脚本。
  2. 无头模式和图形界面模式:支持无头(headless)模式运行测试,这在 CI/CD 环境中非常有用,同时也支持有界面(headful)模式,方便开发时调试。
  3. 快速准确:通过等待元素可用而非固定时间等待,提高了测试的准确性和执行速度。
  4. 现代 Web 功能支持:支持最新的 Web 功能,包括但不限于网络存储、服务工作者、WebSockets 等。
  5. 丰富的 API:提供了一套丰富的 API,能够模拟几乎所有用户操作,并且能够处理复杂的 Web 应用场景。
  6. 多语言绑定:虽然 Playwright 本身是用 TypeScript/JavaScript 开发的,但它也提供了 Python、Java 和 C# 的绑定,使得非 JavaScript 开发者也能够轻松使用。

Playwright 适用于端到端的测试,包括功能测试、视觉回归测试和性能测试等。它通过提供一致的 API 来简化测试脚本的编写和维护工作,帮助开发者和测试工程师提高 Web 应用的质量和稳定性。

记录脚本

命令行界面CLI可用于记录用户交互并生成 Python 代码

playwright codegen malu.me

地址栏带多个传参解决办法:

set url="https://malu.me?aa=aa^^^&bb=bb^^^&cc=cc"
playwright codegen %url%

代码段

兄弟选择器,比如选择选择 text为“最近使用”的下面的兄弟div,可以使用布局选择器:https://playwright.dev/python/docs/selectors#selecting-elements-based-on-layout

page.click('div:below(:text("最近使用"))')

MediaCrawler

能抓小红书、抖音、快手、B站、微博的视频、图片、评论、点赞、转发等信息。

原理:利用playwright搭桥,保留登录成功后的上下文浏览器环境,通过执行JS表达式获取一些加密参数

Puppeteer

puppeteer是谷歌chrome团队出的,支持chrome原生录制脚本,支持chrome无头模式,可模拟移动端,node编写,语法精炼,性能强劲。

API文档:https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md

原生录制

Recorder参考文档:https://developer.chrome.com/docs/devtools/recorder/reference

puppeteer 自动收取邮件示例:

const puppeteer = require('puppeteer');

// 注意该路径会和原始用户配置冲突,如果要用用户配置启动,请把开着的chrome先全部关闭
const user_data_path = String.raw`${process.env.LocalAppData}\Google\Chrome\User Data`;
const chrome_exe = String.raw`${process.env["ProgramFiles(x86)"]}\Google\Chrome\Application\chrome.exe`;

const autoSubmitForm = async (url) => {
    // 启动浏览器
    const browser = await puppeteer.launch({
        // 关闭无头模式,方便我们看到这个无头浏览器执行的过程
        headless: false,
		// 取消加载默认配置
		// ignoreDefaultArgs: true,
        // chrome 启动参数
        args: ['--no-sandbox'],
        // 显示chrome log信息和错误信息
        dumpio: true,
		userDataDir: user_data_path,  // 浏览器用户路径(可选)
		executablePath: chrome_exe,  //调用浏览器位置(可选)
    });

    // 打开页面
    const page = await browser.newPage();
    // 设置浏览器视窗
    page.setViewport({
        width: 1920,
        height: 1080,
    });
    // 地址栏输入网页地址
    await page.goto(url, {
        waitUntil: 'networkidle2', // 等待网络状态为空闲的时候才继续执行
    });

    // 点头像登录
    await page.mouse.click(1300,441);
    await page.waitFor(3000);
    // 点代收邮箱
    await page.mouse.click(80,376);
    await page.waitFor(2000);
    while (true) {
        // 点收取
        await page.mouse.click(265, 119);
        await page.waitFor(60000*5);
    }
};

if (require.main === module) {
    autoSubmitForm('http://mail.qq.com/cgi-bin/frame_html');
}

puppeteer 中启用扩展

默认情况下puppeteer关闭了扩展,具体代码在 node_modules\puppeteer\lib\Launcher.js

const DEFAULT_ARGS = [
'--disable-background-networking',
'--disable-background-timer-throttling',
'--disable-breakpad',
'--disable-client-side-phishing-detection',
'--disable-default-apps',
'--disable-dev-shm-usage',
'--disable-extensions',
....

我们可以在启动时关闭它:

ignoreDefaultArgs: true,

Selenium

Selenium 是一个用于 Web 自动化的开源工具。它可以用于自动化 Web 应用程序的测试、爬虫和其他操作。

Selenium 由两个主要部分组成:

  • Selenium WebDriver:用于控制浏览器并与 Web 元素进行交互。
  • Selenium IDE:一个用于记录和回放 Selenium 测试的集成开发环境。

Selenium 支持多种编程语言,包括 Python、Java、C#、JavaScript 等。

使用 Python 使用 Selenium

要使用 Python 使用 Selenium,您需要做的第一件事是安装 Selenium 库。您可以使用 pip 工具进行安装:

pip install selenium

安装 Selenium 库后,您就可以开始编写 Selenium 脚本了。

以下是一个简单的示例,用于打开首页并搜索“Selenium”:

from selenium import webdriver

# 创建一个 WebDriver 实例
driver = webdriver.Chrome()

# 打开首页
driver.get("https://malu.me")

# 在搜索框中输入“Selenium”
search_box = driver.find_element_by_name("q")
search_box.send_keys("Selenium")

# 提交搜索
search_box.submit()

# 关闭浏览器
driver.quit()

Selenium 的优势

Selenium 具有以下优势:

  • 开源且免费
  • 支持多种编程语言
  • 支持多种浏览器
  • 易于使用
  • 功能强大

Selenium 的应用场景

Selenium 可用于以下场景:

  • Web 自动化测试
  • Web 爬虫
  • 自动化表单填写
  • 自动化数据提取
  • 自动化操作 Web 应用程序

Selenium 是一个强大的 Web 自动化工具。它可以用于自动化 Web 应用程序的测试、爬虫和其他操作。

DrissionPage

文档:https://g1879.gitee.io/drissionpagedocs/

Linux下安装

wget "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb" -O chrome.deb

dpkg -i chrome.deb

# apt-get install libatk1.0-0   # 可不执行
apt --fix-broken install

pip install DrissionPage

example:

_base.py

#!/usr/bin/env python
# 将上级目录绝对路径加入到path路径列表中
import os,sys

sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from DrissionPage import WebPage, ChromiumOptions
from Monitor.WEB_monitor.check_model import CKM

class BASE():
    '''监测模块基类'''

    STD_MSG = '(说明:如果标准差偏大表示数列存在异常)'
    URL_TIMEOUT = 20

    def _base(self,url,title):
        '''监测基础方法'''
        # 检查模块
        self.C = CKM()
        URL = url
        print(f'监测模块: {title}',"\n请求地址:", self.C.color_url(URL))
        return self._create_browser()

    def _create_browser(self,args=None):
        co = ChromiumOptions()
        if os.name != 'nt':
            '''Linux'''
            co = co.set_browser_path(r'/opt/google/chrome/google-chrome')
            co = co.set_argument('--no-sandbox') # 解决$DISPLAY报错
            # co = co.set_argument('--headless=new')
            co = co.set_headless(True)  # 解决浏览器无法连接报错
        else:
            # co = co.set_browser_path(r'C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe')
            pass
        if args is not None:
            if args.proxy is not None:
                co.set_proxy(args.proxy)
        # co = co.use_system_user_path()
        # co = co.set_paths(
        #     # local_port='9888',
        #     # browser_path=r'.\Chrome\chrome.exe',
        #     user_data_path=r'C:\Users\ml\AppData\Local\Google\Chrome\User Data\Default'
        #     )
        page = WebPage(chromium_options=co)
        return page

APP自动化

appium

环境: $ node -v v20.11.0 $ npm -v 10.2.4

npm i -g appium

查看全局已经安装的包

npm list -g –depth=0

手机开启调试

设置-我的设备-全部参数与信息-连续点击OS版本

设置-更多设置-开发者选项-开启开发者选项->无线调试开启

adb下载 Android SDK Platform tools :https://developer.android.com/tools/releases/platform-tools?hl=zh-cn

adb说明文档 https://android.googlesource.com/platform/packages/modules/adb/+/refs/heads/main/docs/user/adb.1.md

使用配对码配对设备

adb pair HOST[:PORT] [PAIRING CODE]

然后连接

adb connect 192.168.x.xxx:xxx  // 无线调试的IP地址及端口

查看设备列表和transport_id

adb devices -l

截个图试试(在cmd下)

adb -t 9 shell screencap /sdcard/screenshot.png

adb -t 9 pull /sdcard/screenshot.png Desktop/aa.png

要使用 adb 获取手机中的应用程序列表,可以使用以下命令:

adb shell pm list packages

获取包名和界面名

adb shell dumpsys window|findstr mCurrentFocus

PC控制手机

推荐用 QtScrcpy

scrcpy :

将安卓设备的屏幕映射到计算机上,并通过键盘和鼠标控制设备:

scrcpy -K -f -m1920 --tcpip=192.168.1.101:1111

调用camera

scrcpy --video-source=camera --no-audio --camera-facing=front -m1920 --camera-ar=16:9 --camera-fps=60 --orientation=flip90 -f --tcpip=192.168.1.101:1111

写个脚本

@REM utf-8防止乱码
chcp 65001
set /p var=请输入端口:
C:\auto_run\bin\scrcpy-win64-v2.4\scrcpy.exe -K -m1920 --window-title=malu --tcpip=192.168.1.101:%var%

快捷键

实体键盘控制    alt+k    (使用键盘时开启屏幕键盘)
最近           alt+s
返回           alt+b     alt+回退键
通知           alt+n

mDNS:

检查adb的mdns启用状态

adb mdns check
adb mdns services

Linux下开启mDNS 参考:locate-hosts-using-mdns

apt install avahi-daemon
avahi-daemon
systemctl status avahi-daemon.service

如需启用 adb 的 mDNS 发现功能,请运行以下命令:

adb mdns说明 https://developer.android.com/tools/adb#mdnsBackends

adb mdns操作步骤 https://source.android.google.cn/docs/devices/automotive/virtualization/tools

set ADB_MDNS_OPENSCREEN=1     # Windows
export ADB_MDNS_OPENSCREEN=1  # Linux

# 查看变量
echo %ADB_MDNS_OPENSCREEN%    # Windows
echo $ADB_MDNS_OPENSCREEN     # Linux

adb kill-server
adb start-server

React

注释写法

var content = (
  <Nav>
    {/* 一般注释, 用 {} 包围 */}
    <Person
      /* 多
         行
         注释 */
      name={window.isLoggedIn ? window.name : ''} // 行尾注释
    />
  </Nav>
);

fetch 跨域

要使浏览器发送包含凭据的请求(即使是跨源来源),请添加credentials: ‘include’到init传递给该fetch()方法的对象。

fetch('https://example.com', {
  credentials: 'include'  
})

如果您只想在请求URL与调用脚本位于相同的源时发送凭据,请添加 credentials: ‘same-origin’。

// The calling script is on the origin 'https://example.com'

fetch('https://example.com', {
  credentials: 'same-origin'  
})

要改为确保浏览器不在请求中包含凭据,请使用credentials: ‘omit’。

// 使用omit来解决跨域报错 !!!

fetch('https://example.com', {
  credentials: 'omit'  
})

参考文档:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

webstorm ES6转ES5

安装 babel-cli 和 babel-preset-es2015

npm install --save-dev babel-cli
npm install --save-dev babel-preset-es2015

然后在项目目录下创建 .babelrc 文件:

{
  "presets": ["es2015"]
}

打开 settings -> Tools -> File Watchers,新建一个Babel, 把 –presets env 参数改成 –presets es2015

PHP多版本安装记录

系统环境:Ubuntu 14.04、apache+php5.5

同时安装多个版本PHP

先添加ppa源

add-apt-repository ppa:ondrej/php
apt-get update

安装php5.5 (默认已存在不用装)

apt-get install -y php5-common php5-mcrypt php5-mysql php5-gd php5-curl php5-json php5-fpm php5-mcrypt libapache2-mod-php5

安装php5.6

apt-get install -y php5.6-common php5.6-mbstring php5.6-mcrypt php5.6-mysql php5.6-xml php5.6-gd php5.6-curl php5.6-json php5.6-fpm php5.6-zip php5.6-intl php5.6-dev libapache2-mod-php5.6

安装php7.0

apt-get install -y php7.0-common php7.0-mbstring php7.0-mcrypt php7.0-mysql php7.0-xml php7.0-gd php7.0-curl php7.0-json php7.0-fpm php7.0-zip php7.0-intl libapache2-mod-php7.0

安装php7.1

apt-get install -y php7.1-common php7.1-mbstring php7.1-mcrypt php7.1-mysql php7.1-xml php7.1-gd php7.1-curl php7.1-json php7.1-fpm php7.1-zip php7.1-intl libapache2-mod-php7.1

安装php7.2

apt-get install -y php7.2-common php7.2-mbstring php7.2-mysql php7.2-xml php7.2-gd php7.2-curl php7.2-json php7.2-fpm php7.2-zip php7.2-intl libapache2-mod-php7.2

注:

PPA包名查找: https://launchpad.net/~ondrej/+archive/ubuntu/php/+packages

切换

打开php5.5

a2dismod php5.6 && a2dismod php7.2 && a2enmod php5 && service apache2 restart

打开php5.6

a2dismod php5 && a2dismod php7.2 && a2enmod php5.6 && service apache2 restart

打开php7.2

a2dismod php5 && a2dismod php5.6 && a2enmod php7.2 && service apache2 restart

开启重定向

a2enmod rewrite
a2enmod headers

同时修改apache2的配置文件

<Directory />
Options FollowSymLinks
AllowOverride None(修改为AllowOverride All)
</Directory>

一个apache同时支持多个版本PHP

为了方便配置,首先把apache升级到 2.4.9 以上(参考这里

把不同vhost的请求分发到不同php-fpm上

注:php-fpm basic auth无法通过认证,解决办法:

Authorization通常出于“安全原因”,Apache模块将剥离标记。我们可以通过env直接将标题传递给PHP来解决此问题:

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

1.在VirtualHost配置里添加FilesMatch,用php-fpm来处理php解析请求(也可以把该配置写在.htaccess里):

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        <FilesMatch \.php$>
            SetHandler "proxy:unix:/run/php/php5.6-fpm.sock|fcgi://localhost"
        </FilesMatch>
        SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
...

2.启动php-fpm前先关闭php-mod:

a2dismod php5.6

启动php-fpm:

php-fpm5.6

3.在另外VirtualHost同样添加FilesMatch:

<VirtualHost *:8080>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        <FilesMatch \.php$>
            SetHandler "proxy:fcgi://127.0.0.1:9150"
        </FilesMatch>
        SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
...

4.编辑并启动php-fpm 7.2版本

打开/etc/php/7.2/fpm/pool.d/www.conf 修改listen为:

listen = 127.0.0.1:9150

启动:

php-fpm7.2

5.最后再启用以下两个模块

a2enmod proxy proxy_fcgi

重启apache就完成了

注意,如果用pecl安装mongodb扩展,会出现两者不能同时兼容,解决办法:

1.先安装一个版本的扩展,比如我们先装5.6扩展

apt remove php7.2-dev
pecl uninstall mongodb
apt install php5.6-dev
pecl install mongodb

1.1 也可以修改php的软链

rm /etc/alternatives/php
ln -s /usr/bin/php5.6 /etc/alternatives/php

2.然后把该mongodb.so文件先备份出来

cp /usr/lib/php/20131226/mongodb.so /home/mongodb-5.6.so

3.再安装7.2扩展

apt install php7.2-dev
pecl uninstall mongodb
pecl install mongodb

4.把刚才备份的5.6扩展放回去

cp /home/mongodb-5.6.so /usr/lib/php/20131226/mongodb.so

5.重启两个php-fpm

killall -USR2 php-fpm5.6
killall -USR2 php-fpm7.2

关于killall信号说明

INT, TERM 立刻终止
QUIT 平滑终止
USR1 重新打开日志文件
USR2 平滑重载所有worker进程并重新载入配置和二进制模块

安装php7.0

1.添加更新源

apt-get install -y language-pack-en-base
LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej/php
apt-get update

2.卸载php5

apt-get purge php5 php5-mysql php5-common
apt-get --purge autoremove

3.安装php7

apt-get install php7.0 php7.0-cli php7.0-fpm php7.0-gd php7.0-json php7.0-mysql php7.0-readline

或者

apt-get install php7.0

4.重启apache

service apache2 restart

查询本地包

apt-cache search php7

同时安装php5和php7

不卸载php5也可以,要切换到php7只需改一下配置:

cd /etc/apache2/mods-enabled
rm php5.conf 
rm php5.load 
ln -s ../mods-available/php7.1.load 
ln -s ../mods-available/php7.1.conf 

然后重启apache

Laravel

Lumen

配置默认自动路由

在 route/web.php 加入

$router->get('/{module}[/{action}]', function ($module, $action='index') {
    $class = app('\\App\\Http\\Controllers\\'.$module.'Controller');
    return $class->$action();
});

Laravel

安装

1.使用laravel安装器安装

composer global require "laravel/installer"

执行完后系统里就有laravel命令了

然后就可以安装了:

laravel new blog

2.如果需要安装指定版本,则需使用composer安装

composer create-project --prefer-dist laravel/laravel blog "5.4.*"

运行

php artisan serve

访问 http://localhost:8000 试试看吧!

相关命令

# 查看laravel版本
php artisan -V

配置

查看laravel项目目录下.env文件是否存在,如果不存在需根据.env.example手动创建

voyager

安装

参考官方文档:https://github.com/the-control-group/voyager

Ubuntu添加磁盘空间

为Ubuntu服务器添加磁盘分区

新增并格式化MBR分区

1.运行fdisk -u /dev/vdb命令新建分区

[root@ecshost ~]# fdisk -u /dev/vdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write commad.

Command (m for help): p

Disk /dev/vdb: 42.9 GB, 42949672960 bytes, 83886080 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x2b31a2a3

Device Boot      Start         End      Blocks   Id  System
/dev/vdb1            2048    41943039    20970496   83  Linux

Command (m for help): n
Partition type:
p   primary (1 primary, 0 extended, 3 free)
e   extended
Select (default p): p
Partition number (2-4, default 2): 2
First sector (41943040-83886079, default 41943040):
Using default value 41943040
Last sector, +sectors or +size{K,M,G} (41943040-83886079, default 83886079):
Using default value 83886079
Partition 2 of type Linux and of size 20 GiB is set

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

2.运行命令lsblk /dev/vdb查看分区。

[root@ecshost ~]# lsblk /dev/vdb
NAME   MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vdb    253:16   0  40G  0 disk
├─vdb1 253:17   0  20G  0 part
└─vdb2 253:18   0  20G  0 part

3.格式化新的分区。

创建ext4文件系统:mkfs.ext4 /dev/vdb2

[root@ecshost ~]# mkfs.ext4 /dev/vdb2
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
1310720 inodes, 5242880 blocks
262144 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=2153775104
160 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000

Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
[root@ecshost ~]# blkid /dev/vdb2
/dev/vdb2: UUID="e3f336dc-d534-4fdd-****-b6ff1a55bdbb" TYPE="ext4"

4.运行mount /dev/vdb2 /mnt2挂载分区。

5.运行df -h查看目前数据盘空间和使用情况。

显示新建文件系统的信息,表示挂载成功。

[root@ecshost ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 1.6G 36G 5% /
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 3.9G 460K 3.9G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/vdb2 9.8G 37M 9.2G 1% /mnt
tmpfs 783M 0 783M 0% /run/user/0

Ffmpeg

流媒体相关记录

图片处理

用脚本批量压缩图片

脚本会把当前目录下所有jpg文件压缩并加编号

压缩jpg.bat

cd /d %~dp0
 
for %%a in (*.jpg) do (
    ffmpeg -i "%%~sa" -vf scale=iw/2:ih/2 -q 2 "%%~na_%%06d.jpg"
)

pause

参数说明:

-i        输入文件,这里指的就是视频文件。
-y        表示无需询问,直接覆盖输出文件(如果有原文件的话)。
-vf       应用滤镜。
scale     指的是缩放比例。
-q 2      表示存储jpeg的图像质量,一般2是高质量。如果为0,则使用 0级压缩质量,即不压缩。如果不指定q的值,则默认为8。

视频

NDI

Windows NDI

OBS https://obsproject.com/

OBS NDI 插件 https://github.com/Palakis/obs-ndi

Android NDI

NewTek-NDI-Apk https://apkshelf.com/newtek-ndi-apk

TriCaster Camera https://apkpure.com/cn/tricaster-camera/com.newtek.ndi.tccam

手机摄像头作为PC摄像头

Webcam 下载地址: https://iriun.com/

webcam支持USB调试模式直连,免费,4K,支持局域网无线。IOS 、安卓都兼容。

ffmpeg推流示例

ffmpeg 将/dev/video0设备的拍摄一张jpg保存到本地

ffmpeg -f video4linux2 -i /dev/video0 -vframes 1 image.jpg

windows 10 主机第二个摄像头

ffmpeg -f dshow -r 30 -rtbufsize 100M -video_size 320x240 -video_device_number 1 -i video="Integrated Webcam" -f mpegts -codec:v mpeg1video udp://192.168.0.21:5122

如果报错: real-time buffer [Integrated Webcam] [video input] too full or near too full

则添加:

-rtbufsize 512M    #该参数用于设置缓冲实时帧的最大内存,将内存加大可减轻这个问题发生

windows查看摄像头列表

ffmpeg -list_devices true -f dshow -i dummy

windows 桌面缩放

ffmpeg -f gdigrab -r 24 -i desktop -vf scale=320:240 -b 4000k -f mpegts -c:v mpeg1video udp://192.168.0.21:5122

-vf scale=320:240 vf 参数用于指定视频滤镜,其中 scale 表示缩放,后面的数字表示缩放至 320x240px

上面的参数 scale=320:240 当中的宽度和高度实际应用场景中通常只需指定一个,比如指定高度为 480 或者 720,至于宽度则可以传入 “-1” 表示由原始视频的宽高比自动计算而得。即参数可以写为:scale=-1:240,当然也可以 scale=320:-1

播放软件

1.VLC (跨平台)

官网: http://www.videolan.org/

注:kali linux 中无法打开VLC播放器的解决方法:

root@kali:~# vlc
VLC is not supposed to be run as root. Sorry.
If you need to use real-time priorities and/or privileged TCP ports
you can use vlc-wrapper (make sure it is Set-UID root and
cannot be run by non-trusted users first).

意思是VLC不能在root下面用.这个也是很好解决.需修改vlc的文件,执行

vim /usr/bin/vlc

然后找到geteuid,把这个字符串替换成getppid保存即可正常运行

2.OBS

官网:https://obsproject.com/

转码工具

1.FFmpeg

官网:http://ffmpeg.org/

查看支持的编码类型

ffmpeg -codecs | findstr "MP3"

ffmpeg -codecs | findstr "h264"

使用 -c:v 参数来指定视频的编解码器,这里 c 是 codec 的缩写,v 是指 video ,处理音频编码可以替换为 a ( audio )

比如把mp4转换成mp3时,这样指定 (测试下来mp3_mf编码器要比libmp3lame快):

ffmpeg -i input.mp4 -f mp3 -c:a mp3_mf output.mp3

ffmpeg 安装过程

下载

wget https://github.com/FFmpeg/FFmpeg/archive/n3.0.11.tar.gz
tar -zxvf n3.0.11.tar.gz

*新版安装:

wget https://ffmpeg.org/releases/ffmpeg-4.0.tar.bz2
tar -jxvf ffmpeg-4.0.tar.bz2 

先安装yasm

apt install yasm

进入安装目录

./configure --enable-shared --prefix=/usr/local/ffmpeg
make
make install

检查是否安装成功:

/usr/local/ffmpeg/bin/ffmpeg --version

报错如下:

/usr/local/ffmpeg/bin/ffmpeg: error while loading shared libraries: libavdevice.so.56: cannot open shared object file: No such file or directory

提示库文件找不到。

修改文件/etc/ld.so.conf 内容增加/usr/local/ffmpeg/lib/

vim /etc/ld.so.conf

include ld.so.conf.d/*.conf
/usr/local/ffmpeg/lib/

使修改生效

ldconfig

完成!

FFmpeg简介

FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。

FFmpeg在Linux平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows、Mac OS X等。

FFmpeg项目由以下几部分组成:

  FFMpeg   视频文件转换命令行工具,也支持经过实时电视卡抓取和编码成视频文件。
  FFServer 基于HTTP(RTSP正在开发中)用于实时广播的多媒体服务器,也支持时间平移.
  FFplay   用SDL和FFmpeg库开发的一个简单的媒体播放器.
  libavcodec   一个包含了所有FFmpeg音视频编解码器的库.为了保证最优性能和高可复用性,大多数编解码器从头开发的.
  libavformat  一个包含了所有的普通音视格式的解析器和产生器的库.

查看支持的协议

ffmpeg -protocols

例子:ffmpeg -y -i “1.avi” -title “Test” -vcodec xvid -s 368x208 -r 29.97 -b 1500 -acodec aac -ac 2 -ar 24000 -ab 128 -vol 200 -f psp -muxvb 768 “output.wmv”

解释:以上命令可以在Dos命令行中输入,也可以创建到批处理文件中运行。不过,前提是:要在ffmpeg所在的目录中执行(转换君所在目录下面的cores子目录)。

输入输出文件通常就是待处理的多媒体文件了。可以是纯粹的音频文件,纯粹的视频文件,或者混合的。大部分常见的格式都能够“通杀”。象常见的各种mpeg,AVI封装的DIVX和Xvid等等,具体的格式支持列表可以使用ffmpeg -formats查看或直接查阅文档。 另:由于Linux把设备视为文件,因此-i选项后可以跟设备名。比如DV,视频卡,光驱或者其它的各类设备。

参数:

-y 覆盖输出文件,即如果 output.wmv 文件已经存在的话,不经提示就覆盖掉 
-i "1.avi" 输入文件是和ffmpeg在同一目录下的1.avi文件,可以自己加路径,改名字 
-title "Test" 在PSP中显示的影片的标题 
-vcodec xvid 使用XVID编码压缩视频,不能改的,对应的库为libxvid
-s 368x208 输出的分辨率为368x208,注意片源一定要是16:9的不然会变形 
-r 29.97 帧数,一般就用这个吧 
-b 1500 视频数据流量,用-b xxxx的指令则使用固定码率,数字随便改,1500以上没效果;还可以用动态码率如:-qscale 4和-qscale 6,4的质量比6高 
-acodec aac 音频编码用AAC 对应的库为libfaac
-ac 2  声道数1或2 
-ar 24000 声音的采样频率,好像PSP只能支持24000Hz 
-ab 128 音频数据流量,一般选择32、64、96、128 
-vol 200 200%的音量,自己改 
-muxvb 768 好像是给PSP机器识别的码率,一般选择384、512和768,我改成1500,PSP就说文件损坏了 
-f psp 输出psp专用格式 
"output.wmv" 输出文件名,也可以加路径改文件名

示例1: 截取一张352x240尺寸大小的,格式为jpg的图片: ffmpeg -i test.asf -y -f image2 -t 0.001 -s 352x240 a.jpg

示例2: 把视频的前30帧转换成一个Animated Gif : ffmpeg -i test.asf -vframes 30 -y -f gif a.gif

示例3: 在视频的第8.01秒处截取 352*240 的缩略图 ffmpeg -i test2.asf -y -f image2 -ss 08.010 -t 0.001 -s 352x240 b.jpg

a)通用选项

-L license

-h 帮助

-fromats 显示可用的格式,编解码的,协议的。。。

-f fmt 强迫采用格式fmt

-i filename 输入文件

-y 覆盖输出文件

-t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持

-ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持

-title string 设置标题

-author string 设置作者

-copyright string 设置版权

-comment string 设置评论

-target type 设置目标文件类型(vcd,svcd,dvd) 所有的格式选项(比特率,编解码以及缓冲区大小)自动设置 ,只需要输入如下的就可以了: ffmpeg -i myfile.avi -target vcd /tmp/vcd.mpg

-hq 激活高质量设置

-itsoffset offset 设置以秒为基准的时间偏移,该选项影响所有后面的输入文件。该偏移被加到输入文件的时戳,定义一个正偏移意味着相应的流被延迟了 offset秒。 [-]hh:mm:ss[.xxx]的格式也支持

b) 视频选项

-b bitrate 设置比特率,缺省200kb/s

-r fps 设置帧频 缺省25

-s size 设置帧大小 格式为WXH 缺省160X128.下面的简写也可以直接使用: Sqcif 128X96 qcif 176X144 cif 252X288 4cif 704X576

-aspect aspect 设置横纵比 4:3 16:9 或 1.3333 1.7777

-croptop size 设置顶部切除带大小 像素单位

-cropbottom size –cropleft size –cropright size

-padtop size 设置顶部补齐的大小 像素单位

-padbottom size –padleft size –padright size –padcolor color 设置补齐条颜色(hex,6个16进制的数,红:绿:兰排列,比如 000000代表黑色)

-vn 不做视频记录

-bt tolerance 设置视频码率容忍度kbit/s

-maxrate bitrate设置最大视频码率容忍度

-minrate bitreate 设置最小视频码率容忍度

-bufsize size 设置码率控制缓冲区大小

-vcodec codec 强制使用codec编解码方式。 如果用copy表示原始编解码数据必须被拷贝。

-sameq 使用同样视频质量作为源(VBR)

-pass n 选择处理遍数(1或者2)。两遍编码非常有用。第一遍生成统计信息,第二遍生成精确的请求的码率

-passlogfile file 选择两遍的纪录文件名为file

c)高级视频选项

-g gop_size 设置图像组大小

-intra 仅适用帧内编码

-qscale q 使用固定的视频量化标度(VBR)

-qmin q 最小视频量化标度(VBR)

-qmax q 最大视频量化标度(VBR)

-qdiff q 量化标度间最大偏差 (VBR)

-qblur blur 视频量化标度柔化(VBR)

-qcomp compression 视频量化标度压缩(VBR)

-rc_init_cplx complexity 一遍编码的初始复杂度

-b_qfactor factor 在p和b帧间的qp因子

-i_qfactor factor 在p和i帧间的qp因子

-b_qoffset offset 在p和b帧间的qp偏差

-i_qoffset offset 在p和i帧间的qp偏差

-rc_eq equation 设置码率控制方程 默认tex^qComp

-rc_override override 特定间隔下的速率控制重载

-me method 设置运动估计的方法 可用方法有 zero phods log x1 epzs(缺省) full

-dct_algo algo 设置dct的算法 可用的有 0 FF_DCT_AUTO 缺省的DCT 1 FF_DCT_FASTINT 2 FF_DCT_INT 3 FF_DCT_MMX 4 FF_DCT_MLIB 5 FF_DCT_ALTIVEC

-idct_algo algo 设置idct算法。可用的有 0 FF_IDCT_AUTO 缺省的IDCT 1 FF_IDCT_INT 2 FF_IDCT_SIMPLE 3 FF_IDCT_SIMPLEMMX 4 FF_IDCT_LIBMPEG2MMX 5 FF_IDCT_PS2 6 FF_IDCT_MLIB 7 FF_IDCT_ARM 8 FF_IDCT_ALTIVEC 9 FF_IDCT_SH4 10 FF_IDCT_SIMPLEARM

-er n 设置错误残留为n 1 FF_ER_CAREFULL 缺省 2 FF_ER_COMPLIANT 3 FF_ER_AGGRESSIVE 4 FF_ER_VERY_AGGRESSIVE

-ec bit_mask 设置错误掩蔽为bit_mask,该值为如下值的位掩码 1 FF_EC_GUESS_MVS (default=enabled) 2 FF_EC_DEBLOCK (default=enabled)

-bf frames 使用frames B 帧,支持mpeg1,mpeg2,mpeg4

-mbd mode 宏块决策 0 FF_MB_DECISION_SIMPLE 使用mb_cmp 1 FF_MB_DECISION_BITS 2 FF_MB_DECISION_RD

-4mv 使用4个运动矢量 仅用于mpeg4

-part 使用数据划分 仅用于mpeg4

-bug param 绕过没有被自动监测到编码器的问题

-strict strictness 跟标准的严格性

-aic 使能高级帧内编码 h263+

-umv 使能无限运动矢量 h263+

-deinterlace 不采用交织方法

-interlace 强迫交织法编码 仅对mpeg2和mpeg4有效。当你的输入是交织的并且你想要保持交织以最小图像损失的时候采用该选项。可选的方法是不交织,但是损失更大

-psnr 计算压缩帧的psnr

-vstats 输出视频编码统计到vstats_hhmmss.log

-vhook module 插入视频处理模块 module 包括了模块名和参数,用空格分开

d)音频选项

-ab bitrate 设置音频码率

-ar freq 设置音频采样率

-ac channels 设置通道 缺省为1

-an 不使能音频纪录

-acodec codec 使用codec编解码

e)音频/视频捕获选项

-vd device 设置视频捕获设备。比如/dev/video0

-vc channel 设置视频捕获通道 DV1394专用

-tvstd standard 设置电视标准 NTSC PAL(SECAM)

-dv1394 设置DV1394捕获

-av device 设置音频设备 比如/dev/dsp

f)高级选项

-map file:stream 设置输入流映射

-debug 打印特定调试信息

-benchmark 为基准测试加入时间

-hex 倾倒每一个输入包

-bitexact 仅使用位精确算法 用于编解码测试

-ps size 设置包大小,以bits为单位

-re 以本地帧频读数据,主要用于模拟捕获设备

-loop 循环输入流。只工作于图像流,用于ffserver测试

注: mpeg1标准只允许几种不同的帧速率(23.976, 24.000, 25.000, 29.970, 30.000, 50.000, 59.940 and 60.000),但是你可以通过使用这个-strict -1选项来告诉ffmpeg忽略规范。

测试源

1,RTMP协议直播源 香港卫视:rtmp://live.hkstv.hk.lxdns.com/live/hks

2,RTSP协议直播源 大熊兔(点播):rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov

3,HTTP协议直播源

香港卫视:http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8
CCTV1高清:http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8
CCTV3高清:http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8
CCTV5高清:http://ivi.bupt.edu.cn/hls/cctv5hd.m3u8
CCTV5+高清:http://ivi.bupt.edu.cn/hls/cctv5phd.m3u8
CCTV6高清:http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8
苹果提供的测试源(点播):http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/prog_index.m3u8

更多http://ivi.bupt.edu.cn/

apple https://developer.apple.com/streaming/examples/

ffmpeg示例

windows下采集局部桌面

ffmpeg -f gdigrab -r 24 -offset_x 0 -offset_y 50 -video_size 640x480 -i desktop -b 4000k -f mpegts -c:v mpeg1video udp://192.168.1.59:5122/

截取窗口:

ffmpeg -f gdigrab -r 24 -i title="kali - root@kali: /home/test - Xshell 5 (Free for Home/School)" -b 4000k -f mpegts -c:v mpeg1video udp://192.168.1.59:5122/

注意:titile后面的标题必须完整名称,tasklist /v可能显示不全,请手动补全

获取窗口title

tasklist /V

windows下裁剪摄像头设备

ffmpeg -f dshow -i video="DroidCam Source 3" -f mpegts -c:v mpeg1video udp://192.168.1.59:5122/

windows下直接预览摄像头

ffplay -f dshow -i video="DroidCam Source 3"

注:除了使用DirectShow作为输入外,使用VFW也可以读取到摄像头的数据,例如下述命令可以播放摄像头数据:

ffplay -f vfwcap -i 0  

windows下查看所有设备

ffmpeg -list_devices true -f dshow -i 1

windows下直播画中画

ffmpeg -f gdigrab -r 24 -offset_x 0 -offset_y 50 -video_size 640x480 -i desktop -f dshow -i video="DroidCam Source 3" -filter_complex "[1:v]scale=w=176:h=144:force_original_aspect_ratio=decrease[ckout];[0:v][ckout]overlay=x=W-w-10:y=10[out]" -map "[out]" -s 320x240 -b 4000k -f mpegts -c:v mpeg1video udp://192.168.1.59:5122/

ERROR

报错:

> locale: Cannot set LC_CTYPE to default locale: No such file or directory
> locale: Cannot set LC_MESSAGES to default locale: No such file or directory
> locale: Cannot set LC_ALL to default locale: No such file or directory

解决办法:

apt update
apt install -y language-pack-zh-hans

$ cat /etc/default/locale
#  File generated by update-locale
LANG="en_US.UTF-8"
LANGUAGE="en_US:en"

locale -a
dpkg-reconfigure locales
# 使配置生效
locale-gen en_US.UTF-8

生成视频过大解决办法

使用huffyuv代替原始视频可能会更好 - 它会将您的文件大小减半,但是完全没有损失。使用,-c:v huffyuv而不是-c copy

官方文档:

http://ffmpeg.org/documentation.html

拷贝编译好的ffmpeg目录

ffmpeg目录存在各种.so链接库,如果直接scp会把links文件当做原文件拷贝,可以用rsync来解决:

rsync -Wav --progress linux:/usr/local/ffmpeg /usr/local/ffmpeg

改完后编辑 /etc/ld.so.conf 文件,在里面添加:

/usr/local/ffmpeg/lib

然后添加全局软链:

ln -s /usr/local/ffmpeg/bin/ffmpeg /usr/bin/ffmpeg

mjpg-streamer

mjpg-streamer是一个命令行应用程序,它将JPEG帧从一个或多个输入插件复制到多个输出插件。它可用于通过基于IP的网络将JPEG文件从网络摄像头流式传输到各种类型的查看器。

Android终端模拟器Termux

Termux是一个Android终端模拟器和Linux环境应用程序,可直接使用,无需root或设置。

官网:https://termux.com/

国内用户去这里下载:https://f-droid.org/packages/com.termux/

termux清华大学开源软件镜像站https://mirrors.tuna.tsinghua.edu.cn/help/termux/

内部存储和外部存储(sd卡)访问

参考官方文档:https://termux.com/storage.html

先把termux-setup-storage安装好

再往$HOME目录建立storage文件夹

mkdir storage 

然后执行(需要在手机终端下执行,远程ssh执行无效)

termux-setup-storage

比如建好后:

bash-4.4$ ls ~/storage/
dcim        downloads   external-1  movies      music       pictures    shared

external-1即是外部sd卡目录

调用摄像头等设备

参考文档:https://wiki.termux.com/wiki/Termux:API

先去安装:termux.api https://f-droid.org/packages/com.termux.api/

然后执行:

 pkg install termux-api

拍照:

termux-camera-photo 1.jpg

开机启动

参考文档:https://wiki.termux.com/wiki/Termux:Boot

先安装:termux.boot https://f-droid.org/packages/com.termux.boot/

执行一下termux.boot让它能开机启动,然后建立目录 ~/.termux/boot/

比如要启动sshd和python脚本, 在该目录下建立启动文件~/.termux/boot/start-boot:

termux-wake-lock
sshd
python2 xxx.py
/data/data/com.termux/files/home/Mammoth_x/Bash/Mammoth_x_pyinstaller/Mammoth_x

Python环境相关

默认安装pip3,在pip list会出现警告,需要在$HOME目录建立文件

bash-4.4$ cat ~/.pip/pip.conf 
[global]
format=legacy

有些库会依赖clang编译,需要把clang安装上

apt install clang

PyInstaller安装问题

PyInstaller在arm平台下打包编译会有问题,原因是默认会加载Linux-64bit引导程序

我们只需在arm下重新编译bootloader,然后替换掉Linux-64bit里的run文件:

PyInstaller源码下载:https://github.com/pyinstaller/pyinstaller/releases

操作过程:

1.解压源码

2.进入目录 PyInstaller-3.3/bootloader

3.执行(注意python版本,如果是python3那用 python3 ./waf distclean all)

python2 ./waf distclean all

正常情况下编译结束会在build/release/ 目录下有个run文件

bash-4.4$ file build/release/run 
build/release/run: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /system/bin/linker64, stripped

如果报错:

../../src/pyi_launch.c:32:14: fatal error: ‘langinfo.h’ file not found

那先把对应行号注释调吧,目前用下来暂时没啥影响。(貌似是python2下才会出现)

4.然后把PyInstaller-3.3/PyInstaller/bootloader/Linux-64bit-aarch/ 目录下的文件copy至/data/data/com.termux/files/usr/lib/python2.7/site-packages/PyInstaller/bootloader/Linux-64bit/

注:PyInstaller-3.3.1 修复了引导问题,但是langinfo.h的问题还是可以通过上述办法解决。

报错 psutil/_psutil_common.c:9:10: fatal error: ‘Python.h’ file not found 处理办法

// 注意是安装对应python-dev,比如Python2
apt install python2-dev

报错 python2.7/Python.h:47:10: fatal error: ‘crypt.h’ file not found 解决办法

// 缺少crypt库导致
pkg install libcrypt-dev

如果pyinstaller是Python3的,想给Python2也安装,那么只要去源码目录用Python2重新安装即可

python2 setup.py install

hashhack完整包

apt install python2 python2-dev clang libcrypt-dev 
pip2 install psutil socketIO_client

报错 [25709] INTERNAL ERROR: cannot create temporary directory!

//默认会去根目录 /tmp 下建立临时文件,我们只需指定零时文件目录即可
export TMPDIR="/data/data/com.termux/files/usr/tmp"

使用触摸键盘

使用Ctrl键是使用终端的必要条件 - 但大多数触摸键盘都不包含一个。为此,Termux使用音量减小按钮来模拟Ctrl键。例如,在触摸键盘上按下音量减小键+ L将发送与在硬件键盘上按Ctrl + L相同的输入。

使用Ctrl键和键的结果取决于使用哪个程序,但是对于许多命令行工具,以下快捷键可用:

Ctrl + A→移动光标到行首 Ctrl + C→中止(发送SIGINT到)当前进程 Ctrl + D→注销终端会话 Ctrl + E→移动光标到行尾 Ctrl + K→从光标删除到行尾 Ctrl + L→清除终端 Ctrl + Z→挂起(发送SIGTSTP到)当前进程 音量增加键也是产生特定输入的特殊键:

音量提高+ E→退出键 音量增加+ T→Tab键 音量增加+ 1→F1(和音量增加+ 2→F2等) 音量增加+ 0→F10 音量增加+ B→Alt + B,使用readline时返回一个单词 音量增加+ F→Alt + F,使用readline时转发一个单词 音量增加+ X→Alt + X 音量增加+ W→向上箭头键 音量增加+ A→左箭头键 音量增加+ S→向下箭头键 音量增加+ D→向右箭头键 音量增加+ L→| (管道字符) 音量加+ H→〜(代字符) 音量增加+ U→_(下划线) 音量提高+ P→上一页 音量增加+ N→下一页 音量增加。→Ctrl + \(SIGQUIT) 音量增加+ V→显示音量控制 音量增加+ Q→显示额外的按键视图

额外的按键视图

termux也有一个额外的按键视图。它允许您使用ESC,CTRL,ALT,TAB, - ,/和 键扩展当前的键盘。要启用额外的按键视图,您必须长按左抽屉菜单中的键盘按钮。您也可以按音量增加+ Q。

文本输入视图

终端模拟器通常不支持自动更正,预测和滑动输入等触摸键盘的高级功能。为了解决这个问题,Termux有一个文本输入视图。输入的文本将被粘贴到终端。由于是原生Android文本输入视图,因此所有触摸键盘功能都可以使用。要访问文本输入视图,您必须将额外的按键视图向左滑动。

使用硬件键盘

将Termux与硬件(如蓝牙)键盘结合使用时,可以使用以下快捷键:Ctrl + Alt:

‘C’→创建新的会话 ‘R’→重命名当前会话 向下箭头(或“N”)→下一个会话 向上箭头(或“P”)→上一个会话 右箭头→打开抽屉 左箭头→关闭抽屉 ‘F’→切换全屏 ‘M’→显示菜单 ‘U’→选择URL ‘V’→粘贴 +/-→调整文字大小 1-9→进入编号会话

搭建MQTT服务器

安装 mosquitto

apt install mosquitto

增加用户test,设置密码

mosquitto_passwd -c /data/data/com.termux/files/usr/etc/mosquitto/passwd test

编辑配置文件 /data/data/com.termux/files/usr/etc/mosquitto/mosquitto.conf

修改监听端口

listener 1234

启动

mosquitto -c /data/data/com.termux/files/usr/etc/mosquitto/mosquitto.conf

异常

通过BCompare中sftp的ansi编码模式方式上传中文文件,导致乱码且删不掉文件的解决办法:

将文件移动到同级的上层目录,例如

mv 文件夹名 ../上层目录/文件夹名

MongoDB

下载地址:https://www.mongodb.com/try/download/community

WSL2下安装MongoDB 6.x

0.使用以下命令安装gnupg及其所需的库

apt-get install gnupg

1.导入包管理系统使用的公钥

wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -

2.为MongoDB创建一个列表文件

echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list

3.重新加载本地包数据库

apt-get update

4.安装MongoDB包

apt-get install -y mongodb-org

5.配置文件位置

/etc/mongod.conf

6.启动脚本

/root/startup.sh

#!/bin/bash
ulimit -SHn 65535
mongod -f /etc/mongod.conf -fork

优雅的关闭

mongod -f /etc/mongod.conf --shutdown

7.Windows启动脚本

c:/auto_run/startup/start.bat

wsl -d Ubuntu -u root /root/startup.sh

8.Windows启动调用

shell:startup /startup.vbs

set ws=WScript.CreateObject("WScript.Shell")
ws.Run "C:\auto_run\startup\start.bat /start",0

安装手册:https://www.mongodb.com/docs/manual/administration/install-on-linux/

代码段

查看今日爬虫状态

/*
* 查看今日爬虫状态
* BY: http://malu.me/
*/
var date = new Date();
var bb = date.getFullYear()+'-'+(date.getMonth()+1)+'-'+date.getDate();
function getcount(){
    var collection_list = db.getCollectionInfos({"name":/BR_/});  // 列出前包含BR_的Collection
    for ( var i=0;i<collection_list.length;i++ ){
        table = collection_list[i]['name'];
        ok = db.getCollection(table).find({'product_info': {$ne:""},"date":bb,"source":"TB"}).count();
        no = db.getCollection(table).find({'product_info': "","date":bb,"source":"TB"}).count();
        print(table, ok+'/'+no);
    }
}
getcount();

PHP模糊查询 old

<?php
   // 连接到mongodb
   $m = new MongoClient("xxx.malu.me:123456");
   // 选择一个数据库
   $db = $m->mydb;
   // 认证登录
   $db->authenticate('username', 'passwd');
   // 选择一个表
   $collection = $db->user;
   $name = 'python';
   $query = array('title' => new MongoRegex("/.*".$name.".*/i"));
   $cursor = $collection->find($query);
   // 迭代显示文档标题
   // var_dump($cursor);
   foreach ($cursor as $document) {
      echo $document["title"] . "\n";
   }
?>

PHP mongoDB常用查询

<?php
//字段字串为
$querys = array"name"=>"malu");
//数值等于多少
$querys = array"number"=>7);
//数值大于多少
$querys = array"number"=>array'$gt' => 5));
//数值大于等于多少
$querys = array"number"=>array'$gte' => 2));
//数值小于多少
$querys = array"number"=>array'$lt' => 5));
//数值小于等于多少
$querys = array"number"=>array'$lte' => 2));
//数值介于多少
$querys = array"number"=>array'$gt' => 1'$lt' => 9));
//数值不等于某值
$querys = array"number"=>array'$ne' => 9));
//使用js下查询条件
$js ="function(){
return this.number == 2 && this.name == 'shian';
}";
$querys = array'$where'=>$js);
//字段等于哪些值
$querys = array"number"=>array'$in' => array1,2,9)));
//字段不等于哪些值
$querys = array"number"=>array'$nin' => array1,2,9)));
//使用正则查询
$querys = array"name"=>  new MongoRegex("/.*".$name.".*/i"));
//或
$querys = array'$or' => arrayarray'number'=>2),array'number'=>9)));
?>

语句

建立复合索引

db.getCollection("bolg").createIndex({"source":1,"date":-1});

1 为指定按升序创建索引

-1 为降序来创建索引

创建唯一索引,并消除重复数据。

数字1表示userid键的索引按升序存储,-1表示userid键的索引按照降序方式存储。

> db.test.ensureIndex({"userid":1},{"unique":true,"dropDups":true}) 

注:如果存在其他键,那么删除重复会失败,需要手动删除。

聚合查询,统计重复个数

> db.runCommand({"distinct":"table_name","key":"field_name"})

# 查看非重复值个数
> db.getCollection("table_name").distinct('field_name').length

# 找出指定字段重复数
> db.AI_online.aggregate([{$group : {_id : "$title", num : {$sum : 1}}},{$match :{num:{$gt : 1}}},{$sort:{num:-1}}])

# 删除指定字段重复值,只保留一个(去重)
> db.AI_online.aggregate([
{
    $group: { _id: {title: '$title'},count: {$sum: 1},dups: {$addToSet: '$_id'}}
},
{
    $match: {count: {$gt: 1}}
}
]).forEach(function(doc){
    doc.dups.shift();
    db.AI_online.remove({_id: {$in: doc.dups}});
})

模糊查询

db.test_info.find({"tname": {$regex: '测试', $options:'i'}}) 

db.test_info.find({"tname": {$regex:/测试.*/i}})

模糊+或查询

db.test_info.find({"$or":[{"title":{$regex:/测试.*/i}},{"summary":{$regex:/测试.*/i}}]}) 

MongoDB运维

RPM安装

rpm -ivh https://repo.mongodb.org/yum/redhat/7/mongodb-org/5.0/x86_64/RPMS/mongodb-org-server-5.0.6-1.el7.x86_64.rpm  --force --nodeps

ubuntu安装5.x

wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | sudo apt-key add -
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-5.0.list
vim /etc/apt/sources.list.d/mongodb-org-5.0.list
apt update
apt-get install -y mongodb-org

服务启动与停止

systemctl start mongod
systemctl stop mongod

异常处理

日志报错:MongoDB之Too many open files

Linux是有文件句柄限制的,而且Linux默认一般都是1024

解决办法:把句柄限制提高

cat /proc/sys/fs/file-max     # file-max(系统级别)是设置系统所有进程一共可以打开的最大文件数量。
cat /etc/security/limits.conf # 永久配置文件(注意WSL2下这个值貌似没生效)
ulimit -n                     # 查看用户级的限制,阿里云服务器一般是65535
ulimit -a                     # 查看当前的各种用户进程限制
ulimit -SHn 65535             # 临时修改系统句柄限制,加-H就是硬限制,加-S就是软限制

mongo3.x老版本升级

如果以前有3.x版本,则需要先卸载老版本

使用 apt list --installed | grep mongo 查看历史版本

然后删除他们:

apt remove mongodb-server-core

参考文章:https://docs.mongodb.com/manual/reference/installation-ubuntu-community-troubleshooting/#unable-to-install-package-due-to-dpkg-deb–error

注意!!

mongod 版本3.x的配置文件和 5.x的有区别:

3.x默认使用 /etc/mongodb.conf

5.x默认使用 /etc/mongod.conf 的 yaml格式,注意格式区分!

开启密码登录:

1.添加用户

在终端下

use admin   // 进入admin库
db.createUser({
  user: 'admin',  // 用户名
  pwd: '123456',  // 密码
  roles:[{
    role: 'root',  // 角色
    db: 'admin'  // 数据库
  }]
})
show users  // 显示用户列表

2.配置文件开启验证 mongod.conf

security:
  authorization: enabled

2.1 或者启动的时候加上 –auth

mongodump常用参数说明

  • –db:指定导出的数据库
  • –collection:指定导出的集合
  • –excludeCollection:指定不导出的集合
  • –host :远程ip
  • –username:开启身份验证后,用户的登录名
  • –password:用户的密码
  • –out(指定输出目录):如果不使用这个参数,mongodump将输出文件保存在当前工作目录中名为dump的目录中
  • –archive:导出归档文件,最后只会生成一个文件
  • –gzip:压缩归档的数据库文件,文件的后缀名为.gz

mongodump和mongorestore来迁移数据库

官方说明书:https://docs.mongodb.com/database-tools/mongodump/

备份恢复本地全库:

mongodump -o /mongodbbackup/20220230/ --gzip
mongorestore --dir ./20220230/ --gzip

备份恢复单个collection

mongodump --uri="mongodb+srv://malu:xxxxx@malu.me" -d=spider_zujuan -c=questions --archive=spider_zujuan.gz --gzip
mongorestore --gzip --archive=spider_zujuan.gz -d=spider_zujuan -c=questions --uri="mongodb://192.168.50.2"

备份整个数据库脚本

#!/bin/bash
MY_PATH=$(cd "$(dirname "$0")"; pwd)
cd $MY_PATH
dd=`date '+%Y-%m-%d-%H%M%S'`
mongodump --uri="mongodb+srv://malu:xxxxx@malu.me" -o ./$dd --gzip
# mongorestore --dir ./20220230/ --gzip

迁移mongodb 3.4->3.6

可以采用直接拷贝数据库文件的方式进行。 拷贝文件需要停止数据库服务,停止后直接拷贝数据库文件目录中的数据即可。

注意事项:

1、.lock文件不要拷贝;
2、diagnostic.data的文件夹不要拷贝,如果拷贝,在新的数据库运行时会出现错误,需要修复,时间有点长。

快速安装

apt-get install mongodb
apt-get install mongodb-org

Linux下安装手册:https://docs.mongodb.com/manual/administration/install-on-linux/

启动

mongod -f /etc/mongodb.conf -fork   //使用配置文件启动,并后台执行

连接

mongo --host xx.xx.xx.xx --port 123

test数据库添加用户

use test
db.addUser("test","test")

登录

// 方式一
mongo
use admin
db.auth('admin', '123456')

// 方式二
mongo admin -u admin -p 123456

添加超级管理员

db.createUser(
  { user: "admin",
    pwd: "admin",
    roles: [ { role: "root", db: "admin" } ]
  }
)

user字段,为新用户的名字;

pwd字段,用户的密码;

roles字段,指定用户的角色,可以用一个空数组给新用户设定空角色。在roles字段,可以指定内置角色和用户定义的角色。

内建的角色:

  1. 数据库用户角色:read、readWrite;
  2. 数据库管理角色:dbAdmin、dbOwner、userAdmin;
  3. 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
  4. 备份恢复角色:backup、restore;
  5. 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
  6. 超级用户角色:root
  7. 这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase)
  8. 内部角色:__system

角色参考:https://docs.mongodb.com/manual/reference/built-in-roles/#built-in-roles

修改超级管理员密码

db.changeUserPassword("admin", "654321")

添加DB读写用户

先建立一个DB,然后在该DB下执行shell:

db.createUser(
  { user: "spider",
    pwd: "spider",
    roles: [ { role: "readWrite", db: "spider" } ]
  }
)

windows下开启mongodb用户认证

修改配置文件:C:\Program Files\MongoDB\Server\3.4\mongod.cfg

添加:

security:
    authorization: enabled

然后重启服务

知识库

聚合

聚合参考文档 https://docs.mongodb.com/v5.0/reference/aggregation/

实用 MongoDB 聚合书 https://www.practical-mongodb-aggregations.com/

PHP

PHP Mongodb库手册

https://docs.mongodb.com/php-library/current/tutorial/

PHP Mongodb库官方文档

https://www.php.net/manual/zh/set.mongodb.php

Python

pymongo手册

https://pymongo.readthedocs.io/

https://www.w3schools.com/python/python_mongodb_insert.asp

CRUD

https://docs.mongodb.com/v5.0/crud/

windowns MongoDB 客户端

navicat-for-mongodb https://www.navicat.com/en/download/navicat-for-mongodb

MongoDB Compass 客户端 https://www.mongodb.com/try/download/compass

Robomongo https://robomongo.org/

studio3t https://studio3t.com/download-now/

windowns MongoDB server

下载地址:

https://www.mongodb.org/dl/win32/

安装教程:

https://docs.mongodb.com/manual/tutorial/install-mongodb-on-windows/

mongodump、mongorestore等工具下载

https://www.mongodb.com/try/download/database-tools

MongoDB 数据库工具文档 https://docs.mongodb.com/database-tools/

Python代码段

记录常用的Python代码段

python使用form-data方式POST数据

首先下载依赖库:

pip install requests_toolbelt

form-data.py

from requests_toolbelt.multipart.encoder import MultipartEncoder
import requests

request_body = MultipartEncoder(
    {
        "name": "Malu",
        "age": "18"
    }
)

request_header = {
    "Content-Type": request_body.content_type
}

response_body = requests.post("localhost", data=request_body, headers=request_header)

获取命令行参数

sys.argv

import sys

def main():
    # 打印参数
    for i in range(len(sys.argv)):
        print(sys.argv[i])

if __name__ == '__main__':
    main()

输出:

# python argv1.py ag1 ag2
argv1.py
ag1
ag2

argparse

argparse 是python 3.2 新版功能,推荐使用

标准库说明:https://docs.python.org/zh-cn/3/library/argparse.html

教程:https://docs.python.org/zh-cn/3/howto/argparse.html

import argparse

def main():
    parser = argparse.ArgumentParser()
    # group = parser.add_mutually_exclusive_group() # 创建互斥参数 -v -q 只能选其一
    # group.add_argument("-v", "--verbose", action="store_true")
    # group.add_argument("-q", "--quiet", action="store_true")
    parser.add_argument("-c","--count", type=int, help="the count",default=0)
    parser.add_argument("-m","--mail", type=str, help="the email")
    args = parser.parse_args()
    print(args.count)
    print(args.mail)
    # print(args.verbose)
    # print(args.quiet)

if __name__ == '__main__':
    main()

输出:

# python argv2.py -m malu@malu.me -c 12
12
malu@malu.me

getopt

存在于标准库中,2.7也支持,文档:https://docs.python.org/zh-cn/3/library/getopt.html


import sys, getopt

def main(argv):
   inputfile = ''
   outputfile = ''
   try:
      opts, args = getopt.getopt(argv,"hi:o:",["ifile=","ofile="])
   except getopt.GetoptError:
      print('test.py -i <inputfile> -o <outputfile>')
      sys.exit(2)
   for opt, arg in opts:
      if opt == '-h':
         print('test.py -i <inputfile> -o <outputfile>')
         sys.exit()
      elif opt in ("-i", "--ifile"):
         inputfile = arg
      elif opt in ("-o", "--ofile"):
         outputfile = arg
   print('输入的文件为:', inputfile)
   print('输出的文件为:', outputfile)

if __name__ == "__main__":
   main(sys.argv[1:])

输出:

# python argv5.py -i aaa.jpg -o bbb.gif
输入的文件为: aaa.jpg
输出的文件为: bbb.gif

click

Click 是 Flask 的团队 pallets 开发的优秀开源项目,它为命令行工具的开发封装了大量方法,使开发者只需要专注于功能实现。这是一个第三方库,专门为了命令行而生的非常有名的 Python 命令行模块。主页:https://palletsprojects.com/p/click/

import click

@click.command()
@click.option('--name',default='Malu',help='name 参数,非必须,有默认值')
@click.option('--count',help='count 参数',type=int)
@click.option('--mail',help='mail 参数')
def test_for_sys(name, count, mail):
    print('the name is', name)
    print('the count is', count)
    print('the mail is', mail)

def main():
    test_for_sys()

if __name__ == '__main__':
    main()

输出:

# python argv4.py --count 12 --name malu --mail malu@malu.me
the name is malu
the count is 12
the mail is malu@malu.me

argh

argh 是非标准库中的,已经不维护,主页:https://github.com/neithere/argh/

提取字符串中IP+端口格式内容

#!/usr/bin/env python
import re

def check_proxy_host(incoming_string):
    return re.findall('(\d+\.\d+\.\d+\.\d+)+[^0-9]+(\d+)', incoming_string, re.S)

if __name__ == '__main__':
    a = ' 192.161.1.3:1211 ' \
        '123.1.1.1:4123 ' \
        '20.2.2.4  24'
    b = '124.1234.124'
    a1 = check_proxy_host(a)
    b1 = check_proxy_host(b)
    print(a1)
    print(b1)

输出:

> python CheckProxy.py
[('192.161.1.3', '1211'), ('123.1.1.1', '4123'), ('20.2.2.4', '24')]
[]

VNC

快速安装:

apt-get install x11vnc

启动 X 然后启动 x11vnc:

startx &
x11vnc &

kali下启动失败解决

报错如下:

XOpenDisplay failed (:0)

重启gdm3

service gdm3 restart

再次执行

x11vnc &

原因:大量爬虫调用chromedriver让显存异常,导致gdm假死

安装lightdm桌面,并启动vnc登录

apt-get install lightdm
lightdm &
x11vnc -display :0 -auth /var/lib/lightdm/.Xauthority 

查看可用xauth:

> xauth list
kali/unix:0  MIT-MAGIC-COOKIE-1  6593ac270a69bf93c0ff1a8ea2146099

查看X信息

> xdpyinfo

xhost

xhost 是用来控制X server访问权限的,这个命令将允许别的用户启动的图形程序将图形显示在当前屏幕上

xhost + 是使所有用户都能访问Xserver.
xhost + ip使ip上的用户能够访问Xserver.
xhost + nis:user@domain使domain上的nis用户user能够访问
xhost + inet:user@domain使domain上的inet用户能够访问。 

生成 VNC 密码

> x11vnc -storepasswd

设置开机启动vnc

再设置X11VNC的密码文件

x11vnc -storepasswd in /etc/x11vnc.pass

将密码文件复制过去:

cp /root/.vnc/passwd /etc/x11vnc.pass

放入开启启动文件:

> cat /etc/rc.local
/usr/bin/x11vnc -auth /var/lib/lightdm/.Xauthority -noxrecord -noxfixes -noxdamage -rfbauth /etc/x11vnc.pass -forever -bg -rfbport 5900 -o /var/log/x11vnc.log