Skip to content

Commit 7f1c95a

Browse files
author
danbai225
committed
更新
1 parent e7e1294 commit 7f1c95a

File tree

12 files changed

+536
-235
lines changed

12 files changed

+536
-235
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ build/
3030

3131
### VS Code ###
3232
.vscode/
33+
/py/gxpa.py

.idea/workspace.xml

Lines changed: 239 additions & 221 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,25 @@
1717
+ 观看看影视的同时能发送弹幕
1818
+ 跨平台同步观看历史记录
1919
+ 跨平台同步观看进度
20-
20+
+ 电视直播(开发中)
2121
## 项目所用到的
2222

2323
+ Spring Boot
2424
+ Mybits
2525
+ Redies
2626
+ MongoDB
2727
+ Docker
28-
2928
## 版本内容更新
30-
3129
### 2019-10-20
3230
+ 弹幕获取功能,不用担心一个人看没弹幕啦,在一些人气较高的影视会自动获取弹幕
3331
+ 修复注册邮箱发送问题
32+
### 2019-11-4
33+
+ 更新搜索功能支持演员、导演搜索影视
34+
+ 弹幕tagid获取将不在服务器而是py采集
35+
+ 影视信息补全
36+
+ 配置功能
3437
## 计划开发功能
38+
+ 电视直播功能
3539
+ 影视增加评论、评分功能
3640
+ 弹幕管理
37-
+ 搜索功能自动联想
3841
+ 淡白影视APP(开发中)

py/pa.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import json
2+
import random
3+
import requests
4+
from lxml import etree
5+
import re
6+
import pymysql
7+
from DBUtils.PooledDB import PooledDB
8+
from multiprocessing.pool import ThreadPool
9+
10+
11+
12+
POOL = PooledDB(
13+
creator=pymysql, # 使用链接数据库的模块
14+
maxconnections=0, # 连接池允许的最大连接数,0和None表示不限制连接数
15+
mincached=20, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
16+
maxcached=5, # 链接池中最多闲置的链接,0和None不限制
17+
maxshared=0, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
18+
blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
19+
maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
20+
setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
21+
ping=0,
22+
# ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
23+
host='127.0.0.1',
24+
port=3306,
25+
user='123',
26+
password='123',
27+
database='ys',
28+
charset='utf8'
29+
)
30+
class Ji:
31+
name=""
32+
url=""
33+
def __init__(self, name, url):
34+
self.name = name
35+
self.url = url
36+
37+
proxy=""
38+
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'}
39+
#获取代理
40+
def get_proxy():
41+
global proxy
42+
r=requests.get("http://ip.jiangxianli.com/")
43+
if(r.status_code==200):
44+
selector=etree.HTML(r.text)
45+
i=random.randint(1,15)
46+
proxy=selector.xpath("//button[@class=\"btn btn-sm btn-copy\"]/@data-url")[i]
47+
#获取页面html
48+
def getHtml(url):
49+
global proxy
50+
try:
51+
html = requests.get(url,headers=header,timeout=5)
52+
# 使用代理访问
53+
return html
54+
except Exception as e:
55+
get_proxy()
56+
print(e)
57+
run(url)
58+
def main():
59+
#get_proxy()
60+
conn = POOL.connection()
61+
cursor = conn.cursor()
62+
#获取最大id
63+
cursor.execute('SELECT MAX( id )FROM ysb')
64+
maxid=cursor.fetchone()[0]
65+
conn.close()
66+
#创建线程池
67+
pool = ThreadPool(20)
68+
for num in range(30000,maxid+200):
69+
url="http://www.okzyw.com/?m=vod-detail-id-{}.html".format(num)
70+
try:
71+
pool.apply_async(run, args=(url,))
72+
except Exception as e:
73+
print(e)
74+
pool.close()
75+
pool.join()
76+
print("结束")
77+
def run(url):
78+
conn = POOL.connection()
79+
cursor = conn.cursor()
80+
#获取页面数据
81+
r=getHtml(url)
82+
if(r.status_code==200):
83+
selector=etree.HTML(r.text)
84+
#获取需要数据
85+
id=re.compile("id-(.*).html").findall(r.url)[0]
86+
list=selector.xpath("//div[@class=\"vodh\"]/h2/text()")
87+
pm=ifnull(list)
88+
list=selector.xpath("//img[@class=\"lazy\"]/@src")
89+
tp="http://img.p00q.cn:222/ys.php?src="+ifnull(list)+"&q=50&w=200&h=285"
90+
list=selector.xpath("//div[@class=\"vodh\"]/span/text()")
91+
zt=ifnull(list)
92+
list=selector.xpath("//div[@class=\"vodh\"]/label/text()")
93+
pf=ifnull(list)
94+
list=selector.xpath("//div[@class=\"vodinfobox\"]/ul/li[1]/span/text()")
95+
bm=ifnull(list)
96+
list=selector.xpath("//div[@class=\"vodinfobox\"]/ul/li[2]/span/text()")
97+
dy=ifnull(list)
98+
list=selector.xpath("//div[@class=\"vodinfobox\"]/ul/li[3]/span/text()")
99+
zy=ifnull(list)
100+
list=selector.xpath("//div[@class=\"vodinfobox\"]/ul/li[4]/span/text()")
101+
lx=ifnull(list)
102+
if lx.find("福利") > -1:
103+
return
104+
list=selector.xpath("//div[@class=\"vodinfobox\"]/ul/li[5]/span/text()")
105+
dq=ifnull(list)
106+
list=selector.xpath("//div[@class=\"vodinfobox\"]/ul/li[6]/span/text()")
107+
yy=ifnull(list)
108+
list=selector.xpath("//div[@class=\"vodinfobox\"]/ul/li[7]/span/text()")
109+
sytime=ifnull(list)
110+
list=selector.xpath("//div[@class=\"vodinfobox\"]/ul/li[8]/span/text()")
111+
pctime=ifnull(list)
112+
list=selector.xpath("//div[@class=\"vodinfobox\"]/ul/li[9]/span/text()")
113+
gxtime=ifnull(list)
114+
list=selector.xpath("//div[@class=\"vodplayinfo\"]/text()")
115+
if(len(list)>0):
116+
js=list[3]
117+
jilist=selector.xpath("//span[text()=\"ckm3u8\"]/../../ul/li/text()")
118+
if len(jilist)>0:
119+
list=fenji(jilist)
120+
gkdz = json.dumps(list, ensure_ascii=False)
121+
else:
122+
gkdz="[]"
123+
jilist=selector.xpath("//div[@id=\"down_1\"]/ul/li/text()")
124+
if len(jilist)>0:
125+
list=fenji(jilist)
126+
xzdz = json.dumps(list, ensure_ascii=False)
127+
else:
128+
xzdz="[]"
129+
if pm!="":
130+
#向数据库插入数据
131+
sql="INSERT INTO ysb (id,pm,tp,zt,pf,bm,dy,zy,lx,dq,yy,sytime,pctime,gxtime,js,gkdz,xzdz) VALUES ({},'{}','{}','{}','{}','{}','{}','{}','{}','{}','{}','{}','{}','{}','{}','{}','{}') ON DUPLICATE KEY UPDATE zt='{}',gxtime='{}',gkdz='{}',xzdz='{}',tp='{}';".format(id,pm,tp,zt,pf,bm,dy,zy,lx,dq,yy,sytime,pctime,gxtime,js,gkdz,xzdz,zt,gxtime,gkdz,xzdz,tp)
132+
cursor.execute(sql)
133+
print("更新"+id+pm)
134+
conn.commit()
135+
conn.close()
136+
def fenji(jilist):
137+
list=[]
138+
for j in jilist:
139+
ji =Ji(j.split("$")[0],j.split("$")[1])
140+
list.append(ji.__dict__)
141+
return list
142+
def ifnull(list):
143+
if(len(list)>0):
144+
return list[0]
145+
return ""
146+
if __name__ == "__main__":
147+
main()

py/tagpa.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import json
2+
import random
3+
import requests
4+
from lxml import etree
5+
import re
6+
import pymysql
7+
from DBUtils.PooledDB import PooledDB
8+
from multiprocessing.pool import ThreadPool
9+
import redis
10+
11+
POOL = PooledDB(
12+
creator=pymysql, # 使用链接数据库的模块
13+
maxconnections=0, # 连接池允许的最大连接数,0和None表示不限制连接数
14+
mincached=20, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
15+
maxcached=5, # 链接池中最多闲置的链接,0和None不限制
16+
maxshared=0, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
17+
blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
18+
maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
19+
setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
20+
ping=0,
21+
# ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
22+
host='127.0.0.1',
23+
port=3306,
24+
user='ys',
25+
password='123',
26+
database='123',
27+
charset='utf8'
28+
)
29+
proxys=[]
30+
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'}
31+
#获取代理
32+
def get_proxy():
33+
global proxys
34+
r=requests.get("http://ip.jiangxianli.com/")
35+
if(r.status_code==200):
36+
selector=etree.HTML(r.text)
37+
proxys=proxys+selector.xpath("//button[@class=\"btn btn-sm btn-copy\"]/@data-url")
38+
#获取页面html
39+
def getHtml(url):
40+
global proxys
41+
p=proxys[random.randint(0,len(proxys)-1)]
42+
try:
43+
html = requests.get(url,proxies={'http':p},headers=header,timeout=5)
44+
if html!=None:
45+
return html.text
46+
except Exception:
47+
proxys.remove(p)
48+
if len(proxys)<2:
49+
get_proxy()
50+
return getHtml(url)
51+
def main():
52+
get_proxy()
53+
conn = POOL.connection()
54+
cursor = conn.cursor()
55+
cursor.execute('SELECT MAX( id )FROM ysb')
56+
maxid=cursor.fetchone()[0]
57+
cursor.execute('SELECT id,pm,dy,lx,gkdz,xzdz FROM `ysb` WHERE id >'+str(maxid-5000))
58+
data = cursor.fetchall()
59+
rpool = redis.ConnectionPool(host='127.0.0.1', port=6379,db=0,password='123')
60+
pool = ThreadPool(100)
61+
for ys in data:
62+
try:
63+
r = redis.Redis(connection_pool=rpool)
64+
pool.apply_async(run, args=(ys,r))
65+
except Exception as e:
66+
print(e)
67+
pool.close()
68+
pool.join()
69+
print("结束")
70+
def run(ys,r):
71+
if ys[4] != '[]':
72+
jys=json.loads(ys[4])
73+
else :
74+
jys=json.loads(ys[5])
75+
pm=ys[1]+ys[2]+ys[3]
76+
tnum=r.get(pm)
77+
if tnum==None:
78+
tnum=0
79+
else:
80+
tnum=int(tnum)
81+
if tnum<len(jys):
82+
fh=getHtml("http://v.qq.com/x/search/?q="+pm)
83+
ysid=re.compile("{id: '(.*)'; type: '2';}",re.M).findall(fh)[0]
84+
fh=getHtml("http://s.video.qq.com/get_playsource?plat=2&type=4&range=1&otype=json&id="+ysid)
85+
jsonj=json.loads(fh[13:-1])
86+
jlist=jsonj["PlaylistItem"]["videoPlayList"]
87+
taglist=[]
88+
if jsonj["PlaylistItem"]['payType']==2:
89+
for i in range (0,len(jlist)):
90+
tfh=getHtml("http://bullet.video.qq.com/fcgi-bin/target/regist?otype=json&vid="+jlist[i]['id'])
91+
tagid=json.loads(tfh[13:-1])['targetid']
92+
taglist.append(tagid)
93+
taglist.reverse()
94+
for i in range (0,len(jys)):
95+
r.set(pm+str(ys[0])+jys[i]['name'],taglist[i])
96+
if len(taglist) >0:
97+
print(pm+str(len(taglist)))
98+
r.set(pm,len(jys))
99+
if __name__ == "__main__":
100+
main()

src/main/java/com/danbai/ys/controller/YsController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ String search(String gjc, Model model) {
142142
if ("".equals(gjc)) {
143143
return "/index";
144144
}
145-
model.addAttribute("ysb", ysService.selectYsByPm(gjc));
145+
model.addAttribute("ysb", ysService.selectYsByGjc(gjc));
146146
model.addAttribute("gjc", gjc);
147147
return "search";
148148
}

src/main/java/com/danbai/ys/controller/restful/v1/Ys.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public BaseResult ysOne(@PathVariable int id) {
4848
*/
4949
@GetMapping("/ys/search/{gjc}")
5050
public BaseResult search(@PathVariable String gjc) {
51-
return ResultUtil.success(ysService.qcsy(ysService.selectYsByPm(gjc)));
51+
return ResultUtil.success(ysService.qcsy(ysService.selectYsByGjc(gjc)));
5252
}
5353

5454
}

src/main/java/com/danbai/ys/service/YsService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public interface YsService {
4444
* @return List<Ysb>
4545
*/
4646
List<Ysb> selectYsByPm(String pm);
47-
47+
List<Ysb> selectYsByGjc(String gjc);
4848
/**
4949
* 根据影视id查询影视返回影视列表
5050
*

src/main/java/com/danbai/ys/service/impl/AdminServiceImpl.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
*/
2020
@Service
2121
public class AdminServiceImpl implements AdminService {
22+
static String YES="yes";
23+
static String NO="no";
2224
@Autowired
2325
ConfigMapper configMapper;
2426
@Autowired

src/main/java/com/danbai/ys/service/impl/YsServiceImpl.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class YsServiceImpl implements YsService {
3737
RedisTemplate redisTemplate;
3838
@Autowired
3939
MongoTemplate mongoTemplate;
40+
@Autowired
41+
AdminServiceImpl adminService;
4042
static String NULL = "null";
4143
static String KONG = "";
4244
static int MIN_DM = 100;
@@ -72,6 +74,13 @@ public List<Ysb> selectYsByPm(String pm) {
7274
return ysbMapper.selectByExample(example);
7375
}
7476

77+
@Override
78+
public List<Ysb> selectYsByGjc(String gjc) {
79+
Example example = new Example(Ysb.class);
80+
example.createCriteria().andLike("pm", "%" + gjc + "%").orLike("zy","%" + gjc + "%").orLike("dy","%" + gjc + "%");
81+
return ysbMapper.selectByExample(example);
82+
}
83+
7584
@Override
7685
public List<Ysb> selectYsByIdlist(int id) {
7786
Example example = new Example(Ysb.class);
@@ -210,15 +219,18 @@ public String getYsDanMu(String pm ,String ysid) {
210219
return null;
211220
}
212221
if (rr != null && !rr.equals(KONG)) {
213-
if (redisTemplate.opsForSet().isMember(OKTAGIDS, rr)) {
214-
Query query = new Query(Criteria.where("player").is(ysid));
215-
if (mongoTemplate.count(query, Dan.class) < MIN_DM) {
216-
return rr;
222+
if(adminService.getConfig("dmcache").equals(AdminServiceImpl.YES)) {
223+
if (redisTemplate.opsForSet().isMember(OKTAGIDS, rr)) {
224+
Query query = new Query(Criteria.where("player").is(ysid));
225+
if (mongoTemplate.count(query, Dan.class) < MIN_DM) {
226+
return rr;
227+
}
228+
return null;
217229
}
218-
return null;
230+
String json = "{tagid:" + rr + ",player:\"" + ysid + "\"}";
231+
redisTemplate.opsForSet().add("tagids", json);
232+
return rr;
219233
}
220-
String json = "{tagid:" + rr + ",player:\"" + ysid + "\"}";
221-
redisTemplate.opsForSet().add("tagids", json);
222234
return rr;
223235
}
224236
return null;

0 commit comments

Comments
 (0)