通过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的设置,不要太短,因为加载传输需要一点点时间,如果设置太短的话,会百分百超时的。

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。

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

记一次失败的接单

学习,如果不是为了赚钱,有谁有动力呢?

需求详情: 需求详情

昨天在 Q 群看到有人需要进行样式修改,于是我接下了这个任务,发现实际上只是爬取了一个网站的内容,但样式不符合要求。

我从描述中就能够看出这是一个路径问题,而当我收到任务包后,发现确实是路径问题。如大家所知,某些网页是通过加载来显示内容的,爬取后并不包含后续内容。

奇怪的是雇主只需样式,不需要 JavaScript 效果,但我们都知道,滚动图(轮播图)大多需要 JavaScript 的支持。因此,我告诉雇主需要修改 JavaScript 路径,并下载新的资源等。然而,雇主坚持只要效果。

所以,我简单地爬取了图片,修改了路径并发送了出去。不过,遗憾的是每个页面底部都有一块空白。当时我以为是我的问题,但后来发现是网站设置的。我想着直接修改 height 并添加 !important 可能会解决问题,但结果并不如预期。

之前看过许多文章和帖子,讲述了遇到扯皮的雇主有多糟糕,但没想到我第一个项目就遇到了一个。因为我没有实现效果,没有去除底部的空白,我当时以为是 JavaScript 的问题,因为我在控制台看到了大约20个错误。虽然雇主说我在扯,但我还是想试试看。所以今天早上继续查看网页,并采取了不同的方法,检查页面元素,包括height、top、bottom、padding、margin等属性,因为它们容易影响网页的格式。

  • height:我发现每个页面的 height 都是固定的,然后通过 JavaScript 来修改。我尝试为 div 元素添加了 height !important,但效果不明显。
  • top:今天早上我发现了 top 元素,我们都知道网页由头部和底部组成,所以我检查了头部,发现了问题。底部的 footer 设置了 top 为 1712px,而且我发现所有页面的 footer 都有这个设置。我简单地修改了这个设置,问题得以解决。

其实,一开始尝试修改 height 时我并没有成功,甚至添加了 !important 也没有效果,我当时觉得这太神奇了。然后我简单地添加了一个边框来测试效果,发现修改高度后,边框位置明显在变化,但内部元素没有变化,然后我注意到有浮动定位。所以,我很快就分析出问题出在底部元素上。

为什么昨晚没有想到呢?我认为是因为脑子被问题困住了,所以在编程时,不管何时卡住了,换个思路,出去散步一下,就可能找到其他解决方法。虽然我睡了一觉,但这个问题还是得以解决。

最终,我将修改后的结果发送给了雇主,尽管这个项目非常失败,但我还是从中学到了许多经验。

typecho joe主题不显示侧栏博主随机文章


起因: 不显示作者下面的随机文。这个其实我用以前的版本是可以显示的,但是没想到换成新版后不显示了,自己进行了一些尝试,发现并没效果,所以准备放弃了。

结果: 完美解决。没想到后来在群里面发现了作者,然后跟作者聊了聊,解决了这个问题。

方法: 修改 Typecho 的设置,我们只需要修改它的 config.inc.php 文件即可,当然,这个文件是网站根目录里的文件。

作者的配置

您的配置

上图为作者的配置,下图为我的配置。我们只需要将 MySQL 修改成 Pdo_MySQL 即可,这个应该是因为传输协议或者连接方式不同所导致不显示作者下面的随机文章。修改后即可。

joe主题的样式该怎么写?

由于最终我转到了Handsome主题,所以之前的效果可能无法再看到,但是只要将代码复制到新环境中,它们应该仍然可用。

之前我一直使用的是Joe的4.5版本主题。在那个版本中,输入特殊字符后,CSS美化样式是通过方括号 [] 来实现的。然而,昨天我升级到了6版本后,发现所有样式都被取消了。我去查看了Joe的网站,发现他将样式改成了使用花括号 {},但有些样式可能也改了名字,不能像以前那样使用了。

因此,我尝试简单修改了一下这些样式:

  1. 标题:

    1
    {mtitle title="标题标题标题"}

    这个修改了名称,以前的我记得是使用 line

  2. 按钮:

    1
    {btn href="" type="default"}默认按钮{/btn}
  3. 提示消息:

    1
    {alt type="success"}成功提示的文案{/alt}
  4. 卡片:

    1
    {card-default width="100%" label="卡片标题"}卡片内容{/card-default}
  5. 隐藏内容:

    1
    2
    3
    4
    {collapse}
    {collapse-item label="标题"}我是隐藏的{/collapse-item}
    {collapse-item label="标题"}我是隐藏的{/collapse-item}
    {/collapse}
  6. 时间线:

    1
    2
    3
    4
    {timeline}
    {timeline-item}他出生了{/timeline-item}
    {timeline-item}他挂了{/timeline-item}
    {/timeline}
  7. 点击复制:

    1
    {copy}我是一个内容{/copy}
  8. 打字机效果:

    1
    {typing}打字机打字机,如果没有看到可以刷新再看一遍{/typing}
  9. 卡片导航:

    1
    2
    3
    4
    {card-nav}
    {card-nav-item src="http://baidu.com" title="百度一下" img="https://www.baidu.com/img/baidu_85beaf5496f291521eb75ba38eacbd87.svg" /}
    {card-nav-item src="http://baidu.com" title="百度一下" img="https://www.baidu.com/img/baidu_85beaf5496f291521eb75ba38eacbd87.svg" /}
    {/card-nav}

如果需要更多的示例,请查看文件路径:/usr/themes/Joe-master/core/short.php

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) + '次提交')

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

python 爬取知乎盐选全部内容

没想到进阶版来的这么快,在发布了python爬取知乎盐选文章内容后,没想到居然这么快就要更新新的内容了。 在下午思考第一篇python爬取知乎盐选文章内容的时候,其实就把自动爬取目录内的其他内容的方法想出来了,但是本来没想这么快更新的,哈哈。 不过思来想去还是发出来吧,毕竟要不哪天就忘了。

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
from DecryptLogin import login
from bs4 import BeautifulSoup
import re
import base64

lg = login.Login()
_, loginstauts = lg.zhihu(username='', password='', mode='pc')

headers = {
'user-agent': "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"
}

url1 = "https://www.zhihu.com/market/paid_column/1178733193687175168/section/1178742737682350080"
url2 = "https://www.zhihu.com/market/paid_column/1178733193687175168/section/1178742849583083520"

# 获取链接
r = loginstauts.get(url1, headers=headers)
wenzi = r.text
soup = BeautifulSoup(wenzi, 'lxml')
lianjie = soup.textarea
lianjie = str(lianjie)

pattern = re.compile('"next_section":{"url":"(.+)","is_end":') # 正则匹配链接所在的文字
result = pattern.findall(lianjie)

texts = soup.find_all('p')

for text in texts:
with open("yanxuan.txt", 'a', encoding='utf-8') as file_object:
file_object.write(text.get_text() + " ")

list = result.pop(0)
print(list)

for link in range(0, 9):
r2 = loginstauts.get(list, headers=headers)
wenzi = r2.text
soup = BeautifulSoup(wenzi, 'lxml')
lianjie = soup.textarea
lianjie = str(lianjie)

pattern = re.compile('"next_section":{"url":"(.+)","is_end":') # 正则匹配链接所在的文字
result = pattern.findall(lianjie)
list = result.pop(0)

texts = soup.find_all('p')

for text in texts:
with open("yanxuan.txt", 'a', encoding='utf-8') as file_object:
file_object.write(text.get_text() + " ")

python 爬取知乎盐选全部内容

直接上一手代码,讲一下思路,首先先是获取文本内容,通过前面的文章,我们知道 了如何获取文本内容,并且明白了该怎么获取整个页面的html内容。

本来最初的想法是把目录里的每一个链接都复制下来,然后通过遍历来获取链接,因为我最初是真的没发现下一篇的链接是通过哪里获得的。然后今天下午的时候,认认真真(闲的蛋疼)的看了一下知乎盐选文章内容的源代码,发现原来跳转链接在他的底部textarea里,并且还是在里面的一个next_section里,让我一顿好找,不过找到就是最好的啦。

找到之后,我们只需要获取到跳转的链接即可了,只需要使用正则进行条件筛选就可以了。

1
2
pattern = re.compile('"next_section":{"url":"(.+)","is_end":')  # 正则匹配链接所在的文字
result = pattern.findall(lianjie)

也就是这一段代码,我们对获取的内容进行匹配筛选,即可获得链接了,不过在获得之后,还是会出现一个问题,就是获取的内容会储存在列表里,我们还需要把列表的内容读取出来才能使用。本来其实最早我的思路是使用循环,然后把获取到的链接储存到同一个列表里,然后利用循环读取即可,但是因为当时脑子可能抽了,把变量的值给改错了,前面虽然该出来了,但是后面的都没改,就会得到一个很尴尬的结果,就是所有的结果都是同一个,然后我就换了种方法,没想到刚换就找到了问题所在。不过也懒得该回去了。

通过列表的方法pop来对列表内容进行删除,并且将删除返回的值进行保存,然后当作一个数据进行储存。也就是这一段的内容了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for link in range(0, 9):
r2 = loginstauts.get(list, headers=headers)
wenzi = r2.text
soup = BeautifulSoup(wenzi, 'lxml')
lianjie = soup.textarea
lianjie = str(lianjie)

pattern = re.compile('"next_section":{"url":"(.+)","is_end":') # 正则匹配链接所在的文字
result = pattern.findall(lianjie)
list = result.pop(0)

texts = soup.find_all('p')

for text in texts:
with open("yanxuan.txt", 'a', encoding='utf-8') as file_object:
file_object.write(text.get_text() + " ")

其他的也就没有什么难度的东西了,不过如果有什么疑问,可以在评论区留下你的疑惑,我会在看到的第一时间进行回复的。

网页音乐播放器 音乐播放器 html+css+js

首先准备工作为 jQuery、HTML、CSS、JavaScript,别的其实并不需要,而且其实 JavaScript 也不需要。 最初是准备不使用 jQuery 的,但是发现用 jQuery 只需要几行代码就能实现的功能,而用原生的 JavaScript 却需要好多,而且也不容易实现,所以最后才准备使用 jQuery 了。

jQuery 的安装各位应该都会吧,如果不会的话,我放一下代码。通过使用 Node.js 来安装,在你的 JS 文件夹里按住 Shift 键并右键,选择打开 PowerShell 窗口,之后只需要输入 cnpm install jquery 即可,或者直接去中文站下载也行,这里不多讲述了。

音乐播放器

列表的点击显示和隐藏就是通过 jQuery 来实现的,很简单,如果使用 JavaScript 还是那句话,麻烦。

之后文字的打字机效果是通过 typed 这个库来实现的,GitHub 跳转链接。其实这个效果加不加都是无所谓的,只是好看了一丢丢而已,并且其实我的 CSS 只是随便写了一下,完全可以稍微优化一下 CSS。

目前的效果也就是点击列表的歌曲,会自动切换音乐和图像,然后上面的目前播放的名字也会换成该音乐的名字。这个网页实现音乐播放器的功能很容易,基本上一眼就能看懂了,后期可能会加一些别的效果,并且把样子做一下,搞一下 CSS。

以下是代码和一些简单的讲解:

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
// JS,名字我是叫的 music.js
// 记录图片和音乐以及正在播放的名字
var mslists = ['./music/jar_of_love.mp3', './music/see_you_again.mp3', './music/sunshine_in_the_rain.mp3'];
var imglists = ['http://p1.music.126.net/8jt2KnGDF0qMP9JbidOtVA==/573945069746475.jpg', 'http://p2.music.126.net/JIc9X91OSH-7fUZqVfQXAQ==/7731765766799133.jpg', 'http://p1.music.126.net/bHQlt-zzDQlsnPydiYKsHw==/109951165124500529.jpg'];
var namelists = ["Jar of love", 'See you again', 'Sunshine in the rain'];

// 点击隐藏和显示
$(".liebiao").click(function() {
if ($(".msxulie").is(":hidden")) {
$(".msxulie").show();
} else {
$(".msxulie").hide();
}
});

// 文字效果
window.onload = function() {
var typed = new Typed(".zzbf", {
strings: ['', '音乐播放器正在播放:'],
startDelay: 300,
typeSpeed: 100,
loop: true,
backSpeed: 50,
showCursor: true,
cursorChar: '➼'
});
}

// 点击切换音乐
$(".jol").click(function() {
$(".mscontrol").attr("src", mslists[0]);
$(".msimg").attr("src", imglists[0]);
$(".msplayingtext").html(namelists[0]);
$(".mscontrol")[0].play();
});

$(".sya").click(function() {
$(".mscontrol").attr("src", mslists[1]);
$(".msimg").attr("src", imglists[1]);
$(".msplayingtext").html(namelists[1]);
$(".mscontrol")[0].play();
});

$(".sitr").click(function() {
$(".mscontrol").attr("src", mslists[2]);
$(".msimg").attr("src", imglists[2]);
$(".msplayingtext").html(namelists[2]);
$(".mscontrol")[0].play();
});

下面是 CSS 代码,这个我是叫的 index.css:

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
/* 播放器位置 */
.msplayer {
float: left;
background-color: aqua;
border-radius: 20%;
}

/* 播放器图片 */
.msplayer .msimg {
margin-top: 5px;
margin-left: 5px;
margin-bottom: 5px;
width: 60px;
height: 60px;
border-radius: 50%;
}

/* 播放器控制器 */
.msplayer .mscontrol {
margin-top: 5px;
margin-left: 5px;
margin-right: 5px;
width: 200px;
}

/* 播放器列表按钮 */
.msplayer .liebiao {
position: relative;
bottom: 25px;
}

/* 音乐列表 */
.msplayer .msxulie {
text-align: center;
width: 315.14px;
position: absolute;
display: block;
background-color: bisque;
top: 20px;
left: 315.14px;
border-radius: 20%;
cursor: pointer;
}

/* 正在播放 */
.msplaying {
position: absolute;
top: 0px;
left: 80px;
font-size: 10px;
}

$(".mscontrol").attr("src",mslists[0]);
$(".msimg").attr("src",imglists[0]);
$(".msplayingtext").html(namelists[0]);
$(".mscontrol")[0].play();

第一行是获取 audio 的 src 值,把它设置为我们数组里的值,第二行是更改图片,第三行是修改名字,最后一行其实加不加无所谓的,就是一个自动播放效果,如果换歌就进行自动播放。

然后我那两行注释是修改那个 typed 的效果的,但是发现函数执行了就很难停止,所

以就给注释掉了,效果也是很容易的,就是将那个 typed 效果创建成一个函数,之后调用即可,然后在里面设置一个变量用于接受我们传递的参数就好了,不过目前来说不会怎么停止已经运行的函数,所以这个想法就搁浅了。

CSS 代码没什么难度吧,应该,就是简单的浮动定位效果,把列表给浮动过去,然后 HTML 也是没什么难度的,自己看一眼就好了。

如果有什么不懂的可以在评论区评论,我会在看到的第一时间回复的。

python 外星人大战,飞船不移动怎么办

今天遇到的小问题!便对着书边敲代码,发现出现错误。python 外星人大战,飞船不移动。这个问题我首先是发去了吾爱,不过后期我自己解决了。如题,边看书边敲的代码,发现飞船不移动。求大佬帮忙看一下!主文件本来发现问题的时候是很慌的,我一开始是以为可能跟书上的内容不太一样,但是后来下了源代码发现确实应该那样。

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
# main.py
import pygame
from setting import Settings
from ship import Ship
import game_functions as gf

def run_game():
# 初始化游戏并且创建一个屏幕对象
pygame.init()

# 初始化背景属性
ai_settings = Settings()

# 使类setting里的内容直接被调用
screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion") # 窗口名字

# 创建飞船
ship = Ship(screen)

# 开始游戏的主循环
while True:
# 监视鼠标和键盘事件
gf.check_events(ship)
gf.update_screen(ai_settings, screen, ship)

run_game()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# game_functions.py
import sys
import pygame

def check_events(ship):
"""响应按键和鼠标事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT: # 向右移动飞船
ship.rect.centerx += 1
elif event.key == pygame.K_LEFT:
ship.rect.centerx -= 1

def update_screen(ai_settings, screen, ship):
"""更新数据"""
screen.fill(ai_settings.bg_color)
ship.blitme()
pygame.display.flip()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ship.py
import pygame

class Ship():
def __init__(self, screen):
"""初始化飞船位置"""
self.screen = screen

# 加载飞船图像并获取其外接矩形
self.image = pygame.image.load("images/ship.bmp")
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()

# 将每艘新飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom

def blitme(self):
"""在指定位置绘制飞船"""
self.screen.blit(self.image, self.rect)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ship.py
import pygame

class Ship():
def __init__(self, screen):
"""初始化飞船位置"""
self.screen = screen

# 加载飞船图像并获取其外接矩形
self.image = pygame.image.load("images/ship.bmp")
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()

# 将每艘新飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom

def blitme(self):
"""在指定位置绘制飞船"""
self.screen.blit(self.image, self.rect)

1
2
3
4
5
6
7
8
9
10
# setting.py
class Settings():
"""储存外星人大战的所有设置"""
def __init__(self):
"""初始化游戏的设置"""
# 屏幕设置
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)

最后还是把书上的内容都复制下来,然后挨个比对,发现错误是game_functions.py文件内第9行if event.type == pygame.K_RIGHT:应该把event.type改为event.key!! 敲代码还是要看仔细,仔细很重要,细节决定成败!

保皇记牌器

相信各位在日常休闲的时候总会打打保皇,够级的。就算平常不打,但是过年还是会打的。我今天在玩qq游戏里的保皇时,突然想做一个记牌器,虽然它自带记牌器但是毕竟花钱,本来想用c/java/python做一个软件通过图片识别功能自动计算的,但是发现学的不到家(确实只学了基础),这些东西一点没学,所以只好退而求其次,做一个简易的记牌器,通过自己的点击来计算场上剩余牌的数量。

保皇效果图 没错,就是这么的简陋,但是胜在代码简单。 具体思路其实就是通过JavaScript函数进行input里text的value值替换,点击按钮进行增加或者减少。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function add(){
var txt=document.getElementById("txt");
var a=txt.value; a++;
if(txt.value<16){
txt.value=a;
}
}
function sub(){
var txt=document.getElementById("txt");
var a=txt.value;
if(a>0){
a--;
txt.value=a;
}
else{
txt.value=0;
}
}

通过修改a++来达到不同的效果,不过其实我觉得非常麻烦,但是受于储存的知识面,目前来说不太会进一步修改,不过目前其实是想在每一个数的后面加上一个历史数据,就是本来值为16,你-4,text里的值变为12,但是历史数据还是16,然后再-1,text值变为11,历史数据变为12,类似这样,在下一个文档我会把他发出来。 最后上一下代码,由于有点长,所以只上一下html代码,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
<ul>
<li>
大王剩余:
<input type="text" id="txtd" value="4" />
<input type="button" onclick="addd()" value="+1">
<input type="button" onclick="subd()" value="-1">
</li>
<li>
小王剩余:
<input type="text" id="txtx" value="4" />
<input type="button" onclick="addx()" value="+1">
<input type="button" onclick="subx()" value="-1">
</li>
<li>
2剩余:
<input type="text" id="txt2" value="16" />
<input type="button" onclick="add21()" value="+1">
<input type="button" onclick="sub24()" value="-4">
<input type="button" onclick="sub23()" value="-3">
<input type="button" onclick="sub22()" value="-2">
<input type="button" onclick="sub21()" value="-1">
</li>
<li>
A剩余:
<input type="text" id="txta" value="16" />
<input type="button" onclick="adda1()" value="+1">
<input type="button" onclick="suba4()" value="-4">
<input type="button" onclick="suba3()" value="-3">
<input type="button" onclick="suba2()" value="-2">
<input type="button" onclick="suba1()" value="-1">
</li>
<!-- 接下来的卡牌以相同的模式继续 -->
</ul>
<script src="js/script.js">

最后把JavaScript代码外链进去即可! 附件最后还是变成了 云盘