Centos安装Jupyter

推荐使用anaconda管理python版本,或者别的虚拟环境对python进行管理。

首先新建一个python版本

1
conda create --name py39 python=3.9

然后进入环境安装jupyter

1
2
conda activate py39
pip install jupyter

如果报错的话,应该是因为pip的版本低

可以更新一下pip的版本

1
pip install --upgrade pip

然后设置一下密码

1
2
3
4
# 生成配置文件
jupyter notebook --generate-config
# 设置密码,提示两次输入密码,然后密码被保存到jupyter_notebook_config.json中
jupyter notebook password

之后执行命令启动即可

1
jupyter notebook --ip 0.0.0.0 --allow-root

pytorch的一个坑爹的地方

想用ddddocr识别一下验证码,但是准确率不是非常的高,正好作者提供了dddd_trainer可以进行训练,于是在我的电脑上下载了源码准备训练,然后就发现没有环境。

百度搜索发现可以通过官网安装pytorch首先需要看一下自己的CUDA版本,安装的话可以低但是不能高。

使用win+r打开运行输入cmd打开命令行

然后输入

1
nvidia-smi

即可查看CUDA的版本

查看CUDA版本

然后就可以直接去官网下载对应的版本了,如果没有自己的版本那么就需要去Previous versions of PyTorch查看其余版本,我这里是11.2但是我安装的是10.2。但是官网并没有提供直接的下载方式,所以就要查看更多版本。

pytorch版本

我是所有的都回退了一个版本,这里选择的是1.10.0

pytorch历史版本

直接通过conda 安装即可,但是安装完成后发现并不能使用。

1
conda install pytorch==1.10.0 torchvision==0.11.0 torchaudio==0.10.0 -c pytorch

torch.cuda.is_available()会提示false。

我是尝试了许多方法都没有解决,最后在谷歌搜索的时候看到知乎上有人发了一个踩坑的文章,里面说安装的版本实际上是cpu版本,所以才不能使用,去conda安装目录下一看,好家伙确实如此,直接去gpu的库地址安装一份gpu的版本就可以正常使用了。

pytorch-gpu

is_available

如何下载YouTube视频/如何使用pytube

在YouTube上看到一些比较好看的视频,想要把一个系列都下载下来。

简单分析了一下网站,感觉还可以,但是需要费时间,然后就想到了可以用现成的库,之后就想到了以前用过的一个库–pytube。

pytube的文档:https://pytube.io/en/latest/

pytube安装:pip install pytube

首先就是需要可以翻墙,这点是必须要的。

然后就是安装一下这个库。

我还用到了plyer这个库,做windows弹窗用。

plyer windows弹窗

但是我简单上手后发现弹窗会堆积,没去查怎么解决这个问题。

pytube这个库其实很容易就上手了,我下载的视频是有播放列表的,所以可以直接循环列表下载就行,如果是单独的视频的话,使用视频的url就可以下载,不过这样的话,我比较推荐直接使用网站下载(油猴插件)

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
from pytube import YouTube
from pytube import Playlist
from time import sleep
from plyer import notification
from pytube.cli import on_progress


def download_ok(msg):
notification.notify(
title="YouTube下载提示",
message=msg,
app_icon=r"favicon.ico",
timeout=10,
)


a1 = 'https://www.youtube.com/playlist?list='
a2 = "https://www.youtube.com/playlist?list="
b1 = "https://www.youtube.com/playlist?list="
b2 = "https://www.youtube.com/playlist?list="
videoList = [a1, a2, b1, b2]
s = 0
d = ["a1", "a2", "b1", "b2"]
for a in videoList:
p = Playlist(a)
index = 0
proxies = {
"http": "http://127.0.0.1:7890",
"https": "http://127.0.0.1:7890"
}
f = d[s]
for url in p.video_urls:
while 1:
try:
yt = YouTube(url, proxies=proxies, on_progress_callback=on_progress)
title = yt.title
YTstream = yt.streams.get_highest_resolution()
download_ok("视频{}开始下载".format(title))
print('download ---')
# video.streams.get_highest_resolution().download(output_path="./a1")
YTstream.download(output_path="./"+f)
print('download ok')
download_ok("视频{}下载成功".format(title))
download_ok(title)
sleep(5)
break
except Exception as e:
print(e)
sleep(5)
s = s + 1
print(f+'all download')
print("ok")

其实逻辑是非常简单的,就是循环列表。

我这里是4个列表a1,a2,b1,b2。然后我把这四个列表便利出来,使用Playlist这个方法将该列表的信息取出来。

之后再通过video_urls取出list中所有视频的url。

然后通过Youtube()这个方法初始化一下内容。

再就是下载视频了,我这里之所以有一个while 1和try是因为视频下载可能会出现问题,然后我不想因为问题而耽搁,就直接无限循环了,如果正常的话,就break出来,不正常就重新下载。

更多的用法其实搜一下文档就可以了,当然直接在pycharm可以看提示。

pyscript教程--快速上手

不得不佩服一下老美。
pyscript顾名思义,就是在web上写python script,当然JavaScript这个冒牌货是不能和pyscript相比的。

1
2
<link  rel="stylesheet" href=" https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js" ></script>

首先需要在网页上导入这两个文件,应该一个是加载格式,一个是调用python引擎。

然后就是需要有两个标签,其实也就是类似于vue之类的,有自己专属的标签,在里面写的内容是通过专属js,css进行加载的。

  • <py-script>: can be used to define python code that is executable within the web page. The element itself is not rendered to the page and is only used to add logic
  • <py-repl>: creates a REPL component that is rendered to the page as a code editor and allows users to write executable code

其实除了这两个还有一个标签也需要使用,就是<**__py-env__**>这个标签是用来导入库的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>

<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>

</head>
<py-env>
- moudle
</py-env>
<body>
<py-script>
print('hello world')
</py-script>
</body>
</html>

首先如果需要导入库的话,请在py-env上写上需要导入的库,然后就是py-script标签内的内容,一定要顶格写,然后就是该缩进缩进,跟python正常的语法一个样子。

其实之所以能够使用pyscript,是因为加载的时候,添加了defer,让script延时加载,之后才能正常使用python。

具体的加载记录都卸载了console面板,大家可以去看一下。

1
2
3
<py-script>
print('hello world')
</py-script>

简单写了一个hello world。目前是你需要的库,本地要安装好才能使用,如果本地没有,那么就会报错。

最后放一个数据分析的demo
pyscript数据分析

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<link rel="icon" type="image/x-icon" href="./favicon.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="theme-color" content="#000000">
<meta name="name" content="PyScript/Panel Streaming Demo">

<title>PyScript/Panel Streaming Demo</title>
<link rel="icon" type="image/x-icon" href="./favicon.ico">

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
type="text/css" />
<link rel="stylesheet" href="https://unpkg.com/@holoviz/[email protected]/dist/css/widgets.css" type="text/css" />
<link rel="stylesheet" href="https://unpkg.com/@holoviz/[email protected]/dist/css/markdown.css" type="text/css" />

<script type="text/javascript" src="https://unpkg.com/[email protected]/dist/js/tabulator.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"></script>
<script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/@holoviz/[email protected]/dist/panel.min.js"></script>
<script type="text/javascript">
Bokeh.set_log_level("info");
</script>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://unpkg.com/@holoviz/[email protected]/dist/bundled/bootstraptemplate/bootstrap.css">
<link rel="stylesheet" href="https://unpkg.com/@holoviz/[email protected]/dist/bundled/defaulttheme/default.css">

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>

<link rel="stylesheet" href="./pyscript.css" />
<script defer src="./pyscript.js"></script>
</head>

<py-env>
- bokeh
- numpy
- pandas
- panel
</py-env>

<body>
<div class="container-fluid d-flex flex-column vh-100 overflow-hidden" id="container">
<nav class="navbar navbar-expand-md navbar-dark sticky-top shadow" id="header"
style="background-color: #000000;">
<button type="button" class="navbar-toggle collapsed" id="sidebarCollapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="app-header">
<a class="navbar-brand app-logo" href="/">
<img src="./favicon.ico" class="app-logo">
</a>
<a class="title" href="" style="color: #f0ab3c;">Panel Streaming Demo</a>
</div>
</nav>

<div class="row overflow-hidden" id="content">
<div class="col mh-100 float-left" id="main">
<div class="bk-root" id="controls"></div>
<div class="row">
<div class="bk-root" id="table"></div>
<div class="bk-root" id="plot"></div>
</div>
</div>
</div>
</div>
<py-script>
import asyncio

import panel as pn
import numpy as np
import pandas as pd

from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from panel.io.pyodide import show

df = pd.DataFrame(np.random.randn(10, 4), columns=list('ABCD')).cumsum()

rollover = pn.widgets.IntInput(name='Rollover', value=15)
follow = pn.widgets.Checkbox(name='Follow', value=True, align='end')

tabulator = pn.widgets.Tabulator(df, height=450, width=400)

def color_negative_red(val):
"""
Takes a scalar and returns a string with
the css property `'color: red'` for negative
strings, black otherwise.
"""
color = 'red' if val < 0 else 'green'
return 'color: %s' % color

tabulator.style.applymap(color_negative_red)

p = figure(height=450, width=600)

cds = ColumnDataSource(data=ColumnDataSource.from_df(df))

p.line('index', 'A', source=cds, line_color='red')
p.line('index', 'B', source=cds, line_color='green')
p.line('index', 'C', source=cds, line_color='blue')
p.line('index', 'D', source=cds, line_color='purple')

def stream():
data = df.iloc[-1] + np.random.randn(4)
tabulator.stream(data, rollover=rollover.value, follow=follow.value)
value = {k: [v] for k, v in tabulator.value.iloc[-1].to_dict().items()}
value['index'] = [tabulator.value.index[-1]]
cds.stream(value)

cb = pn.state.add_periodic_callback(stream, 200)

controls = pn.Row(cb.param.period, rollover, follow, width=400)

await show(controls, 'controls')
await show(tabulator, 'table')
await show(p, 'plot')
</py-script>
</body>
</html>

通过node.js+python实现蓝奏云上传服务

1. cookie获取

首先是cookie,这个想必大家都知道,我们登录一个网站后,再次访问如果不需要输入密码的话,那么就是cookie的帮助了.所以我们如果需要上传文件,那么就需要使用cookie.

1.2 获取

既然cookie这么重要,那么应该怎么获取呢?大多数的网站,都是通过客户端发送账号密码到服务器,然后服务器返回set-cookie,之后客户端根据set-cookie设置cookie,之后每次访问该网站的时候,都会把cookie传入.这样就不需要输入账号密码登录了.
但是这里有人会问,为什么有的网站登录一段时间后就需要重新登录呢?这里就需要说到cookie的时效性了,cookie大多数的网站都不是永久登录的,可能是浏览器关闭就失效,可能是1天失效,还有可能是30天等等.
这里简单看一下php的setcookie函数

1
setcookie(name,value,expire,path,domain,secure)
参数描述
name必需。规定 cookie 的名称。
value必需。规定 cookie 的值。
expire可选。规定 cookie 的有效期。
path可选。规定 cookie 的服务器路径。
domain可选。规定 cookie 的域名。
secure可选。规定是否通过安全的 HTTPS 连接来传输 cookie。

所以,cookie获取不是一次性就可以的,需要根据时间来获取.那么应该怎么获取呢?
目前其实就三种方法:

  1. 自己登录然后打开f12,选择Network,刷新网页,然后找到网站的请求(一般第一个),找到request headers内的cookie,然后就可以使用了.
  2. 通过逆向,获取账号密码加密的参数,之后模拟请求获取cookie
  3. 通过puppeteer/playwright/selenium等库模拟登录获取cookie

目前其实应该就这三种方法,其中1最简单,但是麻烦.2最方便但是难,所以我们选择3.
通过模拟浏览器进行cookie的获取.这里我们使用的是puppeteer.
如果只是单纯使用puppeteer模块的话,是不行的,这应该是会对浏览器指纹进行判断,所以我们这里要用到的是puppeteer-extra这个库.
通过puppeteer-extra这个库,我们可以让浏览器像正常的浏览器一样使用.之后再登录即可.

然后蓝奏云登录有一个滑动验证,这里也有两个方法可以通过,一个是模拟滑动,一个是通过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
26
27
28
29
30
31
32
33
34
35
36
const puppeteer = require('puppeteer-extra')
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
(async ()=>{
let browser = await puppeteer.launch({
headless: false,
args: [
`--proxy-server=127.0.0.1:7890`,
"--disable-gpu",
"--no-sandbox",
"--disable-setuid-sandbox",
],
})
let page = await browser.newPage();
await page.goto('https://pc.woozooo.com/');
await page.waitForTimeout(1000);
await page.click(".y6");
await page.waitForTimeout(1000);
await page.type("#username", "123");
await page.type(".pwd", "123");
await page.waitForTimeout(1000);
const btn = await page.$('.nc_iconfont.btn_slide');
let box = await btn.boundingBox();
await page.mouse.move(box.x+5, box.y+5)
await page.mouse.down()
await page.mouse.move(box.x+70, box.y+3, {steps: 30})
await page.mouse.move(box.x+150, box.y+5, {steps: 30})
await page.mouse.move(box.x+250, box.y+2, {steps: 30})
await page.mouse.up()
await page.waitForTimeout(1000);
await page.click("#s3");
await page.waitForTimeout(1000);
console.log(await page.cookies())
console.log(await page.title());
await browser.close();
})()

1.3 使用

我们可以将cookie保存到文件中,然后通过python的with open读取该文件,然后发送请求即可.

2. 上传

上传这里我使用的是python,其实只用node.js也可以,或者只用python.
我们要用到的一个是requests库,一个是requests_toolbelt库,其中requests_toolbelt库是为了对文件进行处理,可以通过post将数据传递到服务器上.

1
2
import requests
from requests_toolbelt import MultipartEncoder
1
2
3
4
5
6
7
8
9
10
url = "https://pc.woozooo.com/fileup.php"
headers = {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
"cache-control": "no-cache",
"pragma": "no-cache",
"referer": "https://pc.woozooo.com",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36",
}

url为蓝奏云上传文件到服务器的php网址,我们只需要向它传值即可.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
m = MultipartEncoder(
fields={
"task": "1",
"ve": "2",
"id": "WU_FILE_5",
"name": "名字",
"type": "application/pdf",
"lastModifiedDate": "Fri Mar 18 2022 22:31:14 GMT+0800 (中国标准时间)",
"size": "42671023",
"folder_id_bb_n": "-1",
"upload_file": ("文件名", open("文件名", 'rb'), 'application/octet-stream'),
}
)
headers['Content-Type'] = m.content_type
res = requests.post(url, headers=headers, proxies=proxies, data=m)
print(res.text)

这样,我们就可以将文件上传到蓝奏云服务器上了,但是node.js和python怎么整合到一块使用呢?

面向Ubuntu编程

本地环境弄得一团糟,懒得整理,所以借着学习Sanic的机会,在服务器上搭了一个python环境,使用的anaconda来管理不同版本不同需求的python环境.

首先就是需要一台服务器,我是用的虎年回馈在腾讯云买的,3年264还可以.
然后去anaconda官网下载bash文件执行安装.
我是参考的这个教程来做的,我把关键步骤摘出来了.
参考链接https://blog.csdn.net/zimiao552147572/article/details/105455258

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
1.官网下载Anaconda安装包
https://www.anaconda.com/distribution/#download-section
选择 64-Bit (x86) Installer (506 MB)

2.安装
bash Anaconda3-2019.10-Linux-x86_64.sh
注意:
安装过程会出现多次ENTER或YES,按要求输入,直到安装结束
直接按enter查看协议,然后一直enter下去,
看到 [yesno] 直接输入yes 然后按enter,进入下一步。

3.配置环境变量
1.打开.bashrc文件 vim ~/.bashrc 或者 vim /etc/profile
文件末尾添加一行 export PATH="/home/用户名/anaconda3/bin:$PATH"
还没装vim可以执行:sudo apt-get install vim
2.使配置马上生效 source ~/.bashrc 或者 source /etc/profile
3.修改只读文件方式:
1.方式一:使用root修改只读文件
sudo passwd root
su - root
2.方式二
VIM强制保存只读文件的方法底行命令模式执行 :w !sudo tee %
然后出现选项:确定([O]), 加载文件((L))
然后按L,再按ZZ即可

4.查看是否安装成功
输入 conda --version 查看版本信息

安装的时候需要退出root权限,我之前就是在root权限下安装的,然后安装到了root/anaconda3中,但是在默认权限下是使用不了的,然后换回root也不行,所以要在默认的权限下安装.

安装完成后会出现一个问你是否设置环境的选项

1
2
3
installation finished.
Do you wish the installer to initialize Anaconda3
by running conda init? [yesno]

请选择yes
然后再刷新一下文件source ~/.bashrc即可

之后创建环境,我创建了一个3.8的环境,虽然小版本跟我本地不一样,但是大版本一致

1
conda create --name python38 python=3.8

然后进入环境即可

1
conda activate python38

之后创建文件名为run的python文件,输入print(‘hello world!’)
保存退出,然后输入python run.py,会打印出hello world!
然后我们想不适用python就执行run.py文件,那么就需要在文件前加上

1
2
#!python位置
#!/usr/bin/env/python

这个python位置我们自然要使用conda创建的环境中的python,输入which python3会出现python的位置,把这个位置复制到#!后面即可

ps: 其实不需要那么麻烦的配置环境变量,在安装完成后source ~/anaconda3/bin/activate 启动conda,然后在环境里使用conda init 就会自动配置好anaconda环境,之后退出环境即可.https://blog.csdn.net/radiantjeral/article/details/110288050

通过TinyProxy+Stunnel搭建一个代理服务器

一、前提

工作需要用到代理爬一下境外的网站,但是自己找的哪些免费的都不是很好使,不是超时就是被封禁。

所以自己买了个美国的服务器,准备自己搭建一个代理,供自己使用。

工具

  1. 一台服务器
  2. 一台客户端

二、搭建

首先我是准备使用squid搭建服务器的,但是发现现在国内貌似单单搭建squid的话,只能访问国内的网站,国外的访问不了,并且如果是境外的服务器,可能连国内的网站都访问不了,所以当时其实是比较崩溃的,不过如果有人想要尝试,我可以简单说一下其中的问题:
squid

照着教程配置的话,其中有一个是给所有的连接权限,如果设置的0.0.0.0/0.0.0.0的话,启动是会报错的,我们应该使用all来给全体访问连接权限。

然后就是直接切入正题,说说我用的方法

TinyProxy+Stunnel

我是用的TinyProxy+Stunnel这两个合起来搭建的。
首先是是安装这两个库

TinyProxy
1
yum install -y tinyproxy

如果提示nothing的话,那么就代表你的服务器包管理种没有tinyproxy,那么就是用下面的指令来下载即可

1
2
3
yum install -y epel-release
yum update -y
yum -y install tinyproxy

安装完成后我们进行配置

1
vim /etc/tinyproxy/tinyproxy.conf

我为了测试就设置的所有人都允许访问我这台主机,
也就是把

1
Allow 127.0.0.1

注释掉
然后简单说一下其中比较有用的几个内容

1
2
Port 8888
#DisableViaHeader Yes

这两个,第一个是端口,第二个是请求头,可以根据自己的需求进行修改。

1
2
systemctl start tinyproxy.service
systemctl enable tinyproxy.service

一个是启动tinyproxy一个是关闭tinyproxy

1
2
3
4
# 允许访问
iptables -I INPUT -p tcp --dport 8888 -j ACCEPT
# 拒绝访问
iptables -I INPUT -p tcp --dport 8888 -j REJECT

然后再给予访问权限,再设置一下防火墙就可以了。

1
2
firewall-cmd --zone=public --add-port=8888/tcp --permanent
firewall-cmd --reload
Stunnel

之后我们再配置一下stunnel

1
2
yum install -y stunnel
vim /etc/stunnel/stunnel.conf

应该打开stunnel.conf会发现文件是空的,我们直接把写好的配置复制进去就好了。

1
2
3
4
5
[tinyproxy]
accept = 0.0.0.0:3128
connect = 0.0.0.0:8888
cert = /etc/ssl/cert.pem
key = /etc/ssl/key.pem

accept的端口我们随便设置一个任意的就行
然后connect是前面tinyproxy的端口。
下面的两个是证书。

安装证书,上面是命令,下面是信息

1
2
3
4
5
openssl genrsa -out /etc/ssl/key.pem 4096
Generating RSA private key, 4096 bit long modulus
......................................................................++
..............................................................++
e is 65537 (0x10001)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
openssl req -new -x509 -key /etc/ssl/key.pem -out /etc/ssl/cert.pem -days 1826
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:Arizona
Locality Name (eg, city) [Default City]:Phoenix
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:VM_0_17_centos
Email Address []:[email protected]
ls -lh /etc/ssl/
total 8.0K
-rw-r--r-- 1 root root 2.1K Feb 17 11:03 cert.pem
lrwxrwxrwx 1 root root 16 Feb 6 11:56 certs -> ../pki/tls/certs
-rw-r--r-- 1 root root 3.2K Feb 17 10:55 key.pem

然后我们启动stunnel即可

1
stunnel

不过这里我们需要给3128开一下防火墙,要不然是访问不了的。

1
2
firewall-cmd --zone=public --add-port=3128/tcp --permanent
firewall-cmd --reload
配置windows客户端

之后我们配置windows客户端即可。
首先需要下载stunnel客户端
https://www.stunnel.org/downloads.html下载对应的版本然后安装即可。
之后使用xftp连接服务器,然后将前面生成的cert.pem证书下载到stunnel客户端的config内。

然后再配置一下stunnel.conf即可。

1
2
3
4
5
6
7
8
9
debug = info
output = stunnel.log

[tinyproxy]
client = yes
accept = 2221
connect = x.x.x.x:3128
CAfile = cert.pem
verify = 3

connect就是你服务器的地址,然后accept就是你设置代理的地址,配置好后打开客户端重载一下配置即可。

然后我们设置一下浏览器,推荐使用的插件是switchyOmega,简单配置上我们的ip和端口就可以访问了127.0.0.1:xxxx

使用python访问
1
2
3
4
5
6
7
8
9
10
import requests
proxies = {
"http":"http://127.0.0.1:xxxx",
"https":"http://127.0.0.1:xxxx"
}

url="https://www.google.com"
res=requests.get(url, proxies=proxies, timeout=5)
print(res)
print(res.text)

这里要注意的一点就是timeout的设置,不要太短,因为加载传输需要一点点时间,如果设置太短的话,会百分百超时的。

requests请求谷歌翻译遇到400该怎么解决?

前请提要

逛52论坛的时候,看到有人问为啥谷歌翻译会返回400
52论坛自己试了一下发现是因为传值格式才会返回400,下面简单讲一下自己的流程

简单测试

首先先去谷歌翻译的网站,看一下请求的流程
requests请求谷歌翻译遇到400该怎么解决?
发现上面这个请求就是发送要翻译的内容,然后再获取返回值的请求
requests请求谷歌翻译遇到400该怎么解决?
然后再看一下参数

之后简单写一个请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"
}

data = {
"f.req":'[[["MkEWBc","[[\"玩\",\"zh-CN\",\"en\",true],[null]]",null,"generic"]]]'
}

p = requests.post(url="https://translate.google.cn/_/TranslateWebserverUi/data/batchexecute",headers=headers,data=data)

print(p.status_code)
print(p.text)

发现返回值是400,很迷

解决

我当时其实以为的是会有什么检测,但是仔细一想,不应该啊。
然后发现用f.req: %5B%5B%5B%22MkEWBc%22%2C%22%5B%5B%5C%22%E7%8E%A9%5C%22%2C%5C%22zh-CN%5C%22%2C%5C%22en%5C%22%2Ctrue%5D%2C%5Bnull%5D%5D%22%2Cnull%2C%22generic%22%5D%5D%5D
这个值做请求的话,会正常返回200,那么原因其实就是出在参数上了,但是具体是什么原因呢?
还是不是很清楚,于是换了个浏览器。
首先试的试edge发现跟谷歌没啥区别,然后就试了一下火狐,发现问题所在了
requests请求谷歌翻译遇到400该怎么解决?
参数上的英译汉,然后翻译内容等等,前面的不是随便加的,是参数的一部分,所以应该加\\\"其实就是\“这个,而如果只用\"的话结果则是”,所以就导致传的内容出现了问题,然后就会返回400了,更改一下参数就会返回正常的值了。

1
2
3
4
5
6
200
)]}'

[["wrb.fr","MkEWBc","[[\"Wán\",null,null,[[[0,[[[null,1]],[true]]]],1]],[[[null,null,null,null,null,[[\"Play\",null,null,null,[[\"Play\",[4,5]]]]]]],\"en\",1,\"zh-CN\",[\"玩\",\"zh-CN\",\"en\",true]],\"zh-CN\",[\"玩\",null,null,null,null,[[[\"名词\",[[\"play\",null,[\"玩\",\"游戏\",\"戏\",\"戏剧\",\"比赛\",\"剧\"],1,true]],\"en\",\"zh-CN\"],[\"动词\",[[\"play\",null,[\"玩\",\"玩耍\",\"游玩\",\"演\",\"玩儿\",\"玩弄\"],1,true],[\"enjoy\",null,[\"享受\",\"享有\",\"欣赏\",\"享\",\"拥有\",\"玩\"],3,true],[\"toy\",null,[\"玩\",\"玩弄\"],3,true],[\"have fun\",null,[\"玩\",\"玩耍\"],3,true],[\"amuse\",null,[\"游玩\",\"玩耍\",\"娱\",\"玩\",\"敖\",\"惊愕\"],3,true],[\"joke\",null,[\"开玩笑\",\"玩\",\"戏\",\"敖\"],3,true],[\"treat lightly\",null,[\"玩\",\"等闲观之\"],3,true]],\"en\",\"zh-CN\"]],8],null,null,\"zh-CN\",1]]",null,null,null,"generic"],["di",25],["af.httprm",24,"8012391421297243024"]]

Process finished with exit code 0

python实战分析:抖音短视频下载

本来其实我是很懒很懒的,所以好久都没有更新网站了,没想到今天白天更新了一下,晚上又发现了一个很好的东西来进行更新,那就是题目。

目前抖音已经上线了网页版,那么我们想要爬取他的视频就不需要钻研安卓了,我们只需要通过 Python,来进行爬取就可以了。

https://www.douyin.com/ 这个是抖音的官网,一进去就发现其实这个页面是非常干净的,没有什么垃圾广告之类的,不过其实大多数的网站都没有什么小弹窗。

不过发现看视频也没有广告,不过我预计后期可能会加广告,毕竟通过网页来看短视频其实并没有用手机看舒服。

抖音主页面

现在我有一个不知道是好是坏的习惯,就是看见视频页面就理所应当的 F12 查看一下这个视频是否能够下载,既然如此,那么我们就看一下这个视频吧。

抖音视频页

可以很容易的发现我们找到了想要的东西,我们只需要找到链接然后右键 Open in New Web 即可,然后就能将视频下载下来了,这里就不写 Python 代码了,太简单了,只是简单的分析一下而已。

然后其实接下来就是分析一下链接了。

https://www.douyin.com/video/6976573531568016678?previous_page=search_result&extra_params=%7B%22search_id%22%3A%2220210622202739010212081217280CAE8C%22%2C%22search_result_id%22%3A%226976573531568016678%22%2C%22search_type%22%3A%22video%22%2C%22search_keyword%22%3A%22%E6%88%91%E7%9A%84%E4%B8%96%E7%95%8C%22%7D

找了一个视频页来进行分析一下啊,首先开头到 video 都是没有什么意义的东西,然后就是 6976573531568016678 这个是视频的 id,然后 previous_page=search_result 这个应该是说明视频是从哪里来的,后面的内容大概猜了一下就是我搜索的内容然后再加上一些标记来记录这个搜索词,之所以这么认为是因为如果我从这个人的主页打开的话,那么视频页的链接就不是这样的了。

https://www.douyin.com/video/6954614178195721480?previous_page=others_homepage 后面的 previous_page=others_homepage,这个应该是说明这个视频是从作者的主页打开的,所以我们其实这个视频只需要获取 id 即可修改打开所有的网页。

然后再说一下搜索页,https://www.douyin.com/search/我的世界?aid=24c82fdf-b203-44c4-b5ef-bf7489162346&publish_time=0&sort_type=0&source=normal_search&type=video 这里我搜的是我的世界,aid 这个应该是随机的进行记录,然后再就是 publish_time 这个我猜应该是搜索用的时间不过大概率不是,意思是发布时间,但是结果是 0。。。。

搜索页面

然后发现这个有一个发布时间的选项,点击尝试,发现这个 publish_time 是这个一天内一周内半年内的修改值。我随便修改一个值发现没啥用,所以这个应该是定值,0,7,182,分别是一天内,一周内和半年内。

在接下来是 sort_type 这个有了上面的基础,很容易就知道是排序,值分别是 0,1,2 代表的是综合,最多,最新。

source=normal_search 这个我只发现了两个值一个实 history_search 一个是 normal_search,后面的是普通搜索,前面的我

猜是通过搜索历史来搜索。

还有一个值是 search_sug,这个是通过下拉菜单搜索得到的值。

然后最后就是 type 这个就是 video 和 user 了,分别是视频和用户。

然后再简单分析一下用户主页的链接吧。

https://www.douyin.com/user/MS4wLjABAAAAvs39O22rH-34wotF0Zzz5DrGhanbUEJsfeZ79eCPgz4?enter_method=video_title&author_id=94869865259&group_id=6954614178195721480&log_pb=%7B%22impr_id%22%3A%22021624364984797fdbddc0100fff0030a0c325800000034b9e876%22%7D&enter_from=video_detail

是这里 user 其实跟视频一样,就是在说明这个页面是干啥的页面。然后 MS4wLjABAAAA 我发现是固定的。后面是随机的,我猜是标记,因为这个同一个人是不变的。之后 enter_method 这个是进入主页的方式,video_title 这个值应该是我们通过点击这个人进入的主页,没发现别的凡是,然后 author_id 这个是作者的 id,然后再就是 group_id 这个是记录你从那个页面进入主页的,目前我发现的是通过某个视频进入这个主页,那么 group_id 就会是这个视频的 id。

后面的就不知道是啥意思了,如果有懂的可以评论一下大家交流一下。

python-baidu-api-submission

之前一直用的一个关于百度 API 提交的工具貌似不好用了,所以准备自己写一个。

其实感觉不好用可能是因为我的站点信息里看提交都是0。但大概率是百度自己出了问题,既然如此,那么还是重新写一个工具吧。

我们可以看百度自己的教程和示例:

post 推送示例

POST /urls site=www.58.com&token=edk7ychrEZP9pDQD HTTP/1.1
User-Agent: curl/7.12.1
Host: data.zz.baidu.com
Content-Length: 83
http://www.example.com/1.html
http://www.example.com/2.html

我们仿照一下写一个 headers 即可。

1
2
3
4
5
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36,',
'Host': 'data.zz.baidu.com',
'Content-Length': '83'
}

然后创建一个函数来进行判断是否有链接和 API 导入,当然我这次写的是可以直接用的,只需要创建一个 api.txt 然后把 API 放进去,创建一个 links.txt 把链接放进去,每行一个链接即可。

本次主要使用了三个库,分别是 requestsretime。它们分别用于提交、提取以及等待。

具体的效果还是自己测试吧,我把代码放在这里一份,另一份放在我的 GitHub 上:

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
import requests
import re
import time

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36,',
'Host': 'data.zz.baidu.com',
'Content-Length': '83'
}

print("*"*30)
print('links.txt 示例:\nhttps://xxxxx.html\nhttps://xxxxx.html\nhttps://xxxxx.html\nhttps://xxxxx.html')
print("*"*30)
print('api 示例:\nhttp://data.zz.baidu.com/urls?site=xxxxxxxxxxx')

push_num = 1

while push_num < 9999:
if push_num == 1:
answer = input("请问你是否已经将链接填入 links.txt,api填入 api.txt 中呢,如果是则回答1\n")
if answer == '1':
try:
with open('links.txt', 'r') as links:
links = links.read()
except FileNotFoundError:
print("links.txt 文件不存在")
try:
with open('api.txt', 'r') as api:
api = api.read()
except FileNotFoundError:
print("links.txt 文件不存在")

def thinklink(links, api):
if links == '':
print("links.txt 文件为空")
else:
if api == '':
print('api.txt 为空')
else:
try:
html_result = requests.post(api, headers=headers, timeout=5, data=links).text
return html_result
except:
return print("失败")

push_result = thinklink(links, api)
print('提交完成:' + push_result)

surplus_push_num = re.findall('"remain":(.*),"', push_result)
surplus_push_num = surplus_push_num.pop()
print('剩余' + surplus_push_num + '次提交机会')
else:
print("请将内容填充!")

time.sleep(5)
break

print('*'*30)
new_answer = input("是否还需要提交,如果是的话请先去更改一下相应文件,如果是请输入1,如果否请输入0\n")
if new_answer == '0':
print("提交结束")
time.sleep(5)
break

push_num += 1
print("现在开始第" + str(push_num) + '次提交')

如果有任何问题或疑问,可以在评论区留言,我会尽快回复。