初始化仓库
23
.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
26
README.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Rainfo Vue Template
|
||||||
|
|
||||||
|
## Description
|
||||||
|
Setup Procedure
|
||||||
|
## Project setup
|
||||||
|
```
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and hot-reloads for development
|
||||||
|
```
|
||||||
|
yarn run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and minifies for production
|
||||||
|
```
|
||||||
|
yarn run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lints and fixes files
|
||||||
|
```
|
||||||
|
yarn run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customize configuration (vue-cli)
|
||||||
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
19078
package-lock.json
generated
Normal file
56
package.json
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"name": "rainfo",
|
||||||
|
"version": "1.1.1",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@mdi/font": "^5.6.55",
|
||||||
|
"core-js": "^3.6.5",
|
||||||
|
"element-ui": "^2.15.14",
|
||||||
|
"feather-icons": "^4.28.0",
|
||||||
|
"hooper": "^0.3.4",
|
||||||
|
"vee-validate": "^3.4.5",
|
||||||
|
"vue": "^2.6.11",
|
||||||
|
"vue-masonry-wall": "^0.3.2",
|
||||||
|
"vue-router": "^3.4.5",
|
||||||
|
"vue-scrollactive": "^0.9.3",
|
||||||
|
"vue-slick-carousel": "^1.0.6",
|
||||||
|
"vuetify": "^2.2.11"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vue/cli-plugin-babel": "^4.5.0",
|
||||||
|
"@vue/cli-plugin-eslint": "^4.5.0",
|
||||||
|
"@vue/cli-service": "^4.5.0",
|
||||||
|
"babel-eslint": "^10.1.0",
|
||||||
|
"eslint": "^6.7.2",
|
||||||
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
|
"sass": "^1.19.0",
|
||||||
|
"sass-loader": "^8.0.0",
|
||||||
|
"vue-cli-plugin-vuetify": "^2.0.9",
|
||||||
|
"vue-template-compiler": "^2.6.11",
|
||||||
|
"vuetify-loader": "^1.3.0"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:vue/essential",
|
||||||
|
"eslint:recommended"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"parser": "babel-eslint"
|
||||||
|
},
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"last 2 versions",
|
||||||
|
"not dead"
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
public/favicon.ico
Normal file
|
After Width: | Height: | Size: 51 KiB |
21
public/index.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<!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">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<title>YOLO助手</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
|
||||||
|
Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
69
src/App.vue
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<v-app id="inspire">
|
||||||
|
<v-main>
|
||||||
|
<router-view></router-view>
|
||||||
|
</v-main>
|
||||||
|
<v-fab-transition>
|
||||||
|
<div
|
||||||
|
class="scrolltop-wrapper"
|
||||||
|
v-show="fab"
|
||||||
|
v-scroll="onScroll"
|
||||||
|
@click="toTop"
|
||||||
|
>
|
||||||
|
<div class="scrolltotop">
|
||||||
|
<div class="arrow-top"></div>
|
||||||
|
<div class="arrow-top-line"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</v-fab-transition>
|
||||||
|
</v-app>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fab: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onScroll(e) {
|
||||||
|
if (typeof window === "undefined") return;
|
||||||
|
const top = window.pageYOffset || e.target.scrollTop || 0;
|
||||||
|
this.fab = top > 60;
|
||||||
|
},
|
||||||
|
toTop() {
|
||||||
|
this.$vuetify.goTo(0);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.scrolltop-wrapper {
|
||||||
|
position: fixed;
|
||||||
|
right: 30px;
|
||||||
|
top: auto;
|
||||||
|
bottom: 50px;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden-right {
|
||||||
|
transform: translate(50px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden-left {
|
||||||
|
transform: translate(-50px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.showElement {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translate(0, 0);
|
||||||
|
-webkit-transition: all 0.5s ease-out;
|
||||||
|
-moz-transition: all 0.5s ease-out;
|
||||||
|
transition: all 0.5s ease-out;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
BIN
src/assets/img/ajax-loader.gif
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
src/assets/img/award/awards-1.jpg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
src/assets/img/award/awards-2.jpg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
src/assets/img/award/awards-3.jpg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
src/assets/img/award/awards-4.jpg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
src/assets/img/bg/bcg_slide-4.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-1.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/img/bg/bg-image-10.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-11.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-12.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/img/bg/bg-image-13.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-14.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-15.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-16.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-17.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-2.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-3.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/img/bg/bg-image-4.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-5.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-6.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-7.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/img/bg/bg-image-8.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/img/bg/bg-image-9.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
1
src/assets/img/chevron-left.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-left"><polyline points="15 18 9 12 15 6"></polyline></svg>
|
||||||
|
After Width: | Height: | Size: 270 B |
1
src/assets/img/chevron-right.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
||||||
|
After Width: | Height: | Size: 270 B |
BIN
src/assets/img/demos/2025-04/1.rar
Normal file
47
src/assets/img/demos/2025-04/4级用户sql.txt
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
SELECT
|
||||||
|
h.host_id,
|
||||||
|
h.host_name,
|
||||||
|
h.country,
|
||||||
|
h.hosts_source,
|
||||||
|
h.comment,
|
||||||
|
h.useable,
|
||||||
|
hi.info_type as hi_info_type,
|
||||||
|
hi.info_value as hi_info_value,
|
||||||
|
hi.part_month as hi_part_month
|
||||||
|
FROM (
|
||||||
|
SELECT DISTINCT
|
||||||
|
hos.host_id,
|
||||||
|
hs.host_name,
|
||||||
|
hs.country,
|
||||||
|
hs.hosts_source,
|
||||||
|
hos.comment,
|
||||||
|
hos.useable
|
||||||
|
FROM host_of_users hos
|
||||||
|
LEFT JOIN hosts hs ON hos.tenant_id = hs.tenant_id AND hos.host_id = hs.host_id
|
||||||
|
<if test="params.dataStart != null and params.dataEnd != null and params.dataType != null">
|
||||||
|
INNER JOIN hosts_info hi_filter ON hos.host_id = hi_filter.hosts_id
|
||||||
|
AND hi_filter.info_type = #{params.dataType}
|
||||||
|
AND CAST(hi_filter.info_value AS SIGNED) >= #{params.dataStart}
|
||||||
|
AND CAST(hi_filter.info_value AS SIGNED) <![CDATA[ <= ]]> #{params.dataEnd}
|
||||||
|
</if>
|
||||||
|
<where>
|
||||||
|
<if test="params.userId != null">
|
||||||
|
AND hos.owner_by = #{params.userId}
|
||||||
|
</if>
|
||||||
|
<if test="params.tenantId != null">
|
||||||
|
AND hos.tenant_id = #{params.tenantId}
|
||||||
|
</if>
|
||||||
|
<if test="params.region != null">
|
||||||
|
AND hs.country IN
|
||||||
|
(SELECT country_name FROM country_info WHERE country_group_name = #{params.region})
|
||||||
|
</if>
|
||||||
|
<if test="params.searchTime != null">
|
||||||
|
AND hs.update_dt = #{params.searchTime}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
LIMIT #{page.size} OFFSET #{page.current}
|
||||||
|
) h
|
||||||
|
INNER JOIN hosts_info hi ON h.host_id = hi.hosts_id
|
||||||
|
<if test="params.searchTime != null">
|
||||||
|
AND hi.part_month = #{params.searchTime}
|
||||||
|
</if>
|
||||||
710
src/assets/img/demos/2025-04/AppBar (2).vue
Normal file
@@ -0,0 +1,710 @@
|
|||||||
|
<template>
|
||||||
|
<div class="appBarContainer">
|
||||||
|
<Toast group="appBar" />
|
||||||
|
<Sidebar v-model:visible="visibleSidebar">
|
||||||
|
<Menu :model="itemsMenu" class="w-full">
|
||||||
|
<template #submenuheader="{ item }">
|
||||||
|
<span class="text-primary-500 dark:text-primary-400 font-bold leading-none">{{ item.label }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #item="{ item, props }">
|
||||||
|
<router-link :to="item.route" v-if="!item.children" v-slot="{ href }" custom>
|
||||||
|
<a v-ripple :href="href" v-bind="props.action" aria-hidden="false" @click="actionMenu(item.action)">
|
||||||
|
<span :class="item.icon" class="mr-2" />
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
</a>
|
||||||
|
</router-link>
|
||||||
|
<div v-else>
|
||||||
|
<a
|
||||||
|
v-ripple
|
||||||
|
v-styleclass="{
|
||||||
|
selector: '@next',
|
||||||
|
enterClass: 'hidden',
|
||||||
|
enterActiveClass: 'slidedown',
|
||||||
|
leaveToClass: 'hidden',
|
||||||
|
leaveActiveClass: 'slideup',
|
||||||
|
}"
|
||||||
|
class="flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors p-ripple"
|
||||||
|
>
|
||||||
|
<span :class="item.icon" class="mr-2" />
|
||||||
|
<span class="font-medium">{{ item.label }}</span>
|
||||||
|
<i class="pi pi-chevron-down ml-auto"></i>
|
||||||
|
</a>
|
||||||
|
<ul class="list-none py-0 pl-3 pr-0 m-0 hidden overflow-y-hidden transition-all transition-duration-400 transition-ease-in-out">
|
||||||
|
<li v-for="(child, index) in item.children" :key="index">
|
||||||
|
<router-link :to="child.route" v-slot="{ href }" custom>
|
||||||
|
<a
|
||||||
|
v-ripple
|
||||||
|
class="flex align-items-center cursor-pointer p-3 border-round text-700 hover:surface-100 transition-duration-150 transition-colors p-ripple"
|
||||||
|
:href="href"
|
||||||
|
v-bind="props.action"
|
||||||
|
aria-hidden="false"
|
||||||
|
@click="actionMenu(item.action)"
|
||||||
|
>
|
||||||
|
<span :class="child.icon" class="mr-2" />
|
||||||
|
<span class="font-medium">{{ child.label }}</span>
|
||||||
|
</a>
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Menu>
|
||||||
|
</Sidebar>
|
||||||
|
<Menubar class="appBar" :model="sinMenu">
|
||||||
|
<template #start>
|
||||||
|
<div class="flex gap-2 align-items-center">
|
||||||
|
<Button icon="pi pi-bars" text size="large" @click="visibleSidebar = true" />
|
||||||
|
<a href="/" style="text-decoration: none">
|
||||||
|
<span class="text-2xl font-bold logo">
|
||||||
|
<span>Nexus</span>
|
||||||
|
Live Pro
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #end>
|
||||||
|
<div class="flex flex-wrap justify-content-end align-items-center gap-2 info-perfil">
|
||||||
|
<CalendarioUsuario v-if="!store.isAdmin()" />
|
||||||
|
<Tag v-if="!store.isAdmin()" severity="info" rounded :value="`Créditos: ${creditos}`" />
|
||||||
|
<a style="cursor: pointer !important" @click="toggle" aria-haspopup="true" aria-controls="overlay_menu">
|
||||||
|
<Avatar
|
||||||
|
v-if="store.isAdmin() || store.getFoto().length == 0"
|
||||||
|
icon="pi pi-user"
|
||||||
|
class="mr-2"
|
||||||
|
shape="circle"
|
||||||
|
style="background-color: var(--primary-color); color: #2a1261"
|
||||||
|
/>
|
||||||
|
<Avatar v-else :image="store.getFoto()" class="mr-2" shape="circle" />
|
||||||
|
</a>
|
||||||
|
<Menu ref="menu" id="overlay_menu" :model="itemsUsuario" :popup="true" :focusedOptionId="null" :aria-activedescendant="false">
|
||||||
|
<template #start>
|
||||||
|
<button
|
||||||
|
v-ripple
|
||||||
|
class="relative overflow-hidden w-full p-link flex items-center p-2 pl-3 text-surface-700 dark:text-surface-0/80 hover:bg-surface-200 dark:hover:bg-surface-600 rounded-none"
|
||||||
|
>
|
||||||
|
<Avatar v-if="store.isAdmin() || store.getFoto().length == 0" icon="pi pi-user" class="mr-2" shape="circle" />
|
||||||
|
<Avatar v-else :image="store.getFoto()" class="mr-2" shape="circle" />
|
||||||
|
|
||||||
|
<span class="inline-flex flex-column justify-start">
|
||||||
|
<span class="font-bold">{{ usuarioLog.usuario }}</span>
|
||||||
|
<span class="text-sm">{{ usuarioLog.rol }}</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #item="{ item, props }">
|
||||||
|
<a v-ripple class="flex items-center" @click="actionMenu(item.action)" v-bind="props.action">
|
||||||
|
<span :class="item.icon" />
|
||||||
|
<span class="ml-2">{{ item.label }}</span>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Menubar>
|
||||||
|
<dialogMiPerfil :mostrarMiPerfil="mostrarPerfil" @dialogPerfilOculto="mostrarPerfil = false" />
|
||||||
|
<dialogEditarPerfil :mostrarEditar="mostrarEditar" @dialogEditarOculto="mostrarEditar = false" @perfilActualizado="getNewDatos" />
|
||||||
|
<Insignias v-if="store.isAdmin()" :mostrarInsigniasProp="mostrarInsignias" @dialogOculto="mostrarInsignias = false"></Insignias>
|
||||||
|
<Dialog
|
||||||
|
v-model:visible="addCreador"
|
||||||
|
maximizable
|
||||||
|
:header="store.isAdmin() ? 'Credenciales backstage' : 'Agregar creador'"
|
||||||
|
:style="{ width: store.isAdmin() ? '34rem' : '45rem' }"
|
||||||
|
:breakpoints="{ '1199px': '75vw', '575px': '90vw' }"
|
||||||
|
position="top"
|
||||||
|
:modal="true"
|
||||||
|
:draggable="false"
|
||||||
|
>
|
||||||
|
<div v-if="store.isAdmin()">
|
||||||
|
<form ref="formAdd">
|
||||||
|
<div class="flex flex-column gap-1 mb-2">
|
||||||
|
<label for="correo" class="font-bold block">Correo</label>
|
||||||
|
<InputText v-model="paquete.correo" type="email" placeholder="Correo" id="correo" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-column gap-1 mb-2">
|
||||||
|
<label for="contrasena" class="font-bold block">Contraseña</label>
|
||||||
|
<InputText v-model="paquete.contrasena" type="text" placeholder="Contraseña" id="contrasena" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<h2 class="m-0">Credenciales backstage</h2>
|
||||||
|
<div class="flex flex-column gap-1">
|
||||||
|
<label for="correo" class="font-bold block">Correo</label>
|
||||||
|
<InputText v-model="paquete.correo" disabled type="email" placeholder="Correo" id="correo" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-column gap-1">
|
||||||
|
<label for="contrasena" class="font-bold block">Contraseña</label>
|
||||||
|
<InputText v-model="paquete.contrasena" disabled type="text" placeholder="Contraseña" id="contrasena" />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 mb-3">
|
||||||
|
<h3 class="m-0">Guía</h3>
|
||||||
|
<video width="100%" autoplay="false" muted height="300px" controls>
|
||||||
|
<source
|
||||||
|
src="https://res.cloudinary.com/dq2sbqjgf/video/upload/v1711917204/tutoriales/byfp8ygyo7kdv1ueclwf.mp4"
|
||||||
|
type="video/mp4"
|
||||||
|
/>
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
<p>Inicia sesión con las credenciales y agrega al creador</p>
|
||||||
|
<iframe
|
||||||
|
title="TikTok Backstage"
|
||||||
|
height="800px"
|
||||||
|
width="100%"
|
||||||
|
src="https://live-backstage.tiktok.com/login/"
|
||||||
|
frameborder="0"
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<Button label="Cerrar" @click="addCreador = false" text severity="danger" />
|
||||||
|
<div class="flex gap-2" v-if="store.isAdmin()">
|
||||||
|
<Button :label="paquete.estado == 'Activado' ? 'Desactivar' : 'Activar'" severity="warning" @click="cambiarEstadoBackstage" />
|
||||||
|
<Button label="Agregar" @click="modificarCredenciales" severity="success" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from "axios";
|
||||||
|
import { useStoreEvento } from "../store";
|
||||||
|
import dialogMiPerfil from "./MiPerfil.vue";
|
||||||
|
import dialogEditarPerfil from "./EditarPerfil.vue";
|
||||||
|
import EventoEspecial from "./EventoEspecial.vue";
|
||||||
|
import Insignias from "./Insignias.vue";
|
||||||
|
import CalendarioUsuario from "./CalendarioUsuario.vue";
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
creditos: {
|
||||||
|
type: String,
|
||||||
|
default: "0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
dialogMiPerfil,
|
||||||
|
dialogEditarPerfil,
|
||||||
|
Insignias,
|
||||||
|
EventoEspecial,
|
||||||
|
CalendarioUsuario,
|
||||||
|
},
|
||||||
|
data: () => ({
|
||||||
|
API: import.meta.env.VITE_APP_API,
|
||||||
|
store: null,
|
||||||
|
sinMenu: [],
|
||||||
|
itemsMenu: [],
|
||||||
|
itemsUsuario: [],
|
||||||
|
mostrarInsignias: false,
|
||||||
|
mostrarPerfil: false,
|
||||||
|
mostrarEditar: false,
|
||||||
|
usuarioLog: {
|
||||||
|
usuario: null,
|
||||||
|
rol: null,
|
||||||
|
correo: null,
|
||||||
|
telefono: null,
|
||||||
|
},
|
||||||
|
visibleSidebar: false,
|
||||||
|
addCreador: false,
|
||||||
|
paquete: {
|
||||||
|
correo: null,
|
||||||
|
contrasena: null,
|
||||||
|
estado: "Desactivado",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
toggle(event) {
|
||||||
|
this.$refs.menu.toggle(event);
|
||||||
|
},
|
||||||
|
actionMenu(action) {
|
||||||
|
this.visibleSidebar = false;
|
||||||
|
if (action) {
|
||||||
|
action = action.toLowerCase();
|
||||||
|
}
|
||||||
|
switch (action) {
|
||||||
|
case "perfil":
|
||||||
|
this.mostrarPerfil = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "editar_perfil":
|
||||||
|
this.mostrarEditar = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "cerrar_sesión":
|
||||||
|
this.cerrarSesion();
|
||||||
|
break;
|
||||||
|
case "insignia_abrir":
|
||||||
|
this.mostrarInsignias = true;
|
||||||
|
break;
|
||||||
|
case "add_creador":
|
||||||
|
this.addCreador = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getDatosUsuario() {
|
||||||
|
await axios
|
||||||
|
.get(`${this.API}/usuario/${this.store.getId()}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
this.usuarioLog.usuario = response.data.usuario;
|
||||||
|
this.usuarioLog.rol = response.data.rol;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.$toast.add({group:"appBar", severity: "error", summary: "Datos del usuario", detail: "Ocurrió un problema inesperado!", life: 1600 });
|
||||||
|
console.log("Error: ", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async getNewDatos() {
|
||||||
|
await axios
|
||||||
|
.get(`${this.API}/usuario/${this.store.getId()}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
this.store.newDatos(response.data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async modificarCredenciales() {
|
||||||
|
if (this.paquete.correo != null && this.paquete.contrasena != null) {
|
||||||
|
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
if (isEmail.test(this.paquete.correo)) {
|
||||||
|
await axios
|
||||||
|
.post(`${this.API}/usuario/credencialesBackstage`, this.paquete, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((r) => {
|
||||||
|
if (r.data) {
|
||||||
|
this.addCreador = false;
|
||||||
|
}
|
||||||
|
this.$toast.add({group:"appBar",
|
||||||
|
severity: "success",
|
||||||
|
summary: "Credenciales backstage",
|
||||||
|
detail: r.data ? "Credenciales actualizadas correctamente" : "No se pudo actualizar las credenciales",
|
||||||
|
life: 1600,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.$toast.add({group:"appBar", severity: "error", summary: `Sucedió un problema`, detail: error.response.data.message, life: 1500 });
|
||||||
|
console.log("Error: ", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.$toast.add({group:"appBar" ,severity: "error", summary: "Credenciales", detail: "Ingresa un correo válido", life: 1600 });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$toast.add({group:"appBar", severity: "error", summary: "Credenciales", detail: "Debes llenar todos los campos", life: 1600 });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getBackstage() {
|
||||||
|
await axios
|
||||||
|
.get(`${this.API}/usuario/backstage`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
this.paquete = { ...response.data };
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.$toast.add({group:"appBar", severity: "error", summary: "Backstage", detail: "Sucedió un problema", life: 1600 });
|
||||||
|
console.log("Error: ", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async cambiarEstadoBackstage() {
|
||||||
|
this.paquete.estado = this.paquete.estado == "Activado" ? "Desactivado" : "Activado";
|
||||||
|
await axios
|
||||||
|
.put(
|
||||||
|
`${this.API}/usuario/estadoBackstage`,
|
||||||
|
{ estado: this.paquete.estado },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((r) => {
|
||||||
|
this.$toast.add({group:"appBar",
|
||||||
|
severity: "success",
|
||||||
|
summary: "Estado backstage",
|
||||||
|
detail: r.data ? "Estado cambiado correctamente" : "No se pudo cambiar el estado",
|
||||||
|
life: 1600,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.$toast.add({group:"appBar", severity: "error", summary: `Sucedió un problema`, detail: error.response.data.message, life: 1500 });
|
||||||
|
console.log("Error: ", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
cerrarSesion() {
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
this.store = useStoreEvento();
|
||||||
|
const admin = this.store.isAdmin();
|
||||||
|
await this.getBackstage();
|
||||||
|
if (admin) {
|
||||||
|
this.itemsMenu = [
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Creadores",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Gestionar Creador",
|
||||||
|
icon: "pi pi-users",
|
||||||
|
route: "/panel/creadores",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Configuración Bonus",
|
||||||
|
icon: "pi pi-money-bill",
|
||||||
|
route: "/panel/bonus",
|
||||||
|
},
|
||||||
|
{ label: "Tabla seleccionados", icon: "pi pi-table", route: "/panel/tablas" },
|
||||||
|
{
|
||||||
|
label: "Premios Aleatorios",
|
||||||
|
icon: "pi pi-wallet",
|
||||||
|
route: "/panel/aleatorios",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Gestionar Promoción",
|
||||||
|
icon: "pi pi-thumbs-up-fill",
|
||||||
|
route: "/panel/promocion",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Regalos",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/regalos",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Agregar creadores",
|
||||||
|
icon: "pi pi-user-plus",
|
||||||
|
action: "add_creador",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Eventos",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Gestionar Eventos",
|
||||||
|
icon: "pi pi-calendar-plus",
|
||||||
|
route: "/panel/evento",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Eventos Especiales",
|
||||||
|
icon: "pi pi-flag-fill",
|
||||||
|
route: "/panel/eventoEspecial",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Vista Previa",
|
||||||
|
icon: "pi pi-desktop",
|
||||||
|
route: "/evento",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Batallas",
|
||||||
|
icon: "pi pi-calendar-plus",
|
||||||
|
route: "/panel/batalla",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tienda",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Deseos",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/deseos",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Administración",
|
||||||
|
items: [
|
||||||
|
{ label: "Proveedores", icon: "pi pi-sitemap", route: "/panel/proveedores" },
|
||||||
|
{ label: "Reuniones", icon: "pi pi-calendar", route: "/panel/reuniones" },
|
||||||
|
{
|
||||||
|
label: "Insignias",
|
||||||
|
icon: "pi pi-star",
|
||||||
|
action: "insignia_abrir",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Entregar Premios",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/asignar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Control de reglas",
|
||||||
|
icon: "pi pi-sliders-h",
|
||||||
|
route: "/panel/reglas",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Mi perfil",
|
||||||
|
icon: "pi pi-user",
|
||||||
|
action: "perfil",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Editar perfil",
|
||||||
|
icon: "pi pi-user-edit",
|
||||||
|
action: "editar_perfil",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cerrar sesión",
|
||||||
|
icon: "pi pi-sign-out",
|
||||||
|
action: "cerrar_sesión",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.itemsUsuario = [
|
||||||
|
{
|
||||||
|
label: "Mi perfil",
|
||||||
|
icon: "pi pi-user",
|
||||||
|
action: "perfil",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Editar perfil",
|
||||||
|
icon: "pi pi-user-edit",
|
||||||
|
action: "editar_perfil",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cerrar sesión",
|
||||||
|
icon: "pi pi-sign-out",
|
||||||
|
action: "cerrar_sesión",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
//Verificamos el estado del backstage
|
||||||
|
this.itemsMenu = [
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Principal",
|
||||||
|
icon: "pi pi-user",
|
||||||
|
route: "/panel/bonus",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Promoción",
|
||||||
|
icon: "pi pi-thumbs-up-fill",
|
||||||
|
children: [
|
||||||
|
{ label: "Crear orden", icon: "pi pi-cart-plus", route: "/panel/ordenar" },
|
||||||
|
{ label: "Ordenes", icon: "pi pi-shopping-cart", route: "/panel/ordenes" },
|
||||||
|
{ label: "Servicios", icon: "pi pi-list", route: "/panel/servicios" },
|
||||||
|
{ label: "Agregar fondos", icon: "pi pi-money-bill", route: "/panel/agregarfondos" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Deseos",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/deseos",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Evento",
|
||||||
|
icon: "pi pi-calendar-plus",
|
||||||
|
route: "/evento",
|
||||||
|
},
|
||||||
|
/* {
|
||||||
|
label: "Eventos Especiales",
|
||||||
|
icon: "pi pi-flag-fill",
|
||||||
|
route: "/EventoEspecialView",
|
||||||
|
}, */
|
||||||
|
{
|
||||||
|
label: "Batallas",
|
||||||
|
icon: "pi pi-calendar-plus",
|
||||||
|
route: "/panel/batalla",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "DuckRacer",
|
||||||
|
icon: "pi pi-dollar",
|
||||||
|
route: "/duckracer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Administración",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Mi perfil",
|
||||||
|
icon: "pi pi-user",
|
||||||
|
route: "/panel/bonus",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Mis premios",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/premio",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Control de reglas",
|
||||||
|
icon: "pi pi-sliders-h",
|
||||||
|
route: "/actualizaciones-reglas",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Editar perfil",
|
||||||
|
icon: "pi pi-user-edit",
|
||||||
|
action: "editar_perfil",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cerrar sesión",
|
||||||
|
icon: "pi pi-sign-out",
|
||||||
|
action: "cerrar_sesión",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (this.paquete.estado == "Activado") {
|
||||||
|
this.itemsMenu.splice(2, 0, {
|
||||||
|
label: "Agregar creadores",
|
||||||
|
icon: "pi pi-user-plus",
|
||||||
|
action: "add_creador",
|
||||||
|
route: "#action",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.itemsUsuario = [
|
||||||
|
{
|
||||||
|
label: "Editar perfil",
|
||||||
|
icon: "pi pi-user-edit",
|
||||||
|
action: "editar_perfil",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cerrar sesión",
|
||||||
|
icon: "pi pi-sign-out",
|
||||||
|
action: "cerrar_sesión",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
this.getDatosUsuario();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.appBar {
|
||||||
|
background-color: #1f2937 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
/* padding: 0 200px; */
|
||||||
|
}
|
||||||
|
.info-perfil > span.p-tag {
|
||||||
|
width: auto !important;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.opciones {
|
||||||
|
padding: 0 50px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-sidebar-content > div,
|
||||||
|
.p-sidebar-content > .p-menu.p-component > .p-menu-end > .p-menu.p-component {
|
||||||
|
background: none !important;
|
||||||
|
border: 0 !important;
|
||||||
|
min-width: 100% !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-menu .p-submenu-header {
|
||||||
|
background: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-panel .p-panel-header {
|
||||||
|
border-top-left-radius: 0 !important;
|
||||||
|
border-top-right-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo > span {
|
||||||
|
color: #84dc16;
|
||||||
|
}
|
||||||
|
@media (max-width: 1012px) {
|
||||||
|
.opciones {
|
||||||
|
padding: 0 30px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width: 972px) {
|
||||||
|
.opciones {
|
||||||
|
padding: 0 20px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width: 909px) {
|
||||||
|
.opciones {
|
||||||
|
padding: 0 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
635
src/assets/img/demos/2025-04/AppBar.vue
Normal file
@@ -0,0 +1,635 @@
|
|||||||
|
<template>
|
||||||
|
<div class="appBarContainer">
|
||||||
|
<Toast />
|
||||||
|
<Sidebar v-model:visible="visibleSidebar">
|
||||||
|
<Menu :model="itemsMenu" class="w-full">
|
||||||
|
<template #submenuheader="{ item }">
|
||||||
|
<span class="text-primary-500 dark:text-primary-400 font-bold leading-none">{{ item.label }}</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #item="{ item, props }">
|
||||||
|
<router-link :to="item.route" v-slot="{ href }" custom>
|
||||||
|
<a v-ripple :href="href" aria-hidden="true" v-bind="props.action" @click="actionMenu(item.action)">
|
||||||
|
<span :class="item.icon" />
|
||||||
|
<span class="ml-2">{{ item.label }}</span>
|
||||||
|
</a>
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
</Menu>
|
||||||
|
</Sidebar>
|
||||||
|
<Menubar class="appBar" :model="sinMenu">
|
||||||
|
<template #start>
|
||||||
|
<div class="flex gap-2 align-items-center">
|
||||||
|
<Button icon="pi pi-bars" text size="large" @click="visibleSidebar = true" />
|
||||||
|
<a href="/" style="text-decoration: none">
|
||||||
|
<span class="text-2xl font-bold logo">
|
||||||
|
<span>Nexus</span>
|
||||||
|
Live Pro
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #end>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<a style="cursor: pointer !important" @click="toggle" aria-haspopup="true" aria-controls="overlay_menu">
|
||||||
|
<Avatar
|
||||||
|
v-if="store.isAdmin() || store.getFoto().length == 0"
|
||||||
|
icon="pi pi-user"
|
||||||
|
class="mr-2"
|
||||||
|
shape="circle"
|
||||||
|
style="background-color: var(--primary-color); color: #2a1261"
|
||||||
|
/>
|
||||||
|
<Avatar v-else :image="store.getFoto()" class="mr-2" shape="circle" />
|
||||||
|
</a>
|
||||||
|
<Menu ref="menu" id="overlay_menu" :model="itemsUsuario" :popup="true" :focusedOptionId="null" :aria-activedescendant="false">
|
||||||
|
<template #start>
|
||||||
|
<button
|
||||||
|
v-ripple
|
||||||
|
class="relative overflow-hidden w-full p-link flex items-center p-2 pl-3 text-surface-700 dark:text-surface-0/80 hover:bg-surface-200 dark:hover:bg-surface-600 rounded-none"
|
||||||
|
>
|
||||||
|
<Avatar v-if="store.isAdmin() || store.getFoto().length == 0" icon="pi pi-user" class="mr-2" shape="circle" />
|
||||||
|
<Avatar v-else :image="store.getFoto()" class="mr-2" shape="circle" />
|
||||||
|
|
||||||
|
<span class="inline-flex flex-column justify-start">
|
||||||
|
<span class="font-bold">{{ usuarioLog.usuario }}</span>
|
||||||
|
<span class="text-sm">{{ usuarioLog.rol }}</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #item="{ item, props }">
|
||||||
|
<a v-ripple class="flex items-center" @click="actionMenu(item.action)" v-bind="props.action">
|
||||||
|
<span :class="item.icon" />
|
||||||
|
<span class="ml-2">{{ item.label }}</span>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Menubar>
|
||||||
|
<dialogMiPerfil :mostrarMiPerfil="mostrarPerfil" @dialogPerfilOculto="mostrarPerfil = false" />
|
||||||
|
<dialogEditarPerfil :mostrarEditar="mostrarEditar" @dialogEditarOculto="mostrarEditar = false" @perfilActualizado="getNewDatos" />
|
||||||
|
<Insignias v-if="store.isAdmin()" :mostrarInsigniasProp="mostrarInsignias" @dialogOculto="mostrarInsignias = false"></Insignias>
|
||||||
|
<Dialog
|
||||||
|
v-model:visible="addCreador"
|
||||||
|
maximizable
|
||||||
|
:header="store.isAdmin() ? 'Credenciales backstage' : 'Agregar creador'"
|
||||||
|
:style="{ width: store.isAdmin() ? '34rem' : '45rem' }"
|
||||||
|
:breakpoints="{ '1199px': '75vw', '575px': '90vw' }"
|
||||||
|
position="top"
|
||||||
|
:modal="true"
|
||||||
|
:draggable="false"
|
||||||
|
>
|
||||||
|
<div v-if="store.isAdmin()">
|
||||||
|
<form ref="formAdd">
|
||||||
|
<div class="flex flex-column gap-1 mb-2">
|
||||||
|
<label for="correo" class="font-bold block">Correo</label>
|
||||||
|
<InputText v-model="paquete.correo" type="email" placeholder="Correo" id="correo" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-column gap-1 mb-2">
|
||||||
|
<label for="contrasena" class="font-bold block">Contraseña</label>
|
||||||
|
<InputText v-model="paquete.contrasena" type="text" placeholder="Contraseña" id="contrasena" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<h2 class="m-0">Credenciales backstage</h2>
|
||||||
|
<div class="flex flex-column gap-1">
|
||||||
|
<label for="correo" class="font-bold block">Correo</label>
|
||||||
|
<InputText v-model="paquete.correo" disabled type="email" placeholder="Correo" id="correo" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-column gap-1">
|
||||||
|
<label for="contrasena" class="font-bold block">Contraseña</label>
|
||||||
|
<InputText v-model="paquete.contrasena" disabled type="text" placeholder="Contraseña" id="contrasena" />
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 mb-3">
|
||||||
|
<h3 class="m-0">Guía</h3>
|
||||||
|
<video width="100%" autoplay="false" muted height="300px" controls>
|
||||||
|
<source
|
||||||
|
src="https://res.cloudinary.com/dq2sbqjgf/video/upload/v1711917204/tutoriales/byfp8ygyo7kdv1ueclwf.mp4"
|
||||||
|
type="video/mp4"
|
||||||
|
/>
|
||||||
|
</video>
|
||||||
|
</div>
|
||||||
|
<p>Inicia sesión con las credenciales y agrega al creador</p>
|
||||||
|
<iframe
|
||||||
|
title="TikTok Backstage"
|
||||||
|
height="800px"
|
||||||
|
width="100%"
|
||||||
|
src="https://live-backstage.tiktok.com/login/"
|
||||||
|
frameborder="0"
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<Button label="Cerrar" @click="addCreador = false" text severity="danger" />
|
||||||
|
<div class="flex gap-2" v-if="store.isAdmin()">
|
||||||
|
<Button :label="paquete.estado == 'Activado' ? 'Desactivar' : 'Activar'" severity="warning" @click="cambiarEstadoBackstage" />
|
||||||
|
<Button label="Agregar" @click="modificarCredenciales" severity="success" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from "axios";
|
||||||
|
import { useStoreEvento } from "../store";
|
||||||
|
import dialogMiPerfil from "./MiPerfil.vue";
|
||||||
|
import dialogEditarPerfil from "./EditarPerfil.vue";
|
||||||
|
import EventoEspecial from "./EventoEspecial.vue";
|
||||||
|
import Insignias from "./Insignias.vue";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
dialogMiPerfil,
|
||||||
|
dialogEditarPerfil,
|
||||||
|
Insignias,
|
||||||
|
EventoEspecial,
|
||||||
|
},
|
||||||
|
data: () => ({
|
||||||
|
API: import.meta.env.VITE_APP_API,
|
||||||
|
store: null,
|
||||||
|
sinMenu: [],
|
||||||
|
itemsMenu: [],
|
||||||
|
itemsUsuario: [],
|
||||||
|
mostrarInsignias: false,
|
||||||
|
mostrarPerfil: false,
|
||||||
|
mostrarEditar: false,
|
||||||
|
usuarioLog: {
|
||||||
|
usuario: null,
|
||||||
|
rol: null,
|
||||||
|
correo: null,
|
||||||
|
telefono: null,
|
||||||
|
},
|
||||||
|
visibleSidebar: false,
|
||||||
|
addCreador: false,
|
||||||
|
paquete: {
|
||||||
|
correo: null,
|
||||||
|
contrasena: null,
|
||||||
|
estado: "Desactivado",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
toggle(event) {
|
||||||
|
this.$refs.menu.toggle(event);
|
||||||
|
},
|
||||||
|
actionMenu(action) {
|
||||||
|
this.visibleSidebar = false;
|
||||||
|
if (action) {
|
||||||
|
action = action.toLowerCase();
|
||||||
|
}
|
||||||
|
switch (action) {
|
||||||
|
case "perfil":
|
||||||
|
this.mostrarPerfil = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "editar_perfil":
|
||||||
|
this.mostrarEditar = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "cerrar_sesión":
|
||||||
|
this.cerrarSesion();
|
||||||
|
break;
|
||||||
|
case "insignia_abrir":
|
||||||
|
this.mostrarInsignias = true;
|
||||||
|
break;
|
||||||
|
case "add_creador":
|
||||||
|
this.addCreador = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getDatosUsuario() {
|
||||||
|
await axios
|
||||||
|
.get(`${this.API}/usuario/${this.store.getId()}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
this.usuarioLog.usuario = response.data.usuario;
|
||||||
|
this.usuarioLog.rol = response.data.rol;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.$toast.add({ severity: "error", summary: "Datos del usuario", detail: "Ocurrió un problema inesperado!", life: 1600 });
|
||||||
|
console.log("Error: ", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async getNewDatos() {
|
||||||
|
await axios
|
||||||
|
.get(`${this.API}/usuario/${this.store.getId()}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
this.store.newDatos(response.data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async modificarCredenciales() {
|
||||||
|
if (this.paquete.correo != null && this.paquete.contrasena != null) {
|
||||||
|
const isEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
if (isEmail.test(this.paquete.correo)) {
|
||||||
|
await axios
|
||||||
|
.post(`${this.API}/usuario/credencialesBackstage`, this.paquete, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((r) => {
|
||||||
|
if (r.data) {
|
||||||
|
this.addCreador = false;
|
||||||
|
}
|
||||||
|
this.$toast.add({
|
||||||
|
severity: "success",
|
||||||
|
summary: "Credenciales backstage",
|
||||||
|
detail: r.data ? "Credenciales actualizadas correctamente" : "No se pudo actualizar las credenciales",
|
||||||
|
life: 1600,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.$toast.add({ severity: "error", summary: `Sucedió un problema`, detail: error.response.data.message, life: 1500 });
|
||||||
|
console.log("Error: ", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.$toast.add({ severity: "error", summary: "Credenciales", detail: "Ingresa un correo válido", life: 1600 });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$toast.add({ severity: "error", summary: "Credenciales", detail: "Debes llenar todos los campos", life: 1600 });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getBackstage() {
|
||||||
|
await axios
|
||||||
|
.get(`${this.API}/usuario/backstage`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.data) {
|
||||||
|
this.paquete = { ...response.data };
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.$toast.add({ severity: "error", summary: "Backstage", detail: "Sucedió un problema", life: 1600 });
|
||||||
|
console.log("Error: ", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async cambiarEstadoBackstage() {
|
||||||
|
this.paquete.estado = this.paquete.estado == "Activado" ? "Desactivado" : "Activado";
|
||||||
|
await axios
|
||||||
|
.put(
|
||||||
|
`${this.API}/usuario/estadoBackstage`,
|
||||||
|
{ estado: this.paquete.estado },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.store.getToken()}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((r) => {
|
||||||
|
this.$toast.add({
|
||||||
|
severity: "success",
|
||||||
|
summary: "Estado backstage",
|
||||||
|
detail: r.data ? "Estado cambiado correctamente" : "No se pudo cambiar el estado",
|
||||||
|
life: 1600,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
switch (error.response.data.statusCode) {
|
||||||
|
case 401:
|
||||||
|
//Se le termino la sesión
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.$toast.add({ severity: "error", summary: `Sucedió un problema`, detail: error.response.data.message, life: 1500 });
|
||||||
|
console.log("Error: ", error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
cerrarSesion() {
|
||||||
|
this.store.clearUser();
|
||||||
|
this.$router.push("/login");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async created() {
|
||||||
|
this.store = useStoreEvento();
|
||||||
|
const admin = this.store.isAdmin();
|
||||||
|
await this.getBackstage();
|
||||||
|
if (admin) {
|
||||||
|
this.itemsMenu = [
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Creadores",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Gestionar Creador",
|
||||||
|
icon: "pi pi-users",
|
||||||
|
route: "/panel/creadores",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Configuración Bonus",
|
||||||
|
icon: "pi pi-money-bill",
|
||||||
|
route: "/panel/bonus",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Premios Aleatorios",
|
||||||
|
icon: "pi pi-wallet",
|
||||||
|
route: "/panel/aleatorios",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Gestionar Promoción",
|
||||||
|
icon: "pi pi-thumbs-up-fill",
|
||||||
|
route: "/panel/promocion",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Regalos",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/regalos",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Agregar creadores",
|
||||||
|
icon: "pi pi-user-plus",
|
||||||
|
action: "add_creador",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Eventos",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Gestionar Eventos",
|
||||||
|
icon: "pi pi-calendar-plus",
|
||||||
|
route: "/panel/evento",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Eventos Especiales",
|
||||||
|
icon: "pi pi-flag-fill",
|
||||||
|
route: "/panel/eventoEspecial",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Vista Previa",
|
||||||
|
icon: "pi pi-desktop",
|
||||||
|
route: "/evento",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Batallas",
|
||||||
|
icon: "pi pi-calendar-plus",
|
||||||
|
route: "/panel/batalla",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Tienda",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Deseos",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/deseos",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Administración",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Insignias",
|
||||||
|
icon: "pi pi-star",
|
||||||
|
action: "insignia_abrir",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Entregar Premios",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/asignar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Control de reglas",
|
||||||
|
icon: "pi pi-sliders-h",
|
||||||
|
route: "/panel/reglas",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Mi perfil",
|
||||||
|
icon: "pi pi-user",
|
||||||
|
action: "perfil",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Editar perfil",
|
||||||
|
icon: "pi pi-user-edit",
|
||||||
|
action: "editar_perfil",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cerrar sesión",
|
||||||
|
icon: "pi pi-sign-out",
|
||||||
|
action: "cerrar_sesión",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.itemsUsuario = [
|
||||||
|
{
|
||||||
|
label: "Mi perfil",
|
||||||
|
icon: "pi pi-user",
|
||||||
|
action: "perfil",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Editar perfil",
|
||||||
|
icon: "pi pi-user-edit",
|
||||||
|
action: "editar_perfil",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cerrar sesión",
|
||||||
|
icon: "pi pi-sign-out",
|
||||||
|
action: "cerrar_sesión",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
//Verificamos el estado del backstage
|
||||||
|
this.itemsMenu = [
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Principal",
|
||||||
|
icon: "pi pi-user",
|
||||||
|
route: "/panel/bonus",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Promoción",
|
||||||
|
icon: "pi pi-thumbs-up-fill",
|
||||||
|
route: "/panel/promouser",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Deseos",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/deseos",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Evento",
|
||||||
|
icon: "pi pi-calendar-plus",
|
||||||
|
route: "/evento",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Eventos Especiales",
|
||||||
|
icon: "pi pi-flag-fill",
|
||||||
|
route: "/EventoEspecialView",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Batallas",
|
||||||
|
icon: "pi pi-calendar-plus",
|
||||||
|
route: "/panel/batalla",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "DuckRacer",
|
||||||
|
icon: "pi pi-dollar",
|
||||||
|
route: "/duckracer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
separator: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Administración",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "Mi perfil",
|
||||||
|
icon: "pi pi-user",
|
||||||
|
route: "/panel/bonus",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Mis premios",
|
||||||
|
icon: "pi pi-gift",
|
||||||
|
route: "/panel/premio",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Control de reglas",
|
||||||
|
icon: "pi pi-sliders-h",
|
||||||
|
route: "/actualizaciones-reglas",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Editar perfil",
|
||||||
|
icon: "pi pi-user-edit",
|
||||||
|
action: "editar_perfil",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cerrar sesión",
|
||||||
|
icon: "pi pi-sign-out",
|
||||||
|
action: "cerrar_sesión",
|
||||||
|
route: "#action",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (this.paquete.estado == "Activado") {
|
||||||
|
this.itemsMenu.splice(2, 0, {
|
||||||
|
label: "Agregar creadores",
|
||||||
|
icon: "pi pi-user-plus",
|
||||||
|
action: "add_creador",
|
||||||
|
route: "#action",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.itemsUsuario = [
|
||||||
|
{
|
||||||
|
label: "Editar perfil",
|
||||||
|
icon: "pi pi-user-edit",
|
||||||
|
action: "editar_perfil",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cerrar sesión",
|
||||||
|
icon: "pi pi-sign-out",
|
||||||
|
action: "cerrar_sesión",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
this.getDatosUsuario();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.appBar {
|
||||||
|
background-color: #1f2937 !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-sidebar-content > div,
|
||||||
|
.p-sidebar-content > .p-menu.p-component > .p-menu-end > .p-menu.p-component {
|
||||||
|
background: none !important;
|
||||||
|
border: 0 !important;
|
||||||
|
min-width: 100% !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-menu .p-submenu-header {
|
||||||
|
background: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-panel .p-panel-header {
|
||||||
|
border-top-left-radius: 0 !important;
|
||||||
|
border-top-right-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 2em;
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo > span {
|
||||||
|
color: #84dc16;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
BIN
src/assets/img/demos/2025-04/Clash.for.Windows-0.20.39-win.zip
Normal file
248
src/assets/img/demos/2025-04/JsInteraction.py
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
import json
|
||||||
|
import threading
|
||||||
|
from PySide6.QtCore import QObject, Slot, QUrl
|
||||||
|
from PySide6.QtGui import QDesktopServices
|
||||||
|
|
||||||
|
from utils.countrycode import get_country_id_with_name
|
||||||
|
from utils.tiktokAPI import batch_check_anchor
|
||||||
|
from utils.tiktok_cookies import monitor_url_and_cookies
|
||||||
|
|
||||||
|
|
||||||
|
# 爬虫全局配置
|
||||||
|
class fetch_data_config:
|
||||||
|
cookies_dict = {}
|
||||||
|
|
||||||
|
# msToken
|
||||||
|
msToken = "mtzl_MJ-pnO3ChopXcF_2I5a6hgYgIxUr-anVWajHYB3eZzQad8E6JvthPC1TQ4h_T5hQC7_NEmlNpyPIRWuVFRu8vdCYCHGa3F6B8L-mx1vYz7p4fvdtiDACP5f8v__74P4-x1AfaZQhRE="
|
||||||
|
|
||||||
|
# ehaders
|
||||||
|
sid_guard = "4da643b0f71c914bc520343c2df39737%7C1744177601%7C15551757%7CMon%2C+06-Oct-2025+05%3A42%3A38+GMT"
|
||||||
|
|
||||||
|
# cookie
|
||||||
|
cookie = ""
|
||||||
|
|
||||||
|
# 当前国家
|
||||||
|
country = ""
|
||||||
|
|
||||||
|
# 国家code
|
||||||
|
regin = ""
|
||||||
|
|
||||||
|
# 用户id
|
||||||
|
ownerId = ""
|
||||||
|
|
||||||
|
# 租户id
|
||||||
|
tenantId = ""
|
||||||
|
|
||||||
|
# 脚本启动状态
|
||||||
|
isStart = False
|
||||||
|
|
||||||
|
# tk后台管理账号
|
||||||
|
tkBackStageAccounts = []
|
||||||
|
|
||||||
|
# 金币相关
|
||||||
|
class gold:
|
||||||
|
# 最大
|
||||||
|
max = 0
|
||||||
|
# 最小
|
||||||
|
min = 0
|
||||||
|
|
||||||
|
# 粉丝相关
|
||||||
|
class fans:
|
||||||
|
# 最大
|
||||||
|
max = 0
|
||||||
|
# 最小
|
||||||
|
min = 0
|
||||||
|
|
||||||
|
# 爬取速度相关
|
||||||
|
class frequency:
|
||||||
|
# 最大
|
||||||
|
day = 0
|
||||||
|
hour = 0
|
||||||
|
|
||||||
|
# js交互类
|
||||||
|
class Bridge(QObject):
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
# 传值给js 此为测试方法
|
||||||
|
@Slot(str,result=str)
|
||||||
|
def stringToJs(self, name):
|
||||||
|
print(name)
|
||||||
|
return name
|
||||||
|
|
||||||
|
# 获取js的传值 此为测试方法
|
||||||
|
@Slot(str)
|
||||||
|
def stringFromJs(self, str):
|
||||||
|
print(str)
|
||||||
|
|
||||||
|
# 直接调用 此为测试方法
|
||||||
|
@Slot()
|
||||||
|
def doSomething(self):
|
||||||
|
print("执行了一些代码")
|
||||||
|
|
||||||
|
# 爬虫配置的相关配置
|
||||||
|
@Slot(str, result=int)
|
||||||
|
def fetchDataConfig(self,data):
|
||||||
|
|
||||||
|
from infos.autohostinfo import checkAnchorObjs
|
||||||
|
|
||||||
|
dict = json.loads(data)
|
||||||
|
try:
|
||||||
|
fetch_data_config.country = dict["country"]
|
||||||
|
regin = get_country_id_with_name(dict["country"])
|
||||||
|
fetch_data_config.regin = regin
|
||||||
|
fetch_data_config.ownerId = dict["userId"]
|
||||||
|
fetch_data_config.tenantId = dict["tenantId"]
|
||||||
|
fetch_data_config.isStart = dict["isStart"]
|
||||||
|
fetch_data_config.gold.max = dict["gold"]["max"]
|
||||||
|
fetch_data_config.gold.min = dict["gold"]["min"]
|
||||||
|
fetch_data_config.fans.max = dict["fans"]["max"]
|
||||||
|
fetch_data_config.fans.min = dict["fans"]["min"]
|
||||||
|
fetch_data_config.frequency.day = dict["frequency"]["day"]
|
||||||
|
fetch_data_config.frequency.hour = dict["frequency"]["hour"]
|
||||||
|
|
||||||
|
print("数据解析成功")
|
||||||
|
|
||||||
|
if fetch_data_config.isStart:
|
||||||
|
print("开始执行脚本")
|
||||||
|
from infos.autohostinfo import Fetch_TK_data
|
||||||
|
fetch = Fetch_TK_data()
|
||||||
|
threading.Thread(target=fetch.loopRun).start()
|
||||||
|
else:
|
||||||
|
print("停止脚本")
|
||||||
|
pass
|
||||||
|
|
||||||
|
return 200
|
||||||
|
except:
|
||||||
|
print("数据解析失败")
|
||||||
|
#非200为异常
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# 提供给前端各种数量
|
||||||
|
@Slot(result=str)
|
||||||
|
def fetchDataCount(self):
|
||||||
|
from infos.autohostinfo import totalDataCount, validAnchorsCount, checkedDataCount, canInvitationCount
|
||||||
|
data = {
|
||||||
|
"totalCount": totalDataCount, # 总数量
|
||||||
|
"validAnchorsCount":validAnchorsCount, # 有效的主播数量
|
||||||
|
"checkedDataCount":checkedDataCount, # 已查询的数量
|
||||||
|
"canInvitationCount":canInvitationCount # 可邀请的数量
|
||||||
|
}
|
||||||
|
jsonStr = json.dumps(data)
|
||||||
|
return jsonStr
|
||||||
|
|
||||||
|
|
||||||
|
# 前端查询tk后台登录状态的方法
|
||||||
|
@Slot(result=str)
|
||||||
|
def backStageloginStatus(self ):
|
||||||
|
dic = {
|
||||||
|
"index":self.index,
|
||||||
|
"code":self.loginStatus
|
||||||
|
}
|
||||||
|
return json.dumps(dic)
|
||||||
|
|
||||||
|
# 创建公会页面对象
|
||||||
|
def createApi(self, obj):
|
||||||
|
from infos.autohostinfo import checkAnchorObjs
|
||||||
|
from infos.autohostinfo import Fetch_TK_data
|
||||||
|
|
||||||
|
try:
|
||||||
|
dic = json.loads(obj)
|
||||||
|
account = dic["account"]
|
||||||
|
password = dic["password"]
|
||||||
|
self.index = dic["index"] # 获取前端传递的索引值
|
||||||
|
self.loginStatus = 0
|
||||||
|
|
||||||
|
# 添加登录账号到管理端
|
||||||
|
fetch_data_config.tkBackStageAccounts.append(account)
|
||||||
|
|
||||||
|
def loginCallBack():
|
||||||
|
self.loginStatus = 1
|
||||||
|
|
||||||
|
print("准备创建查询对象")
|
||||||
|
api = batch_check_anchor(account, password , loginCallBack)
|
||||||
|
print("查询对象创建完成")
|
||||||
|
checkAnchorObjs.append(api)
|
||||||
|
print("把对象添加到数组")
|
||||||
|
|
||||||
|
print("checkAnchorObjs count = " , len(checkAnchorObjs))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error in createApi: {str(e)}")
|
||||||
|
|
||||||
|
# 打开后台
|
||||||
|
@Slot(str)
|
||||||
|
def loginBackStage(self, obj):
|
||||||
|
try:
|
||||||
|
# 创建并启动新线程
|
||||||
|
thread = threading.Thread(
|
||||||
|
target=self.createApi,
|
||||||
|
args=(obj,),
|
||||||
|
daemon=True # 设置为守护线程,主线程退出时会自动结束
|
||||||
|
)
|
||||||
|
thread.start()
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
|
# 前端查询tk后台登录状态的方法
|
||||||
|
@Slot(result=str)
|
||||||
|
def backStageloginStatusCopy(self ):
|
||||||
|
dic = {
|
||||||
|
"index":self.index,
|
||||||
|
"code":self.loginStatus
|
||||||
|
}
|
||||||
|
return json.dumps(dic)
|
||||||
|
|
||||||
|
def createApiCopy(self, obj):
|
||||||
|
from infos.autohostinfo import checkAnchorObjs
|
||||||
|
try:
|
||||||
|
dic = json.loads(obj)
|
||||||
|
account = dic["account"]
|
||||||
|
password = dic["password"]
|
||||||
|
self.index = dic["index"] # 获取前端传递的索引值
|
||||||
|
self.loginStatus = 0
|
||||||
|
|
||||||
|
# 添加登录账号到管理端
|
||||||
|
fetch_data_config.tkBackStageAccounts.append(account)
|
||||||
|
|
||||||
|
def loginCallBack():
|
||||||
|
self.loginStatus = 1
|
||||||
|
|
||||||
|
print("准备创建查询对象")
|
||||||
|
api = batch_check_anchor(account, password , loginCallBack)
|
||||||
|
print("查询对象创建完成")
|
||||||
|
checkAnchorObjs.append(api)
|
||||||
|
print("把对象添加到数组")
|
||||||
|
|
||||||
|
print("checkAnchorObjs count = " , len(checkAnchorObjs))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error in createApi: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Slot(str)
|
||||||
|
def loginBackStageCopy(self, obj):
|
||||||
|
try:
|
||||||
|
# 创建并启动新线程
|
||||||
|
thread = threading.Thread(
|
||||||
|
target=self.createApi,
|
||||||
|
args=(obj,),
|
||||||
|
daemon=True # 设置为守护线程,主线程退出时会自动结束
|
||||||
|
)
|
||||||
|
thread.start()
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
|
||||||
|
# 打开tiktok
|
||||||
|
@Slot()
|
||||||
|
def loginTikTok(self):
|
||||||
|
threading.Thread(target=monitor_url_and_cookies).start()
|
||||||
|
|
||||||
|
# js传递主播id给Python
|
||||||
|
@Slot(str)
|
||||||
|
def givePyAnchorId(self, anchorId):
|
||||||
|
print(anchorId)
|
||||||
|
url = QUrl(f"https://www.tiktok.com/@{anchorId}/live")
|
||||||
|
QDesktopServices.openUrl(url)
|
||||||
392
src/assets/img/demos/2025-04/autohostinfo.py
Normal file
@@ -0,0 +1,392 @@
|
|||||||
|
import mysql.connector
|
||||||
|
import datetime
|
||||||
|
import requests
|
||||||
|
import countrycode as cc
|
||||||
|
import tableaction as tt
|
||||||
|
|
||||||
|
'''
|
||||||
|
获取checkalive接口,验证正在直播的房间,目前用不着
|
||||||
|
'''
|
||||||
|
def fetch_tiktok_checkalive(mstoken):
|
||||||
|
headers = {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
|
||||||
|
'Cookie': f'tt_chain_token=TxibwRSi3KKe1tf6pISVVQ==; passport_csrf_token=4e893d911568da55730040fc1878559c; passport_csrf_token_default=4e893d911568da55730040fc1878559c; _ga=GA1.1.1942425062.1741594510; FPID=FPID2.2.XItvG4EXgMzYHHXywTiqoJBFZRNVPtwkDonum5HhWgs%3D.1741594510; FPAU=1.2.565309640.1741594511; _fbp=fb.1.1741594510841.2080490210; tiktok_webapp_lang=zh-Hans; passport_auth_status=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; passport_auth_status_ss=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; multi_sids=7480081853916922896%3A36084ce2b0f8b96b6bd6dea2b3b2c77a; cmpl_token=AgQQAPO7F-RO0rfweHcpop0p_a8Pj5Yav4owYNi60g; uid_tt=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; uid_tt_ss=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; sid_tt=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid_ss=36084ce2b0f8b96b6bd6dea2b3b2c77a; store-idc=alisg; store-country-code=FR; store-country-code-src=uid; tt-target-idc=alisg; tt-target-idc-sign=ErAK_1daK7gOjNVGp3XkXR9xzLSLfCco9CTBlhCR9C9zJPfvo6iX0NZw1W80EEuME3nR10Dm8UNo5LfL3hDFtLUKyWtW58OnsGXT-QauQpwM9_6kDO_IvlhTNZzyD5PSqXS2hlJ_3Tl8nji5rVw96JCPdSoOQjaXRT8ooCSMKK027uCwQ5-SJFZJgcgmWKLDIINnviE4cqehrzacIx02M13H_SSVNbX7-tJSCyJEqEuLOSYfOTFs_DZPX_P9gSWsjQcZBnyxFWPwdUzheKYa58EeikgtePwWYvP9H5M5kyYiBfxzekOlwy3zvuv2rEJXkaRPaPoXAzgz1bFjjacwGZKGocIBUH6DH58P6V0-IZcAZHkloyN8Q2igQCfry0uDeWPo8ds3HQnMf-xo5doOve-NBLl_jmVivEr1M9YRze-NuXdnuhImeOK3Az0evFhar6nUMBNKpQBIcSprpgHETZJ9Kyit9j8YvApFWq3fWeOLtMIkhIUXf1nEErH-cUNH; sid_guard=36084ce2b0f8b96b6bd6dea2b3b2c77a%7C1742471450%7C15551959%7CTue%2C+16-Sep-2025+11%3A50%3A09+GMT; sid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; ssid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; tt_csrf_token=g4gW1gFF-n8yPsVakDGDmrNHod_3BKquWkHI; ttwid=1%7Cchxl-ZAvAGfFU51SNT77wDZpLYJaLof20G7FKm8_DFo%7C1742537773%7C662969551ee538eab2dcdc43c3fe4040eb616fadb0643fdf214cd492020211bb; store-country-sign=MEIEDAsnjoHJTjFNneFmHAQgQR99HNzDAO_9D6SuCvfYF54a6DyVUejXuTNuzPiPad4EECxy0Xgv6zgOnvZRwbL1BOI; odin_tt=f6dd93d06620a488d2c682614b0220bd90ce162c6ed4519dd238268f2d093ba6681742fda279cbbc281003b9653189488b0835410c681b9dd606fc3bea583d1e7db3636194de935ad4fb5a4edb93bc7f; FPLC=0cwaDGpn9gDBc5kgScVenLiwA4ke7utdzOwoyYXd01vs%2BTmgjutMCQsNbb4Op9PIx91duASeDnByT92SJCBf7O9%2BcIrWqPtwAdF%2BnTeb9U9Qwtfe%2Fc5qsS4YtdCK3Q%3D%3D; csrfToken=UXnAHlaM-oJpqmZgGifEUaKBQt2qDZdEs5VE; csrf_session_id=6fae5912276f9c74c1655a3bdd905016; msToken={mstoken}; _ga_LWWPCY99PB=GS1.1.1742537780.39.1.1742538627.0.0.1606106523'
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
url = f'https://webcast.tiktok.com/webcast/room/check_alive/?aid=1988&app_language=zh-Hans&app_name=tiktok_web&browser_language=zh-CN&browser_name=Mozilla&browser_online=true&browser_platform=Win32&browser_version=5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F129.0.0.0%20Safari%2F537.36&channel=tiktok_web&cookie_enabled=true&data_collection_enabled=true&device_id=7480081766272042504&device_platform=web_pc&focus_state=false&from_page=user&history_len=8&is_fullscreen=false&is_page_visible=true&os=windows&priority_region=&referer=https%3A%2F%2Fwww.tiktok.com%2F®ion=JP&room_ids=7485246672541682450%2C7485247033091246855%2C7485244095834295048%2C7485241576454638357&root_referer=https%3A%2F%2Fwww.tiktok.com%2F&screen_height=1080&screen_width=1920&tz_name=Asia%2FShanghai&user_is_login=true&webcast_language=zh-Hans&msToken={mstoken}&X-Bogus=DFSzswVuvOxANcScthfHPYG0V1L1&_signature=_02B4Z6wo00001TB-YIwAAIDAfzpHmnTd6QEwfmQAACwC03'
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
response.raise_for_status() # 如果请求失败,会抛出HTTPError异常
|
||||||
|
# 解析JSON响应
|
||||||
|
data = response.json()
|
||||||
|
return data
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"请求失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
获取audience_room_enter_backup接口,用于查找主播的金币(当日当场在线的人数)
|
||||||
|
'''
|
||||||
|
def fetch_tiktok_audience_room_enter_backup(mstoken,roomid):
|
||||||
|
headers = {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
|
||||||
|
'Cookie': f'tt_chain_token=TxibwRSi3KKe1tf6pISVVQ==; passport_csrf_token=4e893d911568da55730040fc1878559c; passport_csrf_token_default=4e893d911568da55730040fc1878559c; _ga=GA1.1.1942425062.1741594510; FPID=FPID2.2.XItvG4EXgMzYHHXywTiqoJBFZRNVPtwkDonum5HhWgs%3D.1741594510; FPAU=1.2.565309640.1741594511; _fbp=fb.1.1741594510841.2080490210; tiktok_webapp_lang=zh-Hans; passport_auth_status=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; passport_auth_status_ss=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; multi_sids=7480081853916922896%3A36084ce2b0f8b96b6bd6dea2b3b2c77a; cmpl_token=AgQQAPO7F-RO0rfweHcpop0p_a8Pj5Yav4owYNi60g; uid_tt=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; uid_tt_ss=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; sid_tt=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid_ss=36084ce2b0f8b96b6bd6dea2b3b2c77a; store-idc=alisg; store-country-code=FR; store-country-code-src=uid; tt-target-idc=alisg; tt-target-idc-sign=ErAK_1daK7gOjNVGp3XkXR9xzLSLfCco9CTBlhCR9C9zJPfvo6iX0NZw1W80EEuME3nR10Dm8UNo5LfL3hDFtLUKyWtW58OnsGXT-QauQpwM9_6kDO_IvlhTNZzyD5PSqXS2hlJ_3Tl8nji5rVw96JCPdSoOQjaXRT8ooCSMKK027uCwQ5-SJFZJgcgmWKLDIINnviE4cqehrzacIx02M13H_SSVNbX7-tJSCyJEqEuLOSYfOTFs_DZPX_P9gSWsjQcZBnyxFWPwdUzheKYa58EeikgtePwWYvP9H5M5kyYiBfxzekOlwy3zvuv2rEJXkaRPaPoXAzgz1bFjjacwGZKGocIBUH6DH58P6V0-IZcAZHkloyN8Q2igQCfry0uDeWPo8ds3HQnMf-xo5doOve-NBLl_jmVivEr1M9YRze-NuXdnuhImeOK3Az0evFhar6nUMBNKpQBIcSprpgHETZJ9Kyit9j8YvApFWq3fWeOLtMIkhIUXf1nEErH-cUNH; sid_guard=36084ce2b0f8b96b6bd6dea2b3b2c77a%7C1742471450%7C15551959%7CTue%2C+16-Sep-2025+11%3A50%3A09+GMT; sid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; ssid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; tt_csrf_token=g4gW1gFF-n8yPsVakDGDmrNHod_3BKquWkHI; ttwid=1%7Cchxl-ZAvAGfFU51SNT77wDZpLYJaLof20G7FKm8_DFo%7C1742537773%7C662969551ee538eab2dcdc43c3fe4040eb616fadb0643fdf214cd492020211bb; store-country-sign=MEIEDAsnjoHJTjFNneFmHAQgQR99HNzDAO_9D6SuCvfYF54a6DyVUejXuTNuzPiPad4EECxy0Xgv6zgOnvZRwbL1BOI; odin_tt=f6dd93d06620a488d2c682614b0220bd90ce162c6ed4519dd238268f2d093ba6681742fda279cbbc281003b9653189488b0835410c681b9dd606fc3bea583d1e7db3636194de935ad4fb5a4edb93bc7f; FPLC=0cwaDGpn9gDBc5kgScVenLiwA4ke7utdzOwoyYXd01vs%2BTmgjutMCQsNbb4Op9PIx91duASeDnByT92SJCBf7O9%2BcIrWqPtwAdF%2BnTeb9U9Qwtfe%2Fc5qsS4YtdCK3Q%3D%3D; csrfToken=UXnAHlaM-oJpqmZgGifEUaKBQt2qDZdEs5VE; csrf_session_id=6fae5912276f9c74c1655a3bdd905016; msToken={mstoken}; _ga_LWWPCY99PB=GS1.1.1742537780.39.1.1742538627.0.0.1606106523'
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
url = f'https://webcast.tiktok.com/webcast/linkmic_multi_guest/webapp/audience_room_enter_backup/?aid=1988&app_id=1988&app_language=zh-Hans&app_name=tiktok_web&browser_language=zh-CN&browser_name=Mozilla&browser_online=true&browser_platform=Win32&browser_version=5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F129.0.0.0%20Safari%2F537.36&channel=tiktok_web&cookie_enabled=true&data_collection_enabled=true&device_id=7480081766272042504&device_platform=web_pc&focus_state=true&from_page=user&history_len=45&is_fullscreen=false&is_page_visible=true&live_id=12&os=windows&priority_region=&referer=https%3A%2F%2Fwww.tiktok.com%2Fsearch%2Fuser%3FblankpageEnterFrom%3Dlive_detail%26blankpageEnterMethod%3Denter%26enterMethod%3Dclick_icon%26q%3Dshouhu2024%26searchSource%3Dsearch_history%26t%3D1742909035069%26videoPageType%3D®ion=SG&room_id={roomid}&root_referer=https%3A%2F%2Fwww.tiktok.com%2F&screen_height=1080&screen_width=1920&tz_name=Asia%2FShanghai&user_is_login=true&verifyFp=verify_m8o9s5gf_yVPbZr0N_PSYe_4qbO_BiFg_AlqcZCJbDhXc&webcast_language=zh-Hans&msToken={mstoken}&_signature=_02B4Z6wo00001lRJTtgAAIDDGw1pztgsPqZUSUpAAPMAc3'
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
response.raise_for_status() # 如果请求失败,会抛出HTTPError异常
|
||||||
|
# 解析JSON响应
|
||||||
|
data = response.json()
|
||||||
|
return data
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"请求失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
'''
|
||||||
|
获取https://webcast16-normal-c-useast1a.tiktokv.com/webcast/ranklist/list/v2接口,用于查找主播的金币(手机端榜单接口)
|
||||||
|
'''
|
||||||
|
def fetch_tiktok_ranklist_list_v2(mstoken,roomid,anchor_id,gapstyle):
|
||||||
|
#gapstyle代表昨日或今日,0代表今日,-1代表昨日
|
||||||
|
#cokkie中的session需要修改
|
||||||
|
headers = {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
|
||||||
|
#'Cookie': f'store-idc=maliva; passport_csrf_token=9f1c3313673d0cffd87316094dbffc7c; passport_csrf_token_default=9f1c3313673d0cffd87316094dbffc7c; multi_sids=7486734628213965840%3A976a1e25225285cf360b44e5fde377c6; cmpl_token=AgQQAPOHF-RPsLfY193SfZ0p-yMtHnfPP4fZYNjGCA; d_ticket=f1c8feea880f8bddd1258fc98100606241a3c; sid_guard=976a1e25225285cf360b44e5fde377c6%7C1743405899%7C15552000%7CSat%2C+27-Sep-2025+07%3A24%3A59+GMT; uid_tt=fb68d9a7e8ea0cece1b7958c8d2da425c2256f153c0b6f7ff56cacde89a20b2e; uid_tt_ss=fb68d9a7e8ea0cece1b7958c8d2da425c2256f153c0b6f7ff56cacde89a20b2e; sid_tt=976a1e25225285cf360b44e5fde377c6; sessionid=73c9e1dd1af6bed1d6e6ba49b50aad0f; sessionid_ss=73c9e1dd1af6bed1d6e6ba49b50aad0f; store-country-code=tw; store-country-code-src=uid; tt-target-idc=alisg; install_id=7487871815659669256; ttreq=1$53c460ab556f59872a6917b9efc4b4dc0ffac9cc; odin_tt=6b7c3d7ec51030c806c5337dadeb3685319ad24874dc5871ebd07'
|
||||||
|
|
||||||
|
'Cookie': f'install_id=7487870756572186410; ttreq=1$2afa63cd4b0ff1161e179c28084d891d64dbb6d9; store-idc=useast5; store-country-code=us; store-country-code-src=uid; tt-target-idc=useast8; uid_tt=732c3940cf2659167f84e71ffdb5616914b710b0b37ffd080e9b0b7b5248e215; uid_tt_ss=732c3940cf2659167f84e71ffdb5616914b710b0b37ffd080e9b0b7b5248e215; sid_guard=b5b341deed5cd4c5174f9203a94dbb89%7C1743601129%7C15378367%7CSat%2C+27-Sep-2025+13%3A24%3A56+GMT; sid_tt=b5b341deed5cd4c5174f9203a94dbb89; sessionid=b5b341deed5cd4c5174f9203a94dbb89; sessionid_ss=b5b341deed5cd4c5174f9203a94dbb89; passport_csrf_token=003f54014b009e057755ae7d4102704a; passport_csrf_token_default=003f54014b009e057755ae7d4102704a; store-country-sign=MEIEDGiF6NUvpjtZij7DxwQgmVgJbARKDUZuipnE77PfyGu02WoyElZtyrloDuD343AEEPieJ8HazV_DRIBjcFzdHr0; odin_tt=ff5a7b80d4a9eef1cc71d5e7430093fe7bf41c03fa008266649e3da7a6fe7ea4c95aa88240daa64ba49e51708f4b921677ee1d42c4d998bec20193aa5ecd8a119784b2b18e3529bde2cb1dc07f6d76d6; msToken=c4Lt_RIFfxVBf5e-ahm9CaI1cOxzgBS9drafpwA6g0UtdLlixh956HRJS8n48LgM_NXzEAhxsvjs7_vR3dDHSoqSgMU7zy3ii-18UDp9gyoDHdBOrWwcXhBtH8k5'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
url = f'https://webcast16-normal-useast8.tiktokv.us/webcast/ranklist/list/v2/?anchor_id={anchor_id}&room_id={roomid}&rank_type=8®ion_type=1&gap_interval={gapstyle}&use_simple_user=true&league_phase=0&device_platform=android&os=android&ssmix=a&_rticket=1743411002698&channel=huaweiadsglobal_int&aid=1233&app_name=musical_ly&version_code=390303&version_name=39.3.3&manifest_version_code=2023903030&update_version_code=2023903030&ab_version=39.3.3&resolution=720*1280&dpi=240&device_type=G011A&device_brand=google&language=zh-Hans&os_api=28&os_version=9&ac=wifi&is_pad=0¤t_region=US&app_type=normal&sys_region=CN&last_install_time=1743405779&mcc_mnc=31031&timezone_name=America%2FLos_Angeles&residence=US&app_language=zh-Hans&carrier_region=US&timezone_offset=-28800&host_abi=armeabi-v7a&locale=zh-Hans&ac2=wifi&uoo=0&op_region=US&build_number=39.3.3®ion=CN&ts=1743411004&iid=7487871815659669256&device_id=7008362079137564165&webcast_sdk_version=3840&webcast_language=zh-Hans&webcast_locale=zh_CN&effect_sdk_version=18.6.0¤t_network_quality_info=%7B%7D'
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
response.raise_for_status() # 如果请求失败,会抛出HTTPError异常
|
||||||
|
# 解析JSON响应
|
||||||
|
data = response.json()
|
||||||
|
return data
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"请求失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
获取feed接口,拿到多个房间号
|
||||||
|
'''
|
||||||
|
def fetch_tiktok_feed(mstoken,region):
|
||||||
|
mstoken = 'mtzl_MJ-pnO3ChopXcF_2I5a6hgYgIxUr-anVWajHYB3eZzQad8E6JvthPC1TQ4h_T5hQC7_NEmlNpyPIRWuVFRu8vdCYCHGa3F6B8L-mx1vYz7p4fvdtiDACP5f8v__74P4-x1AfaZQhRE='
|
||||||
|
headers = {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
|
||||||
|
'Cookie': f'tt_chain_token=TxibwRSi3KKe1tf6pISVVQ==; passport_csrf_token=4e893d911568da55730040fc1878559c; passport_csrf_token_default=4e893d911568da55730040fc1878559c; _ga=GA1.1.1942425062.1741594510; FPID=FPID2.2.XItvG4EXgMzYHHXywTiqoJBFZRNVPtwkDonum5HhWgs%3D.1741594510; FPAU=1.2.565309640.1741594511; _fbp=fb.1.1741594510841.2080490210; tiktok_webapp_lang=zh-Hans; passport_auth_status=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; passport_auth_status_ss=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; multi_sids=7480081853916922896%3A36084ce2b0f8b96b6bd6dea2b3b2c77a; cmpl_token=AgQQAPO7F-RO0rfweHcpop0p_a8Pj5Yav4owYNi60g; uid_tt=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; uid_tt_ss=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; sid_tt=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid_ss=36084ce2b0f8b96b6bd6dea2b3b2c77a; store-idc=alisg; store-country-code=FR; store-country-code-src=uid; tt-target-idc=alisg; tt-target-idc-sign=ErAK_1daK7gOjNVGp3XkXR9xzLSLfCco9CTBlhCR9C9zJPfvo6iX0NZw1W80EEuME3nR10Dm8UNo5LfL3hDFtLUKyWtW58OnsGXT-QauQpwM9_6kDO_IvlhTNZzyD5PSqXS2hlJ_3Tl8nji5rVw96JCPdSoOQjaXRT8ooCSMKK027uCwQ5-SJFZJgcgmWKLDIINnviE4cqehrzacIx02M13H_SSVNbX7-tJSCyJEqEuLOSYfOTFs_DZPX_P9gSWsjQcZBnyxFWPwdUzheKYa58EeikgtePwWYvP9H5M5kyYiBfxzekOlwy3zvuv2rEJXkaRPaPoXAzgz1bFjjacwGZKGocIBUH6DH58P6V0-IZcAZHkloyN8Q2igQCfry0uDeWPo8ds3HQnMf-xo5doOve-NBLl_jmVivEr1M9YRze-NuXdnuhImeOK3Az0evFhar6nUMBNKpQBIcSprpgHETZJ9Kyit9j8YvApFWq3fWeOLtMIkhIUXf1nEErH-cUNH; sid_guard=36084ce2b0f8b96b6bd6dea2b3b2c77a%7C1742471450%7C15551959%7CTue%2C+16-Sep-2025+11%3A50%3A09+GMT; sid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; ssid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; tt_csrf_token=g4gW1gFF-n8yPsVakDGDmrNHod_3BKquWkHI; ttwid=1%7Cchxl-ZAvAGfFU51SNT77wDZpLYJaLof20G7FKm8_DFo%7C1742537773%7C662969551ee538eab2dcdc43c3fe4040eb616fadb0643fdf214cd492020211bb; store-country-sign=MEIEDAsnjoHJTjFNneFmHAQgQR99HNzDAO_9D6SuCvfYF54a6DyVUejXuTNuzPiPad4EECxy0Xgv6zgOnvZRwbL1BOI; odin_tt=f6dd93d06620a488d2c682614b0220bd90ce162c6ed4519dd238268f2d093ba6681742fda279cbbc281003b9653189488b0835410c681b9dd606fc3bea583d1e7db3636194de935ad4fb5a4edb93bc7f; FPLC=0cwaDGpn9gDBc5kgScVenLiwA4ke7utdzOwoyYXd01vs%2BTmgjutMCQsNbb4Op9PIx91duASeDnByT92SJCBf7O9%2BcIrWqPtwAdF%2BnTeb9U9Qwtfe%2Fc5qsS4YtdCK3Q%3D%3D; csrfToken=UXnAHlaM-oJpqmZgGifEUaKBQt2qDZdEs5VE; csrf_session_id=6fae5912276f9c74c1655a3bdd905016; msToken={mstoken}; _ga_LWWPCY99PB=GS1.1.1742537780.39.1.1742538627.0.0.1606106523'
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
#req_from的属性需要重新设置为:webapp_taxonomy_drawer_enter_feed
|
||||||
|
url = f'https://webcast.tiktok.com/webcast/feed/?aid=1988&app_language=zh-Hans&app_name=tiktok_web&browser_language=zh-CN&browser_name=Mozilla&browser_online=true&browser_platform=Win32&browser_version=5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F129.0.0.0%20Safari%2F537.36&channel=tiktok_web&channel_id=1222001&cookie_enabled=true&data_collection_enabled=true&device_id=7480081766272042504&device_platform=web_pc&device_type=web_h265&focus_state=true&from_page=live&history_len=40&is_fullscreen=false&is_non_personalized=0&is_page_visible=true&os=windows&priority_region=&referer=https%3A%2F%2Fwww.tiktok.com%2F%40chuanyuwang20®ion=PH&related_live_tag=chatting&req_from=pc_web_recommend_room&root_referer=https%3A%2F%2Fwww.tiktok.com%2F%40chuanyuwang20&screen_height=1080&screen_width=1920&tz_name=Asia%2FShanghai&user_is_login=true&webcast_language=zh-Hans&msToken={mstoken}&_signature=_02B4Z6wo000019C5TqAAAIDCn.1ptJ30HF.QuUoAAJP85b'
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
response.raise_for_status() # 如果请求失败,会抛出HTTPError异常
|
||||||
|
# 解析JSON响应
|
||||||
|
data = response.json()
|
||||||
|
return data
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"请求失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
获取主播的礼物、榜单等信息
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
# 访问list接口
|
||||||
|
def fetch_tiktok_list(mstoken, roomid,region):
|
||||||
|
headers = {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
|
||||||
|
'Cookie': f'tt_chain_token=TxibwRSi3KKe1tf6pISVVQ==; passport_csrf_token=4e893d911568da55730040fc1878559c; passport_csrf_token_default=4e893d911568da55730040fc1878559c; _ga=GA1.1.1942425062.1741594510; FPID=FPID2.2.XItvG4EXgMzYHHXywTiqoJBFZRNVPtwkDonum5HhWgs%3D.1741594510; FPAU=1.2.565309640.1741594511; _fbp=fb.1.1741594510841.2080490210; tiktok_webapp_lang=zh-Hans; FPLC=unxTy%2BHNrlbV12WKer2Z4p%2BFMLTNffNmPfgFFyE1p9Yp%2F9UV00Mw%2Ft0yEjuVuELtDYxncw%2F6fTuwOoJBWhPgNaHGUHaO7SOvAgQWikUz0VM9W8idI3Y%2Fj2QbcvT7gQ%3D%3D; passport_auth_status=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; passport_auth_status_ss=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; multi_sids=7480081853916922896%3A36084ce2b0f8b96b6bd6dea2b3b2c77a; cmpl_token=AgQQAPO7F-RO0rfweHcpop0p_a8Pj5Yav4owYNi60g; uid_tt=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; uid_tt_ss=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; sid_tt=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid_ss=36084ce2b0f8b96b6bd6dea2b3b2c77a; store-idc=alisg; store-country-code=FR; store-country-code-src=uid; tt-target-idc=alisg; tt-target-idc-sign=ErAK_1daK7gOjNVGp3XkXR9xzLSLfCco9CTBlhCR9C9zJPfvo6iX0NZw1W80EEuME3nR10Dm8UNo5LfL3hDFtLUKyWtW58OnsGXT-QauQpwM9_6kDO_IvlhTNZzyD5PSqXS2hlJ_3Tl8nji5rVw96JCPdSoOQjaXRT8ooCSMKK027uCwQ5-SJFZJgcgmWKLDIINnviE4cqehrzacIx02M13H_SSVNbX7-tJSCyJEqEuLOSYfOTFs_DZPX_P9gSWsjQcZBnyxFWPwdUzheKYa58EeikgtePwWYvP9H5M5kyYiBfxzekOlwy3zvuv2rEJXkaRPaPoXAzgz1bFjjacwGZKGocIBUH6DH58P6V0-IZcAZHkloyN8Q2igQCfry0uDeWPo8ds3HQnMf-xo5doOve-NBLl_jmVivEr1M9YRze-NuXdnuhImeOK3Az0evFhar6nUMBNKpQBIcSprpgHETZJ9Kyit9j8YvApFWq3fWeOLtMIkhIUXf1nEErH-cUNH; sid_guard=36084ce2b0f8b96b6bd6dea2b3b2c77a%7C1742471450%7C15551959%7CTue%2C+16-Sep-2025+11%3A50%3A09+GMT; sid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; ssid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; tt_csrf_token=ZZvquAov-Asrhyv5oLnE4hVh26-TeCgL892E; ttwid=1%7Cchxl-ZAvAGfFU51SNT77wDZpLYJaLof20G7FKm8_DFo%7C1742472556%7Cacad91b38df171e37fa8b2032ee565f8f914e106077cd09bed5aef06edde7b56; store-country-sign=MEIEDOrgSZcKDYtd2mW_6gQgI6MIN_5J-Gh3ZUXIvVE5P87RnDlWDCqBb4cDzPmde5YEEM9aENKPObrvdh6fQ2M4v1w; csrf_session_id=6fae5912276f9c74c1655a3bdd905016; odin_tt=37ea501de00ce0d41f3d9a672f883e3995deae585ed2ced9a0333e872578d6c3142cc5b3030ad88f8594a07cc2a0987f85dd19ed9c9270ddf442b85d67b2c1d7259c98b829d7dfe4977ccc1e90652b9a; csrfToken=XkGOy09r-k51hDZ99RTHEnjAkxWtivpKt380; _ga_LWWPCY99PB=GS1.1.1742470182.37.1.1742472563.0.0.415184211; msToken={mstoken}'
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
url = f'https://webcast.tiktok.com/webcast/gift/list/?aid=1988&app_language=zh-Hans&app_name=tiktok_web&browser_language=zh-CN&browser_name=Mozilla&browser_online=true&browser_platform=Win32&browser_version=5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F129.0.0.0%20Safari%2F537.36&channel=tiktok_web&cookie_enabled=true&data_collection_enabled=true&device_id=7480081766272042504&device_platform=web_pc&focus_state=true&from_page=user&history_len=2&is_fullscreen=false&is_page_visible=true&os=windows&priority_region=&referer=https%3A%2F%2Fwww.tiktok.com%2Fsearch%3Fq%3Dricca1204%26t%3D1742472555302®ion={region}&room_id={roomid}&root_referer=https%3A%2F%2Fwww.tiktok.com%2Fsearch%3Fq%3Dricca1204%26t%3D1742472555302&screen_height=1080&screen_width=1920&tz_name=Asia%2FShanghai&user_is_login=true&webcast_language=zh-Hans&msToken={mstoken}&_signature=_02B4Z6wo00001mnonGwAAIDDJqy7eSCf.YZp6JjAAP21bf'
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
response.raise_for_status() # 如果请求失败,会抛出HTTPError异常
|
||||||
|
# 解析JSON响应
|
||||||
|
data = response.json()
|
||||||
|
return data
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"请求失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 访问enter接口,暂时弃用,爬多了会被封号
|
||||||
|
# def fetch_tiktok_enter(mstoken, roomid):
|
||||||
|
# url = f'https://webcast.tiktok.com/webcast/room/enter/?aid=1988&app_language=zh-Hans&app_name=tiktok_web&browser_language=zh-CN&browser_name=Mozilla&browser_online=true&browser_platform=Win32&browser_version=5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F129.0.0.0%20Safari%2F537.36&channel=tiktok_web&cookie_enabled=true&data_collection_enabled=true&device_id=7480081766272042504&device_platform=web_pc&device_type=web_h265&focus_state=true&from_page=user&history_len=24&is_fullscreen=false&is_page_visible=true&os=windows&priority_region=&referer=https%3A%2F%2Fwww.tiktok.com%2F®ion=PH&root_referer=https%3A%2F%2Fwww.tiktok.com%2F&screen_height=1080&screen_width=1920&tz_name=Asia%2FShanghai&user_is_login=true&verifyFp=verify_m8ijel2v_9YnZMchp_swhm_4bs1_9GXv_G1EbQ1f3NTh4&webcast_language=zh-Hans&msToken={mstoken}&_signature=_02B4Z6wo00001ABqsfgAAIDBTy6W7FBLWBwAarVAAGfOb8'
|
||||||
|
#
|
||||||
|
# headers = {
|
||||||
|
# # 留下
|
||||||
|
# "cookie": f'tt_chain_token=TxibwRSi3KKe1tf6pISVVQ==; passport_csrf_token=4e893d911568da55730040fc1878559c; passport_csrf_token_default=4e893d911568da55730040fc1878559c; _ga=GA1.1.1942425062.1741594510; FPID=FPID2.2.XItvG4EXgMzYHHXywTiqoJBFZRNVPtwkDonum5HhWgs%3D.1741594510; FPAU=1.2.565309640.1741594511; _fbp=fb.1.1741594510841.2080490210; tiktok_webapp_lang=zh-Hans; passport_auth_status=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; passport_auth_status_ss=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; tt_csrf_token=g4gW1gFF-n8yPsVakDGDmrNHod_3BKquWkHI; FPLC=0cwaDGpn9gDBc5kgScVenLiwA4ke7utdzOwoyYXd01vs%2BTmgjutMCQsNbb4Op9PIx91duASeDnByT92SJCBf7O9%2BcIrWqPtwAdF%2BnTeb9U9Qwtfe%2Fc5qsS4YtdCK3Q%3D%3D; csrfToken=UXnAHlaM-oJpqmZgGifEUaKBQt2qDZdEs5VE; csrf_session_id=6fae5912276f9c74c1655a3bdd905016; s_v_web_id=verify_m8ijel2v_9YnZMchp_swhm_4bs1_9GXv_G1EbQ1f3NTh4; d_ticket=29d26aed73a954d73f7f495857a66eed44a85; multi_sids=7480081853916922896%3Ad2199c813f4c846be72cc15f3e31588d; cmpl_token=AgQQAPO7F-RO0rfweHcpop0p_a8Pj5Yav4ohYNi_-w; uid_tt=5bc3b1892a01e1d11e13425d33f3ce57a110ea566d0914bcd316f729167a2d4f; uid_tt_ss=5bc3b1892a01e1d11e13425d33f3ce57a110ea566d0914bcd316f729167a2d4f; sid_tt=d2199c813f4c846be72cc15f3e31588d; sessionid=d2199c813f4c846be72cc15f3e31588d; sessionid_ss=d2199c813f4c846be72cc15f3e31588d; store-idc=alisg; store-country-code=ph; store-country-code-src=uid; tt-target-idc=alisg; tt-target-idc-sign=nVo6E-__ps27ANpVx26momHQUU-VWByzS7Qdt3dPewZU-6bU2W7N7X8v561Miu5Nw1KpnuOj_5-vzZUkbAZqcW8qvoGFC11aSH8_qSWtcanul6aB4sO5GCgaOQnKWiYgGnqk7l3yjQncUBiZhi1O7GQUsr4nmFELFcCezMPO1R46h39Z0szBn_P0QNyzLDRhB3wJWSm9wXxGJFSxCYvC8dQiaojppyHwlowVTmQwPT8WJiFPu60f_AjHO6nJ-tfc6MgwJN4SeLVZgFx1SCBhvd0d7UOjaqPUx5YtS9Q4JkQaZcA_huo-E5g-Tvc2YnDYljdf-QEpHPjFW6AQhxpPQeQMDiZe8IXi7YcqXSU4CnYGxi7pCrp_fBXksqMbb8Xr4z1ZjME_rtMTWrCtF7kmKUvmcmCQDAguNDsNuvj8hN00j6dmZ2yozG35rwUf97owUqpRQk9uu241pAtQ-DHcpvUh08cfUUxD8D5woeMay7mPq1f3lHVkqF9rATCYVdcJ; sid_guard=d2199c813f4c846be72cc15f3e31588d%7C1742546855%7C15551996%7CWed%2C+17-Sep-2025+08%3A47%3A31+GMT; sid_ucp_v1=1.0.0-KGMxNmNhMWIzOWQ1NjQzM2UxOWVhNTZiYmZjM2MxNjZmOTVkMWQ2MWIKGgiQiMGMitql52cQp8_0vgYYsws4AUDqB0gEEAMaAm15IiBkMjE5OWM4MTNmNGM4NDZiZTcyY2MxNWYzZTMxNTg4ZA; ssid_ucp_v1=1.0.0-KGMxNmNhMWIzOWQ1NjQzM2UxOWVhNTZiYmZjM2MxNjZmOTVkMWQ2MWIKGgiQiMGMitql52cQp8_0vgYYsws4AUDqB0gEEAMaAm15IiBkMjE5OWM4MTNmNGM4NDZiZTcyY2MxNWYzZTMxNTg4ZA; ttwid=1%7Cchxl-ZAvAGfFU51SNT77wDZpLYJaLof20G7FKm8_DFo%7C1742553650%7C5fcb46d604bb476d1b8d8047e750969770090f323ddbb69c969dc5a603c5b5dc; store-country-sign=MEIEDFJ-0POjzOvOax6tXgQgdL8sJRGNGwCKAKrA6Ba9AdAyNXHazJ3SWgAuRKKzN3MEEFmTC_o_venconbY3G7AAPs; odin_tt=c97f93758dadfc5203f0dfa5e629ae3c403fffd1a639692aa76319a0b43a3b60cb3bd7db7550fb4aaaf72d1a397293970922de61e112343f44e0d06ebd73dfd58e5629ff4c49fbeac266784326e8b61a; _ga_LWWPCY99PB=GS1.1.1742551714.41.1.1742554753.0.0.290463167; msToken={mstoken}',
|
||||||
|
# "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# form_data = {
|
||||||
|
# 'enter_source': 'recommend-next_icon_click',
|
||||||
|
#
|
||||||
|
# # 注意,room_id是会变化的,后面要从直播大厅直接拿数据,作为入参传进来
|
||||||
|
# 'room_id': f'{roomid}'
|
||||||
|
# }
|
||||||
|
# # 发送 POST 请求
|
||||||
|
# response = requests.post(url, headers=headers, data=form_data)
|
||||||
|
# # json格式
|
||||||
|
# return response
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#feed接口拿房间号
|
||||||
|
'''
|
||||||
|
预留的功能模块,动态获取cookie
|
||||||
|
'''
|
||||||
|
#获取动态的cookie。目前先写死
|
||||||
|
mstoken = 'mtzl_MJ-pnO3ChopXcF_2I5a6hgYgIxUr-anVWajHYB3eZzQad8E6JvthPC1TQ4h_T5hQC7_NEmlNpyPIRWuVFRu8vdCYCHGa3F6B8L-mx1vYz7p4fvdtiDACP5f8v__74P4-x1AfaZQhRE='
|
||||||
|
|
||||||
|
# 连接到MySQL数据库
|
||||||
|
#后续业务复杂性提升的话,可以考虑引入SQLAlchemy框架
|
||||||
|
config = {
|
||||||
|
'host' : '120.26.251.180',
|
||||||
|
'port': '3326',
|
||||||
|
'user' : 'root',
|
||||||
|
'password' : 'wfn53400',
|
||||||
|
'database' : 'tkdata'
|
||||||
|
}
|
||||||
|
# 建立连接
|
||||||
|
conn = mysql.connector.connect(**config)
|
||||||
|
print("连接成功!")
|
||||||
|
|
||||||
|
# 创建一个游标对象来执行 SQL 语句
|
||||||
|
cursor = conn.cursor()
|
||||||
|
#搜索区域,目前写死,其实不用填写,会自动根据vpn转
|
||||||
|
region = "DE"
|
||||||
|
|
||||||
|
def gethostsinfo():
|
||||||
|
'''
|
||||||
|
业务代码,爬取各类信息
|
||||||
|
'''
|
||||||
|
#feed接口的返回,返回了多个房间的数据
|
||||||
|
roomlist = fetch_tiktok_feed(mstoken,region).get("data")
|
||||||
|
|
||||||
|
#有些国家可能没有直播的,需要添加兼容,别报错
|
||||||
|
if roomlist is not None:
|
||||||
|
num = len(roomlist)
|
||||||
|
else:
|
||||||
|
num = 0
|
||||||
|
|
||||||
|
for room in roomlist:
|
||||||
|
# 这张表的数据有多条,创建字典
|
||||||
|
hosts_info_dict = {}
|
||||||
|
|
||||||
|
dataall = room.get("data")
|
||||||
|
|
||||||
|
#房间号
|
||||||
|
try:
|
||||||
|
roomid = dataall.get("id_str")
|
||||||
|
# print(roomid)
|
||||||
|
except:
|
||||||
|
print("未能获取到房间号")
|
||||||
|
continue
|
||||||
|
|
||||||
|
#主播id
|
||||||
|
try:
|
||||||
|
hosts__host_id = dataall.get("owner").get("display_id")
|
||||||
|
#主播的用户号,需要查询金币使用
|
||||||
|
hosts__host_id_str = dataall.get("owner").get("id_str")
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
#默认目前我来托管
|
||||||
|
hosts__owner_by = 666675
|
||||||
|
|
||||||
|
#获取主播名称
|
||||||
|
hosts__host_name = dataall.get("owner").get("nickname")
|
||||||
|
|
||||||
|
#获取主播的粉丝数
|
||||||
|
try:
|
||||||
|
fllowernum = dataall.get("owner").get("follow_info").get("follower_count")
|
||||||
|
except:
|
||||||
|
fllowernum = "0"
|
||||||
|
|
||||||
|
#获取主播的关注数
|
||||||
|
try:
|
||||||
|
fllowingnum = dataall.get("owner").get("follow_info").get("following_count")
|
||||||
|
except:
|
||||||
|
fllowingnum = "0"
|
||||||
|
|
||||||
|
#获取直播类型
|
||||||
|
try:
|
||||||
|
hosts_source = dataall.get("hashtag").get("title")
|
||||||
|
except:
|
||||||
|
hosts_source = " "
|
||||||
|
|
||||||
|
#获取在线人数
|
||||||
|
try:
|
||||||
|
onlinefans = dataall.get("user_count")
|
||||||
|
except:
|
||||||
|
onlinefans = "0"
|
||||||
|
|
||||||
|
#获取金币模块,当前数据
|
||||||
|
# enterdata = fetch_tiktok_audience_room_enter_backup(mstoken,roomid).get('data').get("multi_guest_linkmic_info")
|
||||||
|
hostcoins = 0
|
||||||
|
ysthostcoins = 0
|
||||||
|
try:
|
||||||
|
#锚定的id=hosts__host_id_str,需要先写死
|
||||||
|
hostinfo = fetch_tiktok_ranklist_list_v2(mstoken, roomid,hosts__host_id_str,0).get("data").get("rank_view").get("owner_rank")
|
||||||
|
hostcoins = hostinfo.get("score")
|
||||||
|
|
||||||
|
#昨日的金币
|
||||||
|
yshostinfo = fetch_tiktok_ranklist_list_v2(mstoken, roomid, hosts__host_id_str, -1).get("data").get("rank_view").get("owner_rank")
|
||||||
|
ysthostcoins = yshostinfo.get("score")
|
||||||
|
except:
|
||||||
|
print("不能获取主播金币")
|
||||||
|
|
||||||
|
# 获取list接口的返回,取国家信息和等级
|
||||||
|
hosts__country = 'unkown'
|
||||||
|
hostlevel = " "
|
||||||
|
|
||||||
|
# 获取金币模块,周数据
|
||||||
|
weeklycoins = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = fetch_tiktok_list(mstoken,roomid,region)
|
||||||
|
# 获取国家的代码逻辑
|
||||||
|
pages = data.get("data").get("pages")[0]
|
||||||
|
|
||||||
|
hosts__country = cc.get_country_name(pages.get("region"))
|
||||||
|
|
||||||
|
# 获取主播的等级数据,需要插入字典中,做个映射
|
||||||
|
hostlevel = data.get("data").get("gifts_info").get("gift_gallery_info").get("anchor_ranking_league")
|
||||||
|
|
||||||
|
#获取周金币数据
|
||||||
|
try:
|
||||||
|
giftslist = pages.get("gifts")
|
||||||
|
for gift in giftslist:
|
||||||
|
price = gift.get("diamond_count")
|
||||||
|
if gift.get("gift_sponsor_info") is not None:
|
||||||
|
#数量乘时间的累加
|
||||||
|
weeklycoins += gift.get("gift_sponsor_info").get("sponsor_count") * price
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
except:
|
||||||
|
print("获取周金币数据失败")
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 获取直播的时间戳,可以转换
|
||||||
|
livetime = datetime.datetime.fromtimestamp(dataall.get("owner").get("modify_time"))
|
||||||
|
recordtime = datetime.datetime.now()
|
||||||
|
tips = f"我爬取了: {hosts__host_name}的直播信息,的id是{hosts__host_id},房间号是{roomid},直接类型是{hosts_source}," \
|
||||||
|
f"有{onlinefans}人在看他\n" \
|
||||||
|
f"主播来自: {hosts__country}, 目前的等级是: {hostlevel},今天的开播时间是{livetime},收到了{hostcoins}金币的礼物\n" \
|
||||||
|
f"昨天收到了{ysthostcoins}金币的礼物,主播的粉丝数量为: {fllowernum}, 关注了: {fllowingnum},此条信息记录于{recordtime}"
|
||||||
|
print(tips)
|
||||||
|
|
||||||
|
#添加主播等级
|
||||||
|
hosts_info__info_type = "hostlevel"
|
||||||
|
hosts_info__info_value = hostlevel
|
||||||
|
hosts_info_dict.update({hosts_info__info_type: hosts_info__info_value})
|
||||||
|
|
||||||
|
# 获取金币
|
||||||
|
hosts_info__info_type = "hostcoins"
|
||||||
|
hosts_info__info_value = hostcoins
|
||||||
|
hosts_info_dict.update({hosts_info__info_type: hosts_info__info_value})
|
||||||
|
|
||||||
|
# 获取昨日金币
|
||||||
|
hosts_info__info_type = "ysthostcoins"
|
||||||
|
hosts_info__info_value = ysthostcoins
|
||||||
|
hosts_info_dict.update({hosts_info__info_type: hosts_info__info_value})
|
||||||
|
|
||||||
|
# 获取主播的粉丝数量
|
||||||
|
hosts_info__info_type = "fllowernum"
|
||||||
|
hosts_info__info_value = fllowernum
|
||||||
|
hosts_info_dict.update({hosts_info__info_type: hosts_info__info_value})
|
||||||
|
|
||||||
|
# 获取主播关注的其他人的数量
|
||||||
|
hosts_info__info_type = "fllowingnum"
|
||||||
|
hosts_info__info_value = fllowingnum
|
||||||
|
hosts_info_dict.update({hosts_info__info_type: hosts_info__info_value})
|
||||||
|
|
||||||
|
# 获取直播间人数
|
||||||
|
hosts_info__info_type = "onlinefans"
|
||||||
|
hosts_info__info_value = onlinefans
|
||||||
|
hosts_info_dict.update({hosts_info__info_type: hosts_info__info_value})
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 插入数据到hosts表中
|
||||||
|
# host_id, host_name, owner_by, belong_yn, country, hosts_source, value_level, reserve_1, reserve_2, create_dt, update_dt
|
||||||
|
hosts__create_dt = str(livetime)
|
||||||
|
# 更新时间暂定现在
|
||||||
|
hosts__update_dt = str(livetime)[0:10].replace("-", "")
|
||||||
|
# 被管理状态暂时设为no
|
||||||
|
hosts__belong_yn = 'N'
|
||||||
|
# 主播来源暂时设为0
|
||||||
|
hosts__hosts_source = hosts_source
|
||||||
|
# 主播价值暂时设为no
|
||||||
|
hosts__value_level = '0'
|
||||||
|
# 保留字段暂时为0
|
||||||
|
hosts__tenant_id = 'vic'
|
||||||
|
# 保留字段暂时为0
|
||||||
|
hosts__reserve_2 = '0'
|
||||||
|
|
||||||
|
# hosts表的插入
|
||||||
|
values = f"'{hosts__host_id}','{hosts__host_name}','{hosts__owner_by}','{hosts__belong_yn}','{hosts__country}','{hosts__hosts_source}'" \
|
||||||
|
f",'{hosts__value_level}','{hosts__tenant_id}','{hosts__reserve_2}','{hosts__create_dt}','{hosts__update_dt}'"
|
||||||
|
|
||||||
|
# print(values)
|
||||||
|
hostssql = tt.insertorupdate_hosts_sql(values,hosts__country,hosts__update_dt)
|
||||||
|
print(hostssql)
|
||||||
|
cursor.execute(hostssql)
|
||||||
|
|
||||||
|
# hostsinfo的插入,这里需要先验证今天有没有该条主播的信息,没有就插入,有就更新
|
||||||
|
# hosts_id,info_type,info_value,part_month,reserve_1,reserve_2,create_dt,create_by,update_dt,update_by
|
||||||
|
hosts_info__hosts_id = hosts__host_id
|
||||||
|
hosts_info__part_month = str(livetime)[0:10].replace("-", "")
|
||||||
|
hosts_info__create_dt = str(livetime)
|
||||||
|
# 默认由自己创建
|
||||||
|
hosts_info__create_by = "666675"
|
||||||
|
|
||||||
|
for key, value in hosts_info_dict.items():
|
||||||
|
values = f"'{hosts_info__hosts_id}','{key}','{value}','{hosts_info__part_month}','{tt.hosts_info.hosts_info__reserve_1}'," \
|
||||||
|
f"'{tt.hosts_info.hosts_info__reserve_2}','{hosts_info__create_dt}','{hosts_info__create_by}','{tt.hosts_info.hosts_info__update_dt}','{tt.hosts_info.hosts_info__update_by}'"
|
||||||
|
hostsinfosql = tt.insertorupdate_hosts_info_sql(values, key, value, hosts_info__create_dt)
|
||||||
|
#注入语句打印一下
|
||||||
|
#print(hostsinfosql)
|
||||||
|
cursor.execute(hostsinfosql)
|
||||||
|
|
||||||
|
except mysql.connector.Error as err:
|
||||||
|
conn.rollback()
|
||||||
|
print(f"连接失败:{err}")
|
||||||
|
|
||||||
|
return num
|
||||||
|
|
||||||
|
#测试轮询爬取
|
||||||
|
countnum = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# starttime = datetime.datetime.now()
|
||||||
|
countnum += gethostsinfo()
|
||||||
|
# endtime = datetime.datetime.now()
|
||||||
|
# print("耗时",str(endtime-starttime))
|
||||||
|
# print("目前获取了"+str(countnum)+"个数据")
|
||||||
|
if countnum >= 30:
|
||||||
|
# 关闭游标和连接
|
||||||
|
conn.commit()
|
||||||
|
print("已经提交了"+str(countnum)+"条")
|
||||||
|
if countnum >= 100000:
|
||||||
|
cursor.close()
|
||||||
|
conn.close()
|
||||||
|
break
|
||||||
BIN
src/assets/img/demos/2025-04/country_info.xls
Normal file
264
src/assets/img/demos/2025-04/countrycode.py
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class CountryCode(Enum):
|
||||||
|
AD = "安道尔"
|
||||||
|
AE = "阿拉伯联合酋长国"
|
||||||
|
AF = "阿富汗"
|
||||||
|
AG = "安提瓜和巴布达"
|
||||||
|
AI = "安圭拉"
|
||||||
|
AL = "阿尔巴尼亚"
|
||||||
|
AM = "亚美尼亚"
|
||||||
|
AO = "安哥拉"
|
||||||
|
AQ = "南极洲"
|
||||||
|
AR = "阿根廷"
|
||||||
|
AS = "美属萨摩亚"
|
||||||
|
AT = "奥地利"
|
||||||
|
AU = "澳大利亚"
|
||||||
|
AU1 = "澳大利亚"
|
||||||
|
AW = "阿鲁巴"
|
||||||
|
AX = "奥兰群岛"
|
||||||
|
AZ = "阿塞拜疆"
|
||||||
|
BA = "波斯尼亚和黑塞哥维那"
|
||||||
|
BB = "巴巴多斯"
|
||||||
|
BD = "孟加拉国"
|
||||||
|
BE = "比利时"
|
||||||
|
BF = "布基纳法索"
|
||||||
|
BG = "保加利亚"
|
||||||
|
BH = "巴林"
|
||||||
|
BI = "布隆迪"
|
||||||
|
BJ = "贝宁"
|
||||||
|
BL = "圣巴泰勒米"
|
||||||
|
BM = "百慕大群岛"
|
||||||
|
BN = "文莱达鲁萨兰国"
|
||||||
|
BO = "玻利维亚"
|
||||||
|
BQ = "博奈尔、圣尤斯特歇斯和萨巴"
|
||||||
|
BR = "巴西"
|
||||||
|
BS = "巴哈马"
|
||||||
|
BT = "不丹"
|
||||||
|
BV = "布韦岛"
|
||||||
|
BW = "博茨瓦纳"
|
||||||
|
BY = "白俄罗斯"
|
||||||
|
BZ = "伯利兹"
|
||||||
|
CA = "加拿大"
|
||||||
|
CA1 = "加拿大"
|
||||||
|
CC = "科科斯(基林)群岛"
|
||||||
|
CD = "刚果民主共和国"
|
||||||
|
CF = "中非共和国"
|
||||||
|
CG = "刚果共和国"
|
||||||
|
CH = "瑞士"
|
||||||
|
CI = "科特迪瓦"
|
||||||
|
CK = "库克群岛"
|
||||||
|
CL = "智利"
|
||||||
|
CM = "喀麦隆"
|
||||||
|
CN = "中国"
|
||||||
|
CO = "哥伦比亚"
|
||||||
|
CR = "哥斯达黎加"
|
||||||
|
CU = "古巴"
|
||||||
|
CV = "佛得角"
|
||||||
|
CW = "库拉索"
|
||||||
|
CX = "圣诞岛"
|
||||||
|
CY = "塞浦路斯"
|
||||||
|
CZ = "捷克共和国"
|
||||||
|
DE = "德国"
|
||||||
|
DG = "迪戈加西亚岛"
|
||||||
|
DJ = "吉布提"
|
||||||
|
DK = "丹麦"
|
||||||
|
DM = "多米尼克"
|
||||||
|
DO = "多米尼加共和国"
|
||||||
|
DZ = "阿尔及利亚"
|
||||||
|
EC = "厄瓜多尔"
|
||||||
|
EE = "爱沙尼亚"
|
||||||
|
EG = "埃及"
|
||||||
|
EH = "西撒哈拉"
|
||||||
|
ER = "厄立特里亚"
|
||||||
|
ES = "西班牙"
|
||||||
|
ET = "埃塞俄比亚"
|
||||||
|
FI = "芬兰"
|
||||||
|
FJ = "斐济"
|
||||||
|
FK = "福克兰群岛"
|
||||||
|
FM = "密克罗尼西亚"
|
||||||
|
FO = "法罗群岛"
|
||||||
|
FR = "法国"
|
||||||
|
GA = "加蓬"
|
||||||
|
GB = "英国"
|
||||||
|
GD = "格林纳达"
|
||||||
|
GE = "格鲁吉亚"
|
||||||
|
GF = "法属圭亚那"
|
||||||
|
GG = "根西岛"
|
||||||
|
GH = "加纳"
|
||||||
|
GI = "直布罗陀"
|
||||||
|
GL = "格陵兰"
|
||||||
|
GM = "冈比亚"
|
||||||
|
GN = "几内亚"
|
||||||
|
GP = "瓜德罗普"
|
||||||
|
GQ = "赤道几内亚"
|
||||||
|
GR = "希腊"
|
||||||
|
GS = "南乔治亚和南桑德威奇群岛"
|
||||||
|
GT = "危地马拉"
|
||||||
|
GU = "关岛"
|
||||||
|
GW = "几内亚比绍"
|
||||||
|
GY = "圭亚那"
|
||||||
|
HK = "中国香港特别行政区"
|
||||||
|
HM = "赫德岛和麦克唐纳群岛"
|
||||||
|
HN = "洪都拉斯"
|
||||||
|
HR = "克罗地亚"
|
||||||
|
HT = "海地"
|
||||||
|
HU = "匈牙利"
|
||||||
|
ID = "印度尼西亚"
|
||||||
|
IE = "爱尔兰"
|
||||||
|
IL = "以色列"
|
||||||
|
IM = "马恩岛"
|
||||||
|
IN = "印度"
|
||||||
|
IO = "英属印度洋领地"
|
||||||
|
IQ = "伊拉克"
|
||||||
|
IR = "伊朗"
|
||||||
|
IS = "冰岛"
|
||||||
|
IT = "意大利"
|
||||||
|
JE = "泽西岛"
|
||||||
|
JM = "牙买加"
|
||||||
|
JO = "约旦"
|
||||||
|
JP = "日本"
|
||||||
|
JP1 = "日本"
|
||||||
|
KE = "肯尼亚"
|
||||||
|
KG = "吉尔吉斯斯坦"
|
||||||
|
KH = "柬埔寨"
|
||||||
|
KI = "基里巴斯"
|
||||||
|
KM = "科摩罗"
|
||||||
|
KN = "圣基茨和尼维斯"
|
||||||
|
KP = "朝鲜"
|
||||||
|
KR = "韩国"
|
||||||
|
KR1 = "韩国"
|
||||||
|
KR1_UXWAUDIT = "韩国"
|
||||||
|
KW = "科威特"
|
||||||
|
KY = "开曼群岛"
|
||||||
|
KZ = "哈萨克斯坦"
|
||||||
|
LA = "老挝"
|
||||||
|
LB = "黎巴嫩"
|
||||||
|
LC = "圣卢西亚"
|
||||||
|
LI = "列支敦士登"
|
||||||
|
LK = "斯里兰卡"
|
||||||
|
LR = "利比里亚"
|
||||||
|
LS = "莱索托"
|
||||||
|
LT = "立陶宛"
|
||||||
|
LU = "卢森堡"
|
||||||
|
LV = "拉脱维亚"
|
||||||
|
LY = "利比亚"
|
||||||
|
MA = "摩洛哥"
|
||||||
|
MC = "摩纳哥"
|
||||||
|
MD = "摩尔多瓦"
|
||||||
|
ME = "黑山"
|
||||||
|
MF = "圣马丁"
|
||||||
|
MG = "马达加斯加"
|
||||||
|
MH = "马绍尔群岛"
|
||||||
|
MK = "北马其顿"
|
||||||
|
ML = "马里"
|
||||||
|
MM = "缅甸"
|
||||||
|
MN = "蒙古"
|
||||||
|
MO = "中国澳门特别行政区"
|
||||||
|
MP = "北马里亚纳群岛"
|
||||||
|
MQ = "马提尼克"
|
||||||
|
MR = "毛里塔尼亚"
|
||||||
|
MS = "蒙特塞拉特"
|
||||||
|
MT = "马耳他"
|
||||||
|
MU = "毛里求斯"
|
||||||
|
MV = "马尔代夫"
|
||||||
|
MW = "马拉维"
|
||||||
|
MX = "墨西哥"
|
||||||
|
MY = "马来西亚"
|
||||||
|
MZ = "莫桑比克"
|
||||||
|
NA = "纳米比亚"
|
||||||
|
NC = "新喀里多尼亚"
|
||||||
|
NE = "尼日尔"
|
||||||
|
NF = "诺福克岛"
|
||||||
|
NG = "尼日利亚"
|
||||||
|
NI = "尼加拉瓜"
|
||||||
|
NL = "荷兰"
|
||||||
|
NO = "挪威"
|
||||||
|
NP = "尼泊尔"
|
||||||
|
NR = "瑙鲁"
|
||||||
|
NU = "纽埃"
|
||||||
|
NZ = "新西兰"
|
||||||
|
OM = "阿曼"
|
||||||
|
PA = "巴拿马"
|
||||||
|
PE = "秘鲁"
|
||||||
|
PF = "法属玻利尼西亚"
|
||||||
|
PG = "巴布亚新几内亚"
|
||||||
|
PH = "菲律宾"
|
||||||
|
PK = "巴基斯坦"
|
||||||
|
PL = "波兰"
|
||||||
|
PM = "圣皮埃尔和密克隆群岛"
|
||||||
|
PN = "皮特凯恩群岛"
|
||||||
|
PR = "波多黎各"
|
||||||
|
PS = "巴勒斯坦"
|
||||||
|
PT = "葡萄牙"
|
||||||
|
PW = "帕劳"
|
||||||
|
PY = "巴拉圭"
|
||||||
|
QA = "卡塔尔"
|
||||||
|
RE = "留尼汪"
|
||||||
|
RO = "罗马尼亚"
|
||||||
|
RS = "塞尔维亚"
|
||||||
|
RU = "俄罗斯"
|
||||||
|
RW = "卢旺达"
|
||||||
|
SA = "沙特阿拉伯"
|
||||||
|
SB = "索罗门群岛"
|
||||||
|
SC = "塞舌尔"
|
||||||
|
SD = "苏丹"
|
||||||
|
SE = "瑞典"
|
||||||
|
SG = "新加坡"
|
||||||
|
SI = "斯洛文尼亚"
|
||||||
|
SJ = "斯瓦尔巴和扬马延"
|
||||||
|
SK = "斯洛伐克"
|
||||||
|
SL = "塞拉利昂"
|
||||||
|
SM = "圣马利诺"
|
||||||
|
SN = "塞内加尔"
|
||||||
|
SO = "索马里"
|
||||||
|
SR = "苏里南"
|
||||||
|
SS = "南苏丹"
|
||||||
|
ST = "圣多美和普林西比"
|
||||||
|
SV = "萨尔瓦多"
|
||||||
|
SX = "荷属圣马丁"
|
||||||
|
SY = "叙利亚"
|
||||||
|
SZ = "斯威士兰"
|
||||||
|
TC = "特克斯和凯科斯群岛"
|
||||||
|
TD = "乍得"
|
||||||
|
TF = "法属南部领地"
|
||||||
|
TG = "多哥"
|
||||||
|
TH = "泰国"
|
||||||
|
TJ = "塔吉克斯坦"
|
||||||
|
TK = "托克劳群岛"
|
||||||
|
TL = "东帝汶"
|
||||||
|
TM = "土库曼斯坦"
|
||||||
|
TN = "突尼斯"
|
||||||
|
TO = "汤加"
|
||||||
|
TR = "土耳其"
|
||||||
|
TT = "特立尼达和多巴哥"
|
||||||
|
TV = "图瓦卢"
|
||||||
|
TW = "台湾"
|
||||||
|
TZ = "坦桑尼亚"
|
||||||
|
UA = "乌克兰"
|
||||||
|
UG = "乌干达"
|
||||||
|
UM = "美国本土外小岛屿"
|
||||||
|
US = "美国"
|
||||||
|
UY = "乌拉圭"
|
||||||
|
UZ = "乌兹别克斯坦"
|
||||||
|
VA = "梵蒂冈"
|
||||||
|
VC = "圣文森特"
|
||||||
|
VE = "委内瑞拉"
|
||||||
|
VG = "英属维尔京群岛"
|
||||||
|
VI = "美属维尔京群岛"
|
||||||
|
VN = "越南"
|
||||||
|
VN1 = "越南"
|
||||||
|
VU = "瓦努阿图"
|
||||||
|
WS = "萨摩亚"
|
||||||
|
YE = "也门"
|
||||||
|
YT = "马约特岛"
|
||||||
|
ZA = "南非"
|
||||||
|
ZM = "赞比亚"
|
||||||
|
ZW = "津巴布韦"
|
||||||
|
|
||||||
|
# 用法封装
|
||||||
|
def get_country_name(code):
|
||||||
|
try:
|
||||||
|
return CountryCode[code].value
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
BIN
src/assets/img/demos/2025-04/default-file-name (3).xls
Normal file
BIN
src/assets/img/demos/2025-04/default-file-name (4).xlsx
Normal file
BIN
src/assets/img/demos/2025-04/dist(1).rar
Normal file
BIN
src/assets/img/demos/2025-04/dist(2).rar
Normal file
BIN
src/assets/img/demos/2025-04/dist(3).rar
Normal file
BIN
src/assets/img/demos/2025-04/dist(4).rar
Normal file
BIN
src/assets/img/demos/2025-04/dist(5).rar
Normal file
BIN
src/assets/img/demos/2025-04/dist(6).rar
Normal file
BIN
src/assets/img/demos/2025-04/dist(7).rar
Normal file
BIN
src/assets/img/demos/2025-04/dist(8).rar
Normal file
BIN
src/assets/img/demos/2025-04/dist(9).rar
Normal file
BIN
src/assets/img/demos/2025-04/dist.rar
Normal file
18
src/assets/img/demos/2025-04/feed.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
def fetch_tiktok_feed(mstoken,region):
|
||||||
|
mstoken = 'mtzl_MJ-pnO3ChopXcF_2I5a6hgYgIxUr-anVWajHYB3eZzQad8E6JvthPC1TQ4h_T5hQC7_NEmlNpyPIRWuVFRu8vdCYCHGa3F6B8L-mx1vYz7p4fvdtiDACP5f8v__74P4-x1AfaZQhRE='
|
||||||
|
headers = {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
|
||||||
|
'Cookie': f'tt_chain_token=TxibwRSi3KKe1tf6pISVVQ==; passport_csrf_token=4e893d911568da55730040fc1878559c; passport_csrf_token_default=4e893d911568da55730040fc1878559c; _ga=GA1.1.1942425062.1741594510; FPID=FPID2.2.XItvG4EXgMzYHHXywTiqoJBFZRNVPtwkDonum5HhWgs%3D.1741594510; FPAU=1.2.565309640.1741594511; _fbp=fb.1.1741594510841.2080490210; tiktok_webapp_lang=zh-Hans; passport_auth_status=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; passport_auth_status_ss=98e26cf148d3b31544b1e2b3116ac83e%2C9faaf97cadfd79d24eeacb85863f3cbb; multi_sids=7480081853916922896%3A36084ce2b0f8b96b6bd6dea2b3b2c77a; cmpl_token=AgQQAPO7F-RO0rfweHcpop0p_a8Pj5Yav4owYNi60g; uid_tt=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; uid_tt_ss=487180040fe050b6c38b7a10df35bc74da00193f9ed8cefadd9276a17a05313f; sid_tt=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid=36084ce2b0f8b96b6bd6dea2b3b2c77a; sessionid_ss=36084ce2b0f8b96b6bd6dea2b3b2c77a; store-idc=alisg; store-country-code=FR; store-country-code-src=uid; tt-target-idc=alisg; tt-target-idc-sign=ErAK_1daK7gOjNVGp3XkXR9xzLSLfCco9CTBlhCR9C9zJPfvo6iX0NZw1W80EEuME3nR10Dm8UNo5LfL3hDFtLUKyWtW58OnsGXT-QauQpwM9_6kDO_IvlhTNZzyD5PSqXS2hlJ_3Tl8nji5rVw96JCPdSoOQjaXRT8ooCSMKK027uCwQ5-SJFZJgcgmWKLDIINnviE4cqehrzacIx02M13H_SSVNbX7-tJSCyJEqEuLOSYfOTFs_DZPX_P9gSWsjQcZBnyxFWPwdUzheKYa58EeikgtePwWYvP9H5M5kyYiBfxzekOlwy3zvuv2rEJXkaRPaPoXAzgz1bFjjacwGZKGocIBUH6DH58P6V0-IZcAZHkloyN8Q2igQCfry0uDeWPo8ds3HQnMf-xo5doOve-NBLl_jmVivEr1M9YRze-NuXdnuhImeOK3Az0evFhar6nUMBNKpQBIcSprpgHETZJ9Kyit9j8YvApFWq3fWeOLtMIkhIUXf1nEErH-cUNH; sid_guard=36084ce2b0f8b96b6bd6dea2b3b2c77a%7C1742471450%7C15551959%7CTue%2C+16-Sep-2025+11%3A50%3A09+GMT; sid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; ssid_ucp_v1=1.0.0-KDkzMmQzNjk2NWFhYjdjZjIxNGNjMDJhMWY3ODY0NjU2Yjg4Yjk0NGUKGgiQiMGMitql52cQmoLwvgYYsws4AUDrB0gEEAMaAm15IiAzNjA4NGNlMmIwZjhiOTZiNmJkNmRlYTJiM2IyYzc3YQ; tt_csrf_token=g4gW1gFF-n8yPsVakDGDmrNHod_3BKquWkHI; ttwid=1%7Cchxl-ZAvAGfFU51SNT77wDZpLYJaLof20G7FKm8_DFo%7C1742537773%7C662969551ee538eab2dcdc43c3fe4040eb616fadb0643fdf214cd492020211bb; store-country-sign=MEIEDAsnjoHJTjFNneFmHAQgQR99HNzDAO_9D6SuCvfYF54a6DyVUejXuTNuzPiPad4EECxy0Xgv6zgOnvZRwbL1BOI; odin_tt=f6dd93d06620a488d2c682614b0220bd90ce162c6ed4519dd238268f2d093ba6681742fda279cbbc281003b9653189488b0835410c681b9dd606fc3bea583d1e7db3636194de935ad4fb5a4edb93bc7f; FPLC=0cwaDGpn9gDBc5kgScVenLiwA4ke7utdzOwoyYXd01vs%2BTmgjutMCQsNbb4Op9PIx91duASeDnByT92SJCBf7O9%2BcIrWqPtwAdF%2BnTeb9U9Qwtfe%2Fc5qsS4YtdCK3Q%3D%3D; csrfToken=UXnAHlaM-oJpqmZgGifEUaKBQt2qDZdEs5VE; csrf_session_id=6fae5912276f9c74c1655a3bdd905016; msToken={mstoken}; _ga_LWWPCY99PB=GS1.1.1742537780.39.1.1742538627.0.0.1606106523'
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
#req_from的属性需要重新设置为:webapp_taxonomy_drawer_enter_feed
|
||||||
|
url = f'https://webcast.tiktok.com/webcast/feed/?aid=1988&app_language=zh-Hans&app_name=tiktok_web&browser_language=zh-CN&browser_name=Mozilla&browser_online=true&browser_platform=Win32&browser_version=5.0%20%28Windows%20NT%2010.0%3B%20Win64%3B%20x64%29%20AppleWebKit%2F537.36%20%28KHTML%2C%20like%20Gecko%29%20Chrome%2F129.0.0.0%20Safari%2F537.36&channel=tiktok_web&channel_id=1222001&cookie_enabled=true&data_collection_enabled=true&device_id=7480081766272042504&device_platform=web_pc&device_type=web_h265&focus_state=true&from_page=live&history_len=40&is_fullscreen=false&is_non_personalized=0&is_page_visible=true&os=windows&priority_region=&referer=https%3A%2F%2Fwww.tiktok.com%2F%40chuanyuwang20®ion=PH&related_live_tag=chatting&req_from=pc_web_recommend_room&root_referer=https%3A%2F%2Fwww.tiktok.com%2F%40chuanyuwang20&screen_height=1080&screen_width=1920&tz_name=Asia%2FShanghai&user_is_login=true&webcast_language=zh-Hans&msToken={mstoken}&_signature=_02B4Z6wo000019C5TqAAAIDCn.1ptJ30HF.QuUoAAJP85b'
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
response.raise_for_status() # 如果请求失败,会抛出HTTPError异常
|
||||||
|
# 解析JSON响应
|
||||||
|
data = response.json()
|
||||||
|
return data
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"请求失败: {e}")
|
||||||
|
return None
|
||||||
291
src/assets/img/demos/2025-04/get_batch(1).py
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# import time
|
||||||
|
#
|
||||||
|
# import requests
|
||||||
|
# import json
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# headers = {
|
||||||
|
# "accept": "application/json, text/plain, */*",
|
||||||
|
# "accept-language": "zh-CN,zh;q=0.9",
|
||||||
|
# "content-type": "application/json",
|
||||||
|
# "faction-id": "101876",
|
||||||
|
# "origin": "https://live-backstage.tiktok.com",
|
||||||
|
# "priority": "u=1, i",
|
||||||
|
# "referer": "https://live-backstage.tiktok.com/portal/overview",
|
||||||
|
# "sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
|
||||||
|
# "sec-ch-ua-mobile": "?0",
|
||||||
|
# "sec-ch-ua-platform": "\"Windows\"",
|
||||||
|
# "sec-fetch-dest": "empty",
|
||||||
|
# "sec-fetch-mode": "cors",
|
||||||
|
# "sec-fetch-site": "same-origin",
|
||||||
|
# "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
|
||||||
|
# "x-appid": "1180",
|
||||||
|
# "x-csrf-token": "undefined",
|
||||||
|
# "x-language": "zh-Hans",
|
||||||
|
# "x-secsdk-csrf-token": "000100000001a2b7d6e383fd83174d70e9e13de88857bec4f39be23c3cc0747401a9c94949971836beb4628ab5a8"
|
||||||
|
# }
|
||||||
|
# # cookies = {
|
||||||
|
# # "s_v_web_id": "verify_m9jnunys_7L3fxVAj_Uvvc_4SFB_A6IR_0D77iQR4Lt7m",
|
||||||
|
# # "passport_csrf_token": "590d7ce7c5c8652da08d29007a87ccb6",
|
||||||
|
# # "passport_csrf_token_default": "590d7ce7c5c8652da08d29007a87ccb6",
|
||||||
|
# # "d_ticket_backstage": "ba92711982ddeac04b9f98f2efd7007c08a5a",
|
||||||
|
# # "uid_tt_backstage": "eb7edba319a8b3a84d255aa11422cdeb15c9c8aaf0f400a677b81d15d1134d2a",
|
||||||
|
# # "uid_tt_ss_backstage": "eb7edba319a8b3a84d255aa11422cdeb15c9c8aaf0f400a677b81d15d1134d2a",
|
||||||
|
# # "sid_tt_backstage": "b9c7e5436006785411420080dc2d37e3",
|
||||||
|
# # "sessionid_backstage": "b9c7e5436006785411420080dc2d37e3",
|
||||||
|
# # "sessionid_ss_backstage": "b9c7e5436006785411420080dc2d37e3",
|
||||||
|
# # "sid_guard_backstage": "b9c7e5436006785411420080dc2d37e3%7C1744791584%7C5183996%7CSun%2C+15-Jun-2025+08%3A19%3A40+GMT",
|
||||||
|
# # "sid_ucp_v1_backstage": "1.0.0-KDQ4NjY3YWVmNThjZDJiZGNmZjA5ZjVkYzE3ODE2YTZiMTM0ZWJkMjIKGAiGiJXQ7fTjjWcQoND9vwYYwTU4AUDrBxADGgZtYWxpdmEiIGI5YzdlNTQzNjAwNjc4NTQxMTQyMDA4MGRjMmQzN2Uz",
|
||||||
|
# # "ssid_ucp_v1_backstage": "1.0.0-KDQ4NjY3YWVmNThjZDJiZGNmZjA5ZjVkYzE3ODE2YTZiMTM0ZWJkMjIKGAiGiJXQ7fTjjWcQoND9vwYYwTU4AUDrBxADGgZtYWxpdmEiIGI5YzdlNTQzNjAwNjc4NTQxMTQyMDA4MGRjMmQzN2Uz",
|
||||||
|
# # "passport_fe_beating_status": "true",
|
||||||
|
# # "ttwid": "1%7Crlwqo-RnA7TPzGAhHAlZM0qUuMLYN0hvXtvIQCB_rG8%7C1744791585%7Cad3d66e43c668ccb03ab28a959819057295614e399739f758a66fd87d2948e77",
|
||||||
|
# # "csrf_session_id": "64b4328196b861edd2cb4767e1e8e6af",
|
||||||
|
# # "cookie-consent": "{%22optional%22:true%2C%22ga%22:true%2C%22af%22:true%2C%22fbp%22:true%2C%22lip%22:true%2C%22bing%22:true%2C%22ttads%22:true%2C%22reddit%22:true%2C%22hubspot%22:true%2C%22version%22:%22v10%22}",
|
||||||
|
# # "_ga": "GA1.1.459162136.1744791630",
|
||||||
|
# # "_ga_GZB380RXJX": "GS1.1.1744791630.1.0.1744791630.0.0.621335016",
|
||||||
|
# # "_ttp": "2vnrMVBnbyC0vMfL9K5BB9Z6u2o.tt.1",
|
||||||
|
# # "_tt_enable_cookie": "1",
|
||||||
|
# # "ttcsid": "1744791630532.1.1744791630532",
|
||||||
|
# # "FPID": "FPID2.2.QwBg850AKLWqe1V7ktKFgMHXETPYV4c69zBuTI2YROc%3D.1744791630",
|
||||||
|
# # "FPAU": "1.2.2009001839.1744791630",
|
||||||
|
# # "_fbp": "fb.1.1744791630414.1545554243",
|
||||||
|
# # "FPLC": "TPrN8cLVPjh9S9%2FHl5f0n3qn%2FoO58puhQxphpT30nwmqNaJF4bf%2Fp%2F8W%2B79lqOocCcZM4joA2atNh6Rgq8XLNk6RuOapiebbBLlPPVYfMT%2BOIU7ue8X0Eo4cAOVZzA%3D%3D",
|
||||||
|
# # "ttcsid_CQ6FR3RC77U6L0AM21H0": "1744791630531.1.1744791632260",
|
||||||
|
# # "msToken": "rlgeoikWiiMLU7swOLi_DbXpdPBODXkJXUEai-SnWUYnrplV6caHRU3NwHyvUqF0c5XOYhZgt_CTfKJxX8xGy_OC6qf_wYIKDGaS5jjNUc3xdzzC0x9ZAyu0yRz1I5bEjeUg4M96"
|
||||||
|
# # }
|
||||||
|
#
|
||||||
|
# cookies = {
|
||||||
|
# # 'passport_fe_beating_status': 'true',
|
||||||
|
# # 'ssid_ucp_v1_backstage': '1.0.0-KDcwMjIzNjMzYTU1MDViNzVhZjQwZjc4MDJjNWQ4MzU0MmZkOGFjNzgKGAiGiJXQ7fTjjWcQjNP9vwYYwTU4AUDrBxADGgZtYWxpdmEiIDY4YzI2MGU5NDA0MjM2NzdjZTg3OTk3Y2RhOWM5MTM0',
|
||||||
|
# # 'msToken': 'OjoXovaKDp-RmE3AZfQiUsROHEQp6quvuDjNnD_nlWrhSK5mtSoaVHfixIAffIr69G3j9rA3PJuN0wk4qnPeFv5TWyS41f9t22XjgoJUQVJmGV9bYvlf3SbEwl1qQ1UjxwX3x8sP',
|
||||||
|
# # 'sessionid_backstage': '68c260e940423677ce87997cda9c9134',
|
||||||
|
# 'sid_guard_backstage': 'e9001a915acfa5e8d59ce9a1b0ab80c8%7C1744797728%7C5183997%7CSun%2C+15-Jun-2025+10%3A02%3A05+GMT',
|
||||||
|
#
|
||||||
|
# # 'ttwid': '1%7CjH6u3QfKY8-doLE8Fi0l-OcHoE9FQN6BVXNoHsgR1rM%7C1744791948%7Ca0db477248e6592c7187aa9ae35d2510d12eeef8a72f6d890ed575b9630eebe3',
|
||||||
|
# # 'sid_tt_backstage': '68c260e940423677ce87997cda9c9134',
|
||||||
|
# # 'sessionid_ss_backstage': '68c260e940423677ce87997cda9c9134',
|
||||||
|
# # 'uid_tt_backstage': '9664c926b9174006e075c864cc536924534b21797ae3e4904a4332c029504951',
|
||||||
|
# 's_v_web_id': 'verify_m9jriexs_oiMl5mD8_bQd7_4Syc_96ap_oHAEkLfAdBbr',
|
||||||
|
# # 'd_ticket_backstage': 'e3623469149bc2d303235e0611ffae7e260c0',
|
||||||
|
# # 'sid_ucp_v1_backstage': '1.0.0-KDcwMjIzNjMzYTU1MDViNzVhZjQwZjc4MDJjNWQ4MzU0MmZkOGFjNzgKGAiGiJXQ7fTjjWcQjNP9vwYYwTU4AUDrBxADGgZtYWxpdmEiIDY4YzI2MGU5NDA0MjM2NzdjZTg3OTk3Y2RhOWM5MTM0',
|
||||||
|
# # 'passport_csrf_token_default': '09ab6e51d45589114c948d7a434decc0',
|
||||||
|
# # 'uid_tt_ss_backstage': '9664c926b9174006e075c864cc536924534b21797ae3e4904a4332c029504951',
|
||||||
|
# # 'passport_csrf_token': '09ab6e51d45589114c948d7a434decc0'
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# # cookies = {
|
||||||
|
# # "s_v_web_id": "verify_m9jriexs_oiMl5mD8_bQd7_4Syc_96ap_oHAEkLfAdBbr",
|
||||||
|
# # "passport_csrf_token": "41002584d346ed70266ccfded87a63b5",
|
||||||
|
# # "passport_csrf_token_default": "41002584d346ed70266ccfded87a63b5",
|
||||||
|
# # "d_ticket_backstage": "719b1840fbea4af44bbe4e9064e3c8609443d",
|
||||||
|
# # "uid_tt_backstage": "eb1f56382f3e2963bc8e6425029651357fb295379501e752b51f47ee33fd3b5f",
|
||||||
|
# # "uid_tt_ss_backstage": "eb1f56382f3e2963bc8e6425029651357fb295379501e752b51f47ee33fd3b5f",
|
||||||
|
# # "sid_tt_backstage": "e9001a915acfa5e8d59ce9a1b0ab80c8",
|
||||||
|
# # "sessionid_backstage": "e9001a915acfa5e8d59ce9a1b0ab80c8",
|
||||||
|
# # "sessionid_ss_backstage": "e9001a915acfa5e8d59ce9a1b0ab80c8",
|
||||||
|
# # "sid_guard_backstage": "e9001a915acfa5e8d59ce9a1b0ab80c8%7C1744797728%7C5183997%7CSun%2C+15-Jun-2025+10%3A02%3A05+GMT",
|
||||||
|
# # "sid_ucp_v1_backstage": "1.0.0-KGVhMTMzNTliYjVlZmZjOWEzMGJkYjI2ZmMyMmM1OWM4MmQ0ODYzNDMKGAiSiNaglIHTtmcQoID-vwYYwTU4AUDrBxADGgZtYWxpdmEiIGU5MDAxYTkxNWFjZmE1ZThkNTljZTlhMWIwYWI4MGM4",
|
||||||
|
# # "ssid_ucp_v1_backstage": "1.0.0-KGVhMTMzNTliYjVlZmZjOWEzMGJkYjI2ZmMyMmM1OWM4MmQ0ODYzNDMKGAiSiNaglIHTtmcQoID-vwYYwTU4AUDrBxADGgZtYWxpdmEiIGU5MDAxYTkxNWFjZmE1ZThkNTljZTlhMWIwYWI4MGM4",
|
||||||
|
# # "passport_fe_beating_status": "true",
|
||||||
|
# # "ttwid": "1%7Cfp5Gb1OQNsxg8aJybfHCK9L9yqtYpRyQ1M3viBOr72I%7C1744797729%7Ceae5426c3f8990a2e8ef03dea9cac4b9dbc704ef0d669e0a92e39692f88472c9",
|
||||||
|
# # "csrf_session_id": "64b4328196b861edd2cb4767e1e8e6af",
|
||||||
|
# # "msToken": "wNDPPUqbXTafGw9Q_XcnT9VuWG9duaLcmlo2gwPHz97WYwv2eFsPlw250M2Uzw7951EtGnzSiBYAdWEwroxQCt6Kw9XxLVRJv4AyNDEnWxIM41N3e3CiZI3GCVkTRhR8-ahOoys=",
|
||||||
|
# # "cookie-consent": "{%22optional%22:true%2C%22ga%22:true%2C%22af%22:true%2C%22fbp%22:true%2C%22lip%22:true%2C%22bing%22:true%2C%22ttads%22:true%2C%22reddit%22:true%2C%22hubspot%22:true%2C%22version%22:%22v10%22}",
|
||||||
|
# # "_ga": "GA1.1.1962967800.1744797925",
|
||||||
|
# # "_ttp": "2vo47ZF1HgA1kvSWkaHPBMaVr3p.tt.1",
|
||||||
|
# # "_tt_enable_cookie": "1",
|
||||||
|
# # "ttcsid": "1744797925882.1.1744797925882",
|
||||||
|
# # "ttcsid_CQ6FR3RC77U6L0AM21H0": "1744797925879.1.1744797926920",
|
||||||
|
# # "_ga_GZB380RXJX": "GS1.1.1744797925.1.0.1744797933.0.0.912964856"
|
||||||
|
# # }
|
||||||
|
#
|
||||||
|
# # cookies = {'ssid_ucp_v1_backstage': '1.0.0-KDlkMmVjYmM3OWJmYzhmMTVlZWY2MjVlYTQxNWZjZDk4ZDdjYWE3ZWQKGAiCiKiQ2IHy5WQQ2eb9vwYYwTU4AUDrBxADGgZtYWxpdmEiIGExZTVkMDcyNzE3NDA0ZjI5NTdiZGNjMzNmMDNmMWM2', 'sid_guard_backstage': 'a1e5d072717404f2957bdcc33f03f1c6%7C1744794457%7C5183996%7CSun%2C+15-Jun-2025+09%3A07%3A33+GMT', 'passport_csrf_token_default': 'f3aab5003a123929eb452d6a01c5b376', 'msToken': 'VGMaZjyaDbyoH0GTawM3FlUEos1M10jw75oDzk4rFKR2ZYLrKT7m3xrhTmITDKMilFpkLd_dT_wOrpslLDR4n3JPsjRka4Cl-Tr35UWCTUCpdnGH-6uE-wqSRJ98K_51ciUxOHc=', 'sessionid_backstage': 'a1e5d072717404f2957bdcc33f03f1c6', 'd_ticket_backstage': 'c18b04f68b3731bb7a63183af62500228b404', 'ttwid': '1%7CIRh8FYc5kUsBw7NtTYy2GseVFUcjT1n3JJkdTMPMOCo%7C1744794457%7Cbdc793f3160263f868d510d10b0eca4bb0d75806bb874b5f0879e29357eb3bb4', 'sid_tt_backstage': 'a1e5d072717404f2957bdcc33f03f1c6', 'uid_tt_ss_backstage': '7f5d2cc504c32e89e239121ff970fb71c4e88bc23b4fd7760d238997cde6cd28', 'passport_csrf_token': 'f3aab5003a123929eb452d6a01c5b376', 'sessionid_ss_backstage': 'a1e5d072717404f2957bdcc33f03f1c6', 'passport_fe_beating_status': 'true', 'FPLC': 'NkDJld6G5Xs%2F6Nru7Yjrp1wqHLQC4xsd2EGqeKMlo37f%2FMlcBIKnwdyi7ATF5%2FD8c6AZnaKBSDa22ZlndZh%2FzEdxUhxGZCJH9viBw5YDCWFtuuyRL7LhbeX1wpsOUw%3D%3D', '_ttp': '2vnx58uRsi4nL7G25nmUCASbXjD.tt.1', '_tt_enable_cookie': '1', 'FPID': 'FPID2.2.1YH%2FQoB3qTFFKLI6JqGiKf3qel9Ac2%2FF4Z6ouegPPnw%3D.1744794452', 'ttcsid': '1744794452818.1.1744794452818', 'sid_ucp_v1_backstage': '1.0.0-KDlkMmVjYmM3OWJmYzhmMTVlZWY2MjVlYTQxNWZjZDk4ZDdjYWE3ZWQKGAiCiKiQ2IHy5WQQ2eb9vwYYwTU4AUDrBxADGgZtYWxpdmEiIGExZTVkMDcyNzE3NDA0ZjI5NTdiZGNjMzNmMDNmMWM2', 'FPAU': '1.2.418031211.1744794453', 'ttcsid_CQ6FR3RC77U6L0AM21H0': '1744794452815.1.1744794453039', 'cookie-consent': '{%22optional%22:true%2C%22ga%22:true%2C%22af%22:true%2C%22fbp%22:true%2C%22lip%22:true%2C%22bing%22:true%2C%22ttads%22:true%2C%22reddit%22:true%2C%22hubspot%22:true%2C%22version%22:%22v10%22}', '_ga_GZB380RXJX': 'GS1.1.1744794451.1.0.1744794456.0.0.110277459', 's_v_web_id': 'verify_m9jpjz5d_WPnZ4RSj_9wVY_4i8C_8S92_vIAYfsalgZ8Q', '_fbp': 'fb.1.1744794452782.1040477631', '_ga': 'GA1.1.1676829406.1744794452', 'uid_tt_backstage': '7f5d2cc504c32e89e239121ff970fb71c4e88bc23b4fd7760d238997cde6cd28'}
|
||||||
|
# url = "https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/"
|
||||||
|
#
|
||||||
|
# params = {
|
||||||
|
# "msToken": "wNDPPUqbXTafGw9Q_XcnT9VuWG9duaLcmlo2gwPHz97WYwv2eFsPlw250M2Uzw7951EtGnzSiBYAdWEwroxQCt6Kw9XxLVRJv4AyNDEnWxIM41N3e3CiZI3GCVkTRhR8-ahOoys=",
|
||||||
|
# "X-Bogus": "DFSzswjLrEWKNMwBtgzgoUkX95zH",
|
||||||
|
# "_signature": "_02B4Z6wo0000185DMDgAAIDD-Wf0ZmiybIPOQySAAJR4d4"
|
||||||
|
# }
|
||||||
|
# data = {
|
||||||
|
# "DisplayIDList": [
|
||||||
|
# "roseanne3360",
|
||||||
|
# "nikastore.id",
|
||||||
|
# "bg.bara07",
|
||||||
|
# "_24_1234",
|
||||||
|
# "_callsign_shade",
|
||||||
|
# "_caramelihtwo",
|
||||||
|
# "_etthandavidd",
|
||||||
|
# "_itsmeemm",
|
||||||
|
# "_ludi_milojko_11",
|
||||||
|
# "_majesticstyles",
|
||||||
|
# "_marinkaaaa_3333",
|
||||||
|
# "_mjanaque",
|
||||||
|
# "_monami_mode",
|
||||||
|
# "_nailsforqueens",
|
||||||
|
# "_nan4s",
|
||||||
|
# "_nine_live",
|
||||||
|
# "_nixleodeon",
|
||||||
|
# "_ow_yu_",
|
||||||
|
# "_posss",
|
||||||
|
# "_saiji07",
|
||||||
|
# "_storiesbygia",
|
||||||
|
# "_yourazi",
|
||||||
|
# "._.kristenn",
|
||||||
|
# ".1973560",
|
||||||
|
# ".407978",
|
||||||
|
# ".couplecards",
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
# data = json.dumps(data, separators=(',', ':'))
|
||||||
|
# response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
|
||||||
|
#
|
||||||
|
# print(response.text)
|
||||||
|
# print(response)
|
||||||
|
# Z_count = 0
|
||||||
|
# count = 0
|
||||||
|
# start = time.time()
|
||||||
|
#
|
||||||
|
# while True:
|
||||||
|
#
|
||||||
|
# response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
|
||||||
|
# Z_count += 1
|
||||||
|
# if response.text:
|
||||||
|
# print(response.text)
|
||||||
|
# end = time.time()
|
||||||
|
# print("请求了,", count, "次", "花费了", end - start, "秒")
|
||||||
|
# count += 1
|
||||||
|
# if count >= 70:
|
||||||
|
# print("已经成功查询70次")
|
||||||
|
# break
|
||||||
|
# else:
|
||||||
|
#
|
||||||
|
# continue
|
||||||
|
#
|
||||||
|
# print(f"总共请求了{Z_count}次")
|
||||||
|
import time
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"accept": "application/json, text/plain, */*",
|
||||||
|
"accept-language": "zh-CN,zh;q=0.9",
|
||||||
|
"content-type": "application/json",
|
||||||
|
"faction-id": "101796",
|
||||||
|
"origin": "https://live-backstage.tiktok.com",
|
||||||
|
"priority": "u=1, i",
|
||||||
|
"referer": "https://live-backstage.tiktok.com/portal/overview",
|
||||||
|
"sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
|
||||||
|
"sec-ch-ua-mobile": "?0",
|
||||||
|
"sec-ch-ua-platform": "\"Windows\"",
|
||||||
|
"sec-fetch-dest": "empty",
|
||||||
|
"sec-fetch-mode": "cors",
|
||||||
|
"sec-fetch-site": "same-origin",
|
||||||
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
|
||||||
|
"x-appid": "1180",
|
||||||
|
"x-csrf-token": "undefined",
|
||||||
|
"x-language": "zh-Hans",
|
||||||
|
"x-secsdk-csrf-token": "0001000000014c377dafa1df1b5bac3ac8af1cef5aefde81ad5f4def70525f94a0c8d2cf159c1836c44ada2d96f3"
|
||||||
|
}
|
||||||
|
cookies = {
|
||||||
|
# 关键参数1
|
||||||
|
# "s_v_web_id": "verify_m9jpjz5d_WPnZ4RSj_9wVY_4i8C_8S92_vIAYfsalgZ8Q",
|
||||||
|
"s_v_web_id": "verify_m9jt7e2e_4e7QzejO_Httr_4yqQ_8dPB_gdFy61liMmNh",
|
||||||
|
|
||||||
|
"passport_csrf_token": "41002584d346ed70266ccfded87a63b5",
|
||||||
|
"passport_csrf_token_default": "41002584d346ed70266ccfded87a63b5",
|
||||||
|
"d_ticket_backstage": "719b1840fbea4af44bbe4e9064e3c8609443d",
|
||||||
|
"uid_tt_backstage": "eb1f56382f3e2963bc8e6425029651357fb295379501e752b51f47ee33fd3b5f",
|
||||||
|
"uid_tt_ss_backstage": "eb1f56382f3e2963bc8e6425029651357fb295379501e752b51f47ee33fd3b5f",
|
||||||
|
"sid_tt_backstage": "e9001a915acfa5e8d59ce9a1b0ab80c8",
|
||||||
|
"sessionid_backstage": "e9001a915acfa5e8d59ce9a1b0ab80c8",
|
||||||
|
"sessionid_ss_backstage": "e9001a915acfa5e8d59ce9a1b0ab80c8",
|
||||||
|
# 关键参数2
|
||||||
|
# "sid_guard_backstage": "a1e5d072717404f2957bdcc33f03f1c6%7C1744794457%7C5183996%7CSun%2C+15-Jun-2025+09%3A07%3A33+GMT",
|
||||||
|
"sid_guard_backstage": "3a739e9a176acf6c0f32f354ef84caf4%7C1744800570%7C5184000%7CSun%2C+15-Jun-2025+10%3A49%3A30+GMT",
|
||||||
|
"sid_ucp_v1_backstage": "1.0.0-KGVhMTMzNTliYjVlZmZjOWEzMGJkYjI2ZmMyMmM1OWM4MmQ0ODYzNDMKGAiSiNaglIHTtmcQoID-vwYYwTU4AUDrBxADGgZtYWxpdmEiIGU5MDAxYTkxNWFjZmE1ZThkNTljZTlhMWIwYWI4MGM4",
|
||||||
|
"ssid_ucp_v1_backstage": "1.0.0-KGVhMTMzNTliYjVlZmZjOWEzMGJkYjI2ZmMyMmM1OWM4MmQ0ODYzNDMKGAiSiNaglIHTtmcQoID-vwYYwTU4AUDrBxADGgZtYWxpdmEiIGU5MDAxYTkxNWFjZmE1ZThkNTljZTlhMWIwYWI4MGM4",
|
||||||
|
"passport_fe_beating_status": "true",
|
||||||
|
"ttwid": "1%7Cfp5Gb1OQNsxg8aJybfHCK9L9yqtYpRyQ1M3viBOr72I%7C1744797729%7Ceae5426c3f8990a2e8ef03dea9cac4b9dbc704ef0d669e0a92e39692f88472c9",
|
||||||
|
"csrf_session_id": "64b4328196b861edd2cb4767e1e8e6af",
|
||||||
|
"cookie-consent": "{%22optional%22:true%2C%22ga%22:true%2C%22af%22:true%2C%22fbp%22:true%2C%22lip%22:true%2C%22bing%22:true%2C%22ttads%22:true%2C%22reddit%22:true%2C%22hubspot%22:true%2C%22version%22:%22v10%22}",
|
||||||
|
"_ga": "GA1.1.1962967800.1744797925",
|
||||||
|
"_ttp": "2vo47ZF1HgA1kvSWkaHPBMaVr3p.tt.1",
|
||||||
|
"_tt_enable_cookie": "1",
|
||||||
|
"ttcsid": "1744797925882.1.1744797925882",
|
||||||
|
"ttcsid_CQ6FR3RC77U6L0AM21H0": "1744797925879.1.1744797926920",
|
||||||
|
"_ga_GZB380RXJX": "GS1.1.1744797925.1.0.1744797933.0.0.912964856",
|
||||||
|
"msToken": "2pESiV4xZIic204nHe3L03vVnu_KW9SUEoRdA4GOl4IxuCgTC3NgID1BGj4dyW35gxEW-b3UamTrYn9JDTSfn7YVzxf2QiN1Cpa0tWknO4aeswfH2NZXTzV8j5Ht8uSs-3z82Vk="
|
||||||
|
}
|
||||||
|
url = "https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/"
|
||||||
|
params = {
|
||||||
|
"msToken": "2pESiV4xZIic204nHe3L03vVnu_KW9SUEoRdA4GOl4IxuCgTC3NgID1BGj4dyW35gxEW-b3UamTrYn9JDTSfn7YVzxf2QiN1Cpa0tWknO4aeswfH2NZXTzV8j5Ht8uSs-3z82Vk=",
|
||||||
|
"X-Bogus": "DFSzswjLrh8KNMwBtgzDKzkX95mA",
|
||||||
|
"_signature": "_02B4Z6wo00001jUK6VgAAIDCAi4tBw.gE8Y1Cv3AAOrLe1"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"DisplayIDList": [
|
||||||
|
"roseanne3360",
|
||||||
|
"nikastore.id",
|
||||||
|
"bg.bara07",
|
||||||
|
"_24_1234",
|
||||||
|
"_callsign_shade",
|
||||||
|
"_caramelihtwo",
|
||||||
|
"_etthandavidd",
|
||||||
|
"_itsmeemm",
|
||||||
|
"_ludi_milojko_11",
|
||||||
|
"_majesticstyles",
|
||||||
|
"_marinkaaaa_3333",
|
||||||
|
"_mjanaque",
|
||||||
|
"_monami_mode",
|
||||||
|
"_nailsforqueens",
|
||||||
|
"_nan4s",
|
||||||
|
"_nine_live",
|
||||||
|
"_nixleodeon",
|
||||||
|
"_ow_yu_",
|
||||||
|
"_posss",
|
||||||
|
"_saiji07",
|
||||||
|
"_storiesbygia",
|
||||||
|
"_yourazi",
|
||||||
|
"._.kristenn",
|
||||||
|
".1973560",
|
||||||
|
".407978",
|
||||||
|
".couplecards",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
data = json.dumps(data, separators=(',', ':'))
|
||||||
|
response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
|
||||||
|
|
||||||
|
print(response.text)
|
||||||
|
print(response)
|
||||||
|
Z_count = 0
|
||||||
|
count = 0
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
|
response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
|
||||||
|
Z_count += 1
|
||||||
|
if response.text:
|
||||||
|
print(response.text)
|
||||||
|
end = time.time()
|
||||||
|
print("请求了,", count, "次", "花费了", end - start, "秒")
|
||||||
|
count += 1
|
||||||
|
if count >= 70:
|
||||||
|
print("已经成功查询70次")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"总共请求了{Z_count}次")
|
||||||
195
src/assets/img/demos/2025-04/get_batch.py
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
# import base64
|
||||||
|
# import json
|
||||||
|
# import time
|
||||||
|
# import requests
|
||||||
|
# from DrissionPage import ChromiumPage
|
||||||
|
# from DrissionPage import ChromiumOptions
|
||||||
|
# from PIL import Image, ImageDraw
|
||||||
|
# import random
|
||||||
|
# from DrissionPage.common import Actions
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class batch_check_anchor:
|
||||||
|
#
|
||||||
|
# def __init__(self, username, password):
|
||||||
|
# # 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
# self.username = username
|
||||||
|
# self.password = password
|
||||||
|
# start_time = time.time()
|
||||||
|
# co = ChromiumOptions()
|
||||||
|
# # 设置不加载图片、静音
|
||||||
|
# co.mute(True)
|
||||||
|
# co.headless(False)
|
||||||
|
# co.auto_port(True)
|
||||||
|
# self.page = ChromiumPage(co)
|
||||||
|
# self.page.set.window.max()
|
||||||
|
# # self.page.set.cookies.clear()
|
||||||
|
# self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# def get_cookies(self):
|
||||||
|
# while True:
|
||||||
|
# loginele = self.page.ele("@data-id=login")
|
||||||
|
# if loginele:
|
||||||
|
# #
|
||||||
|
# # self.page.set.window.show()
|
||||||
|
# # 点击登录按钮
|
||||||
|
# self.page.ele("@data-id=login").click()
|
||||||
|
# time.sleep(random.random())
|
||||||
|
# # 输入账号
|
||||||
|
# self.page.ele("@class=semi-input semi-input-default").input(self.username, clear=True)
|
||||||
|
# time.sleep(random.random())
|
||||||
|
# # 输入密码
|
||||||
|
# self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(self.password,
|
||||||
|
# clear=True)
|
||||||
|
# # 点击进行登录
|
||||||
|
# time.sleep(random.random())
|
||||||
|
# login = self.page.ele("@data-id=login-primary-button").click()
|
||||||
|
#
|
||||||
|
# if loginele:
|
||||||
|
# break
|
||||||
|
#
|
||||||
|
# while True:
|
||||||
|
# try:
|
||||||
|
# loginele = self.page.ele("@data-id=login", timeout=1)
|
||||||
|
# if not loginele:
|
||||||
|
# print('后台登录成功')
|
||||||
|
# # self.page.set.window.hide()
|
||||||
|
# # self.page.set.timeouts(3)
|
||||||
|
# cookies = self.page.cookies()
|
||||||
|
# cookies_dict = {cookie['name']: cookie['value'] for cookie in cookies}
|
||||||
|
# print(cookies_dict)
|
||||||
|
# return cookies_dict
|
||||||
|
#
|
||||||
|
# time.sleep(0.2)
|
||||||
|
# except:
|
||||||
|
# pass
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# b = batch_check_anchor("wmlcca@tiktok0.xyz","niu995228.")
|
||||||
|
# print(b.get_cookies())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"accept": "application/json, text/plain, */*",
|
||||||
|
"accept-language": "zh-CN,zh;q=0.9",
|
||||||
|
"content-type": "application/json",
|
||||||
|
"faction-id": "101876",
|
||||||
|
"origin": "https://live-backstage.tiktok.com",
|
||||||
|
"priority": "u=1, i",
|
||||||
|
"referer": "https://live-backstage.tiktok.com/portal/overview",
|
||||||
|
"sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
|
||||||
|
"sec-ch-ua-mobile": "?0",
|
||||||
|
"sec-ch-ua-platform": "\"Windows\"",
|
||||||
|
"sec-fetch-dest": "empty",
|
||||||
|
"sec-fetch-mode": "cors",
|
||||||
|
"sec-fetch-site": "same-origin",
|
||||||
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
|
||||||
|
"x-appid": "1180",
|
||||||
|
"x-csrf-token": "undefined",
|
||||||
|
"x-language": "zh-Hans",
|
||||||
|
"x-secsdk-csrf-token": "000100000001a2b7d6e383fd83174d70e9e13de88857bec4f39be23c3cc0747401a9c94949971836beb4628ab5a8"
|
||||||
|
}
|
||||||
|
# cookies = {
|
||||||
|
# "s_v_web_id": "verify_m9jnunys_7L3fxVAj_Uvvc_4SFB_A6IR_0D77iQR4Lt7m",
|
||||||
|
# "passport_csrf_token": "590d7ce7c5c8652da08d29007a87ccb6",
|
||||||
|
# "passport_csrf_token_default": "590d7ce7c5c8652da08d29007a87ccb6",
|
||||||
|
# "d_ticket_backstage": "ba92711982ddeac04b9f98f2efd7007c08a5a",
|
||||||
|
# "uid_tt_backstage": "eb7edba319a8b3a84d255aa11422cdeb15c9c8aaf0f400a677b81d15d1134d2a",
|
||||||
|
# "uid_tt_ss_backstage": "eb7edba319a8b3a84d255aa11422cdeb15c9c8aaf0f400a677b81d15d1134d2a",
|
||||||
|
# "sid_tt_backstage": "b9c7e5436006785411420080dc2d37e3",
|
||||||
|
# "sessionid_backstage": "b9c7e5436006785411420080dc2d37e3",
|
||||||
|
# "sessionid_ss_backstage": "b9c7e5436006785411420080dc2d37e3",
|
||||||
|
# "sid_guard_backstage": "b9c7e5436006785411420080dc2d37e3%7C1744791584%7C5183996%7CSun%2C+15-Jun-2025+08%3A19%3A40+GMT",
|
||||||
|
# "sid_ucp_v1_backstage": "1.0.0-KDQ4NjY3YWVmNThjZDJiZGNmZjA5ZjVkYzE3ODE2YTZiMTM0ZWJkMjIKGAiGiJXQ7fTjjWcQoND9vwYYwTU4AUDrBxADGgZtYWxpdmEiIGI5YzdlNTQzNjAwNjc4NTQxMTQyMDA4MGRjMmQzN2Uz",
|
||||||
|
# "ssid_ucp_v1_backstage": "1.0.0-KDQ4NjY3YWVmNThjZDJiZGNmZjA5ZjVkYzE3ODE2YTZiMTM0ZWJkMjIKGAiGiJXQ7fTjjWcQoND9vwYYwTU4AUDrBxADGgZtYWxpdmEiIGI5YzdlNTQzNjAwNjc4NTQxMTQyMDA4MGRjMmQzN2Uz",
|
||||||
|
# "passport_fe_beating_status": "true",
|
||||||
|
# "ttwid": "1%7Crlwqo-RnA7TPzGAhHAlZM0qUuMLYN0hvXtvIQCB_rG8%7C1744791585%7Cad3d66e43c668ccb03ab28a959819057295614e399739f758a66fd87d2948e77",
|
||||||
|
# "csrf_session_id": "64b4328196b861edd2cb4767e1e8e6af",
|
||||||
|
# "cookie-consent": "{%22optional%22:true%2C%22ga%22:true%2C%22af%22:true%2C%22fbp%22:true%2C%22lip%22:true%2C%22bing%22:true%2C%22ttads%22:true%2C%22reddit%22:true%2C%22hubspot%22:true%2C%22version%22:%22v10%22}",
|
||||||
|
# "_ga": "GA1.1.459162136.1744791630",
|
||||||
|
# "_ga_GZB380RXJX": "GS1.1.1744791630.1.0.1744791630.0.0.621335016",
|
||||||
|
# "_ttp": "2vnrMVBnbyC0vMfL9K5BB9Z6u2o.tt.1",
|
||||||
|
# "_tt_enable_cookie": "1",
|
||||||
|
# "ttcsid": "1744791630532.1.1744791630532",
|
||||||
|
# "FPID": "FPID2.2.QwBg850AKLWqe1V7ktKFgMHXETPYV4c69zBuTI2YROc%3D.1744791630",
|
||||||
|
# "FPAU": "1.2.2009001839.1744791630",
|
||||||
|
# "_fbp": "fb.1.1744791630414.1545554243",
|
||||||
|
# "FPLC": "TPrN8cLVPjh9S9%2FHl5f0n3qn%2FoO58puhQxphpT30nwmqNaJF4bf%2Fp%2F8W%2B79lqOocCcZM4joA2atNh6Rgq8XLNk6RuOapiebbBLlPPVYfMT%2BOIU7ue8X0Eo4cAOVZzA%3D%3D",
|
||||||
|
# "ttcsid_CQ6FR3RC77U6L0AM21H0": "1744791630531.1.1744791632260",
|
||||||
|
# "msToken": "rlgeoikWiiMLU7swOLi_DbXpdPBODXkJXUEai-SnWUYnrplV6caHRU3NwHyvUqF0c5XOYhZgt_CTfKJxX8xGy_OC6qf_wYIKDGaS5jjNUc3xdzzC0x9ZAyu0yRz1I5bEjeUg4M96"
|
||||||
|
# }
|
||||||
|
|
||||||
|
cookies = {'passport_fe_beating_status': 'true', 'ssid_ucp_v1_backstage': '1.0.0-KDcwMjIzNjMzYTU1MDViNzVhZjQwZjc4MDJjNWQ4MzU0MmZkOGFjNzgKGAiGiJXQ7fTjjWcQjNP9vwYYwTU4AUDrBxADGgZtYWxpdmEiIDY4YzI2MGU5NDA0MjM2NzdjZTg3OTk3Y2RhOWM5MTM0', 'msToken': 'OjoXovaKDp-RmE3AZfQiUsROHEQp6quvuDjNnD_nlWrhSK5mtSoaVHfixIAffIr69G3j9rA3PJuN0wk4qnPeFv5TWyS41f9t22XjgoJUQVJmGV9bYvlf3SbEwl1qQ1UjxwX3x8sP', 'sessionid_backstage': '68c260e940423677ce87997cda9c9134', 'sid_guard_backstage': '68c260e940423677ce87997cda9c9134%7C1744791948%7C5183997%7CSun%2C+15-Jun-2025+08%3A25%3A45+GMT', 'ttwid': '1%7CjH6u3QfKY8-doLE8Fi0l-OcHoE9FQN6BVXNoHsgR1rM%7C1744791948%7Ca0db477248e6592c7187aa9ae35d2510d12eeef8a72f6d890ed575b9630eebe3', 'sid_tt_backstage': '68c260e940423677ce87997cda9c9134', 'sessionid_ss_backstage': '68c260e940423677ce87997cda9c9134', 'uid_tt_backstage': '9664c926b9174006e075c864cc536924534b21797ae3e4904a4332c029504951', 's_v_web_id': 'verify_m9jo2k5y_KvKEHrUu_TCKv_4mN5_Bs2U_BjJoJtwBKYfQ', 'd_ticket_backstage': 'e3623469149bc2d303235e0611ffae7e260c0', 'sid_ucp_v1_backstage': '1.0.0-KDcwMjIzNjMzYTU1MDViNzVhZjQwZjc4MDJjNWQ4MzU0MmZkOGFjNzgKGAiGiJXQ7fTjjWcQjNP9vwYYwTU4AUDrBxADGgZtYWxpdmEiIDY4YzI2MGU5NDA0MjM2NzdjZTg3OTk3Y2RhOWM5MTM0', 'passport_csrf_token_default': '09ab6e51d45589114c948d7a434decc0', 'uid_tt_ss_backstage': '9664c926b9174006e075c864cc536924534b21797ae3e4904a4332c029504951', 'passport_csrf_token': '09ab6e51d45589114c948d7a434decc0'}
|
||||||
|
|
||||||
|
url = "https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/"
|
||||||
|
params = {
|
||||||
|
"msToken": "rlgeoikWiiMLU7swOLi_DbXpdPBODXkJXUEai-SnWUYnrplV6caHRU3NwHyvUqF0c5XOYhZgt_CTfKJxX8xGy_OC6qf_wYIKDGaS5jjNUc3xdzzC0x9ZAyu0yRz1I5bEjeUg4M96",
|
||||||
|
"X-Bogus": "DFSzswjLhJXVFFwBtgmuCtkX95zy",
|
||||||
|
"_signature": "_02B4Z6wo00001rpdaoAAAIDCjXmu34pMyca6XX4AAMl0e1"
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
"DisplayIDList": [
|
||||||
|
"roseanne3360",
|
||||||
|
"nikastore.id",
|
||||||
|
"bg.bara07",
|
||||||
|
"_24_1234",
|
||||||
|
"_callsign_shade",
|
||||||
|
"_caramelihtwo",
|
||||||
|
"_etthandavidd",
|
||||||
|
"_itsmeemm",
|
||||||
|
"_ludi_milojko_11",
|
||||||
|
"_majesticstyles",
|
||||||
|
"_marinkaaaa_3333",
|
||||||
|
"_mjanaque",
|
||||||
|
"_monami_mode",
|
||||||
|
"_nailsforqueens",
|
||||||
|
"_nan4s",
|
||||||
|
"_nine_live",
|
||||||
|
"_nixleodeon",
|
||||||
|
"_ow_yu_",
|
||||||
|
"_posss",
|
||||||
|
"_saiji07",
|
||||||
|
"_storiesbygia",
|
||||||
|
"_yourazi",
|
||||||
|
"._.kristenn",
|
||||||
|
".1973560",
|
||||||
|
".407978",
|
||||||
|
".couplecards",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
data = json.dumps(data, separators=(',', ':'))
|
||||||
|
response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
|
||||||
|
|
||||||
|
print(response.text)
|
||||||
|
print(response)
|
||||||
|
Z_count = 0
|
||||||
|
count = 0
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
|
response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
|
||||||
|
time.sleep(2)
|
||||||
|
Z_count += 1
|
||||||
|
if response.text:
|
||||||
|
print(response.text)
|
||||||
|
end = time.time()
|
||||||
|
print("请求了,", count, "次", "花费了", end - start, "秒")
|
||||||
|
count += 1
|
||||||
|
if count >= 70:
|
||||||
|
print("已经成功查询70次")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"总共请求了{Z_count}次")
|
||||||
219
src/assets/img/demos/2025-04/get_page_cookie.py
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import json
|
||||||
|
import random
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
from DrissionPage import ChromiumOptions
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
|
||||||
|
import urllib3
|
||||||
|
|
||||||
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # Python3
|
||||||
|
|
||||||
|
|
||||||
|
class get_page_cookie:
|
||||||
|
|
||||||
|
def __init__(self, username, password, callBack):
|
||||||
|
self.callBack = callBack
|
||||||
|
# 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
start_time = time.time()
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
self.page.set.window.max()
|
||||||
|
# self.page.set.cookies.clear()
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
|
||||||
|
while True:
|
||||||
|
loginele = self.page.ele("@data-id=login")
|
||||||
|
if loginele:
|
||||||
|
#
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# 点击登录按钮
|
||||||
|
self.page.ele("@data-id=login").click()
|
||||||
|
time.sleep(0.5)
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username, clear=True)
|
||||||
|
time.sleep(0.5)
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,
|
||||||
|
clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(0.5)
|
||||||
|
login = self.page.ele("@data-id=login-primary-button").click()
|
||||||
|
|
||||||
|
if loginele:
|
||||||
|
break
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loginele = self.page.ele("@data-id=login", timeout=1)
|
||||||
|
if not loginele:
|
||||||
|
print('后台登录成功')
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
# self.page.set.timeouts(3)
|
||||||
|
cookies = self.page.cookies()
|
||||||
|
cookies_dict = {cookie['name']: cookie['value'] for cookie in cookies}
|
||||||
|
self.cookie1 = cookies_dict
|
||||||
|
self.s_v_web_id = cookies_dict["s_v_web_id"]
|
||||||
|
self.sid_guard_backstage = cookies_dict["sid_guard_backstage"]
|
||||||
|
self.msToken = cookies_dict["msToken"]
|
||||||
|
self.sessionid_backstage = cookies_dict["sessionid_backstage"]
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
print("1.开启线程")
|
||||||
|
threading.Thread(target=self.checkCodeStatus).start()
|
||||||
|
|
||||||
|
def checkCodeStatus(self):
|
||||||
|
print("2.线程启动")
|
||||||
|
self.page.listen.start(
|
||||||
|
'https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
|
||||||
|
while True:
|
||||||
|
time.sleep(1)
|
||||||
|
res = self.page.listen.wait(1)
|
||||||
|
header = res.request.headers
|
||||||
|
|
||||||
|
print("3.监听")
|
||||||
|
self.url = res.request.url
|
||||||
|
self.cookie = res.request.headers.get("Cookie")
|
||||||
|
|
||||||
|
self.x_secsdk_csrf_token = header["x-secsdk-csrf-token"]
|
||||||
|
self.faction_id = header['faction-id']
|
||||||
|
self.x_csrf_token = header['x-csrf-token']
|
||||||
|
|
||||||
|
# headers = {
|
||||||
|
# "accept": "application/json, text/plain, */*",
|
||||||
|
# "accept-language": "zh-CN,zh;q=0.9",
|
||||||
|
# "content-type": "application/json",
|
||||||
|
# # "faction-id": "101796",
|
||||||
|
# "faction-id": self.faction_id,
|
||||||
|
# "origin": "https://live-backstage.tiktok.com",
|
||||||
|
# "priority": "u=1, i",
|
||||||
|
# "referer": "https://live-backstage.tiktok.com/portal/overview",
|
||||||
|
# "sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
|
||||||
|
# "sec-ch-ua-mobile": "?0",
|
||||||
|
# "sec-ch-ua-platform": "\"Windows\"",
|
||||||
|
# "sec-fetch-dest": "empty",
|
||||||
|
# "sec-fetch-mode": "cors",
|
||||||
|
# "sec-fetch-site": "same-origin",
|
||||||
|
# "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
|
||||||
|
# "x-appid": "1180",
|
||||||
|
# # "x-csrf-token": "undefined",
|
||||||
|
# "x-csrf-token": self.x_csrf_token,
|
||||||
|
# "x-language": "zh-Hans",
|
||||||
|
# # "x-secsdk-csrf-token": f"0001000000014c377dafa1df1b5bac3ac8af1cef5aefde81ad5f4def70525f94a0c8d2cf159c1836c44ada2d96f3"
|
||||||
|
# "x-secsdk-csrf-token": self.x_secsdk_csrf_token,
|
||||||
|
# # "Cookie": self.cookie1
|
||||||
|
#
|
||||||
|
# }
|
||||||
|
|
||||||
|
# if response.text:
|
||||||
|
# # print('111', response.text)
|
||||||
|
# if "BaseResp" in response.json():
|
||||||
|
# # print('111',response.text)
|
||||||
|
#
|
||||||
|
# else:
|
||||||
|
# pass
|
||||||
|
|
||||||
|
if "BaseResp" not in res.response.body:
|
||||||
|
print("到此登录完成")
|
||||||
|
self.callBack()
|
||||||
|
self.page.set.window.hide()
|
||||||
|
print("隐藏页面")
|
||||||
|
# else:
|
||||||
|
# print("查询遇到验证码")
|
||||||
|
# self.page.set.window.show()
|
||||||
|
|
||||||
|
# 查询主播
|
||||||
|
def get_anchor_with_ids(self, ids):
|
||||||
|
headers = {
|
||||||
|
"accept": "application/json, text/plain, */*",
|
||||||
|
"accept-language": "zh-CN,zh;q=0.9",
|
||||||
|
"content-type": "application/json",
|
||||||
|
# "faction-id": "101796",
|
||||||
|
"faction-id": self.faction_id,
|
||||||
|
"origin": "https://live-backstage.tiktok.com",
|
||||||
|
"priority": "u=1, i",
|
||||||
|
"referer": "https://live-backstage.tiktok.com/portal/overview",
|
||||||
|
"sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
|
||||||
|
"sec-ch-ua-mobile": "?0",
|
||||||
|
"sec-ch-ua-platform": "\"Windows\"",
|
||||||
|
"sec-fetch-dest": "empty",
|
||||||
|
"sec-fetch-mode": "cors",
|
||||||
|
"sec-fetch-site": "same-origin",
|
||||||
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
|
||||||
|
"x-appid": "1180",
|
||||||
|
# "x-csrf-token": "undefined",
|
||||||
|
"x-csrf-token": self.x_csrf_token,
|
||||||
|
"x-language": "zh-Hans",
|
||||||
|
# "x-secsdk-csrf-token": f"0001000000014c377dafa1df1b5bac3ac8af1cef5aefde81ad5f4def70525f94a0c8d2cf159c1836c44ada2d96f3"
|
||||||
|
"x-secsdk-csrf-token": self.x_secsdk_csrf_token,
|
||||||
|
"Cookie": self.cookie
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
data1 = {
|
||||||
|
"DisplayIDList": ["测试"]
|
||||||
|
}
|
||||||
|
|
||||||
|
data1 = json.dumps(data1, separators=(',', ':'))
|
||||||
|
url1 = "https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/"
|
||||||
|
|
||||||
|
params1 = {
|
||||||
|
"msToken": self.msToken,
|
||||||
|
"X-Bogus": "DFSzswjLrh8KNMwBtgzDKzkX95mA",
|
||||||
|
"_signature": "_02B4Z6wo00001jUK6VgAAIDCAi4tBw.gE8Y1Cv3AAOrLe1"
|
||||||
|
}
|
||||||
|
|
||||||
|
while True:
|
||||||
|
response = requests.post(url1, headers=headers, data=data1, params=params1, cookies=self.cookie1,
|
||||||
|
verify=False)
|
||||||
|
|
||||||
|
print(response.text)
|
||||||
|
if response.text:
|
||||||
|
if "BaseResp" in response.json():
|
||||||
|
self.page.set.window.show()
|
||||||
|
break
|
||||||
|
elif "data" in response.json():
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
url = self.url
|
||||||
|
# url = "https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/"
|
||||||
|
# params = {
|
||||||
|
# "msToken": self.msToken,
|
||||||
|
# "X-Bogus": "DFSzswjLrh8KNMwBtgzDKzkX95mA",
|
||||||
|
# "_signature": "_02B4Z6wo00001jUK6VgAAIDCAi4tBw.gE8Y1Cv3AAOrLe1"
|
||||||
|
# }
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"DisplayIDList": ids
|
||||||
|
}
|
||||||
|
|
||||||
|
data = json.dumps(data, separators=(',', ':'))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
|
# response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
|
||||||
|
response = requests.post(url, headers=headers, data=data)
|
||||||
|
print("1", url)
|
||||||
|
print("2", headers)
|
||||||
|
print("3", data)
|
||||||
|
|
||||||
|
print(response.text, "rrr")
|
||||||
|
|
||||||
|
if response.text:
|
||||||
|
return response.json()
|
||||||
|
else:
|
||||||
|
time.sleep(1)
|
||||||
BIN
src/assets/img/demos/2025-04/logo_super(1).ico
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
src/assets/img/demos/2025-04/logo_super(2).ico
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
src/assets/img/demos/2025-04/logo_super.ico
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
src/assets/img/demos/2025-04/python.zip
Normal file
44
src/assets/img/demos/2025-04/sql.txt
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<select id="manaSearchHostsInfo" resultMap="HostInfoMapper">
|
||||||
|
SELECT
|
||||||
|
h.host_id,
|
||||||
|
h.host_name,
|
||||||
|
h.country,
|
||||||
|
h.hosts_source,
|
||||||
|
hi.info_type as hi_info_type,
|
||||||
|
hi.info_value as hi_info_value,
|
||||||
|
hi.part_month as hi_part_month
|
||||||
|
FROM (
|
||||||
|
SELECT DISTINCT
|
||||||
|
h_inner.host_id,
|
||||||
|
h_inner.host_name,
|
||||||
|
h_inner.country,
|
||||||
|
h_inner.hosts_source
|
||||||
|
FROM hosts h_inner
|
||||||
|
<if test="params.dataStart != null and params.dataEnd != null and params.dataType != null">
|
||||||
|
INNER JOIN hosts_info hi_check ON h_inner.host_id = hi_check.hosts_id
|
||||||
|
AND hi_check.info_type = #{params.dataType}
|
||||||
|
AND CAST(hi_check.info_value AS SIGNED) >= #{params.dataStart}
|
||||||
|
AND CAST(hi_check.info_value AS SIGNED) <![CDATA[ <= ]]> #{params.dataEnd}
|
||||||
|
</if>
|
||||||
|
<where>
|
||||||
|
<if test="params.region != null">
|
||||||
|
AND h_inner.country IN
|
||||||
|
(SELECT country_name FROM country_info WHERE country_group_name = #{params.region})
|
||||||
|
</if>
|
||||||
|
<if test="params.searchTime != null">
|
||||||
|
AND h_inner.update_dt = #{params.searchTime}
|
||||||
|
</if>
|
||||||
|
<if test="params.userId != null">
|
||||||
|
AND h_inner.owner_by = #{params.userId}
|
||||||
|
</if>
|
||||||
|
<if test="params.tenantId != null">
|
||||||
|
AND h_inner.tenant_id = #{params.tenantId}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
LIMIT #{page.size} OFFSET #{page.current}
|
||||||
|
) h
|
||||||
|
INNER JOIN hosts_info hi ON h.host_id = hi.hosts_id
|
||||||
|
<if test="params.searchTime != null">
|
||||||
|
AND hi.part_month = #{params.searchTime}
|
||||||
|
</if>
|
||||||
|
</select>
|
||||||
241
src/assets/img/demos/2025-04/tableaction.py
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
class hosts():
|
||||||
|
'''
|
||||||
|
hosts表元素初始化
|
||||||
|
'''
|
||||||
|
# 主播id
|
||||||
|
hosts__host_id = ' ',
|
||||||
|
# 主播名称
|
||||||
|
hosts__host_name = ' ',
|
||||||
|
# 管理主播的经理
|
||||||
|
hosts__owner_by = ' ',
|
||||||
|
# 是否被管理
|
||||||
|
hosts__belong_yn = ' ',
|
||||||
|
# 主播国家
|
||||||
|
hosts__country = ' ',
|
||||||
|
# 主播来源
|
||||||
|
hosts__hosts_source = ' ',
|
||||||
|
# 主播价值评价
|
||||||
|
hosts__value_level = ' ',
|
||||||
|
# 保留字段1
|
||||||
|
hosts__reserve_1 = ' ',
|
||||||
|
# 保留字段2
|
||||||
|
hosts__reserve_2 = ' ',
|
||||||
|
# 创建时间
|
||||||
|
hosts__create_dt = ' ',
|
||||||
|
# 更新时间
|
||||||
|
hosts__update_dt = ' ',
|
||||||
|
|
||||||
|
class user:
|
||||||
|
'''
|
||||||
|
user表元素初始化
|
||||||
|
'''
|
||||||
|
# 无业务含义,自增主键
|
||||||
|
user__id = ' ',
|
||||||
|
# 员工id
|
||||||
|
user__user_id = ' ',
|
||||||
|
# 员工姓名
|
||||||
|
user__user_name = ' ',
|
||||||
|
# 员工类型(管理员、经理等)
|
||||||
|
user__user_type = ' ',
|
||||||
|
# 上级id,逗号分隔
|
||||||
|
user__manager_by_id = ' ',
|
||||||
|
# 使用权限(是否可用)
|
||||||
|
user__active_yn = ' ',
|
||||||
|
# 使用等级(总部、代理等)
|
||||||
|
user__user_level = ' ',
|
||||||
|
# 租户号
|
||||||
|
user__tenant_id = ' ',
|
||||||
|
# 保留字段1
|
||||||
|
user__reserve_1 = ' ',
|
||||||
|
# 保留字段2
|
||||||
|
user__reserve_2 = ' ',
|
||||||
|
# 创建时间
|
||||||
|
user__create_dt = ' ',
|
||||||
|
# 更新时间
|
||||||
|
user__update_dt = ' ',
|
||||||
|
|
||||||
|
class hosts_info:
|
||||||
|
'''
|
||||||
|
hosts_info表元素初始化
|
||||||
|
'''
|
||||||
|
# 主播id
|
||||||
|
hosts_info__hosts_id = ' ',
|
||||||
|
# 信息类型
|
||||||
|
hosts_info__info_type = ' ',
|
||||||
|
# 信息值
|
||||||
|
hosts_info__info_value = ' ',
|
||||||
|
# 月份数据,做分区
|
||||||
|
hosts_info__part_month = ' ',
|
||||||
|
# 保留字段1
|
||||||
|
hosts_info__reserve_1 = ' ',
|
||||||
|
# 保留字段2
|
||||||
|
hosts_info__reserve_2 = ' ',
|
||||||
|
# 创建时间
|
||||||
|
hosts_info__create_dt = ' ',
|
||||||
|
# 创建人id
|
||||||
|
hosts_info__create_by = ' ',
|
||||||
|
# 更新时间
|
||||||
|
hosts_info__update_dt = ' ',
|
||||||
|
# 更新人id
|
||||||
|
hosts_info__update_by = ' ',
|
||||||
|
|
||||||
|
class param_dict:
|
||||||
|
'''
|
||||||
|
param_dict表元素初始化
|
||||||
|
'''
|
||||||
|
# 主键id,无业务含义
|
||||||
|
param_dict__id = ' ',
|
||||||
|
# 参数类型
|
||||||
|
param_dict__param_type = ' ',
|
||||||
|
# 参数说明
|
||||||
|
param_dict__param_meaning = ' ',
|
||||||
|
# 参数代码
|
||||||
|
param_dict__param_code = ' ',
|
||||||
|
# 参数说明
|
||||||
|
param_dict__param_code_meaning = ' ',
|
||||||
|
# 租户号
|
||||||
|
param_dict__tenant_id = ' ',
|
||||||
|
# 保留字段1
|
||||||
|
param_dict__reserve_1 = ' ',
|
||||||
|
# 保留字段2
|
||||||
|
param_dict__reserve_2 = ' ',
|
||||||
|
# 创建时间
|
||||||
|
param_dict__create_dt = ' ',
|
||||||
|
# 创建人
|
||||||
|
param_dict__create_by = ' ',
|
||||||
|
|
||||||
|
class menus:
|
||||||
|
'''
|
||||||
|
menus表元素初始化
|
||||||
|
'''
|
||||||
|
# 主键id,无业务含义
|
||||||
|
menus__id = ' ',
|
||||||
|
# 按钮id
|
||||||
|
menus__menu_id = ' ',
|
||||||
|
# 按钮业务类型
|
||||||
|
menus__menu_type = ' ',
|
||||||
|
# 按钮名称
|
||||||
|
menus__menu_name = ' ',
|
||||||
|
# 租户号
|
||||||
|
menus__tenant_id = ' ',
|
||||||
|
# 是否激活
|
||||||
|
menus__active_yn = ' ',
|
||||||
|
# 保留字段1
|
||||||
|
menus__reserve_1 = ' ',
|
||||||
|
# 保留字段2
|
||||||
|
menus__reserve_2 = ' ',
|
||||||
|
# 创建时间
|
||||||
|
menus__create_dt = ' ',
|
||||||
|
# 创建人
|
||||||
|
menus__create_by = ' ',
|
||||||
|
# 更新时间
|
||||||
|
menus__update_dt = ' ',
|
||||||
|
# 更新人
|
||||||
|
menus__update_by = ' ',
|
||||||
|
|
||||||
|
class country_info:
|
||||||
|
'''
|
||||||
|
country_info表元素初始化
|
||||||
|
'''
|
||||||
|
# 主键id,无业务含义
|
||||||
|
country_info__id = ' ',
|
||||||
|
# 业务区与地区码
|
||||||
|
country_info__country_group = ' ',
|
||||||
|
# 业务区与地区名称
|
||||||
|
country_info__country_group_name = ' ',
|
||||||
|
# 国家id
|
||||||
|
country_info__country_id = ' ',
|
||||||
|
# 国家名称
|
||||||
|
country_info__country_name = ' ',
|
||||||
|
# 语言
|
||||||
|
country_info__language = ' ',
|
||||||
|
# 语言中文
|
||||||
|
country_info__language_name = ' ',
|
||||||
|
# 保留字段1
|
||||||
|
country_info__reserve_1 = ' ',
|
||||||
|
# 保留字段2
|
||||||
|
country_info__reserve_2 = ' ',
|
||||||
|
# 创建时间
|
||||||
|
country_info__create_dt = ' ',
|
||||||
|
# 创建人id
|
||||||
|
country_info__create_by = ' ',
|
||||||
|
# 更新时间
|
||||||
|
country_info__update_dt = ' ',
|
||||||
|
# 更新人id
|
||||||
|
country_info__update_by = ' ',
|
||||||
|
|
||||||
|
class host_of_fans:
|
||||||
|
'''
|
||||||
|
host_of_fans表元素初始化
|
||||||
|
'''
|
||||||
|
# 业务id,无实际含义
|
||||||
|
host_of_fans__id = ' ',
|
||||||
|
# 使用者id
|
||||||
|
host_of_fans__fans_id = ' ',
|
||||||
|
# 从哪个主播房间导入
|
||||||
|
host_of_fans__find_by_host_id = ' ',
|
||||||
|
# 被分配的员工id
|
||||||
|
host_of_fans__owner_by = ' ',
|
||||||
|
# 价值评估
|
||||||
|
host_of_fans__value_level = ' ',
|
||||||
|
# 国家id
|
||||||
|
host_of_fans__country_id = ' ',
|
||||||
|
# 国家名称
|
||||||
|
host_of_fans__country_name = ' ',
|
||||||
|
# 保留字段1
|
||||||
|
host_of_fans__tenant_id = ' ',
|
||||||
|
# 保留字段2
|
||||||
|
host_of_fans__reserve_2 = ' ',
|
||||||
|
# 创建时间
|
||||||
|
host_of_fans__create_dt = ' ',
|
||||||
|
# 创建人
|
||||||
|
host_of_fans__create_by = ' ',
|
||||||
|
# 更新时间
|
||||||
|
host_of_fans__update_dt = ' ',
|
||||||
|
# 更新人
|
||||||
|
host_of_fans__update_by = ' ',
|
||||||
|
|
||||||
|
# 当表结构改变时,应当要维护该语句
|
||||||
|
def insert_host_of_fans_sql(values):
|
||||||
|
files = "id,fans_id,find_by_host_id,owner_by,value_level,country_id,country_name,tenant_id,reserve_2,create_dt,create_by,update_dt,update_by"
|
||||||
|
sql = f"INSERT INTO host_of_fans ({files}) VALUES ({values})"
|
||||||
|
return sql
|
||||||
|
|
||||||
|
# 当表结构改变时,应当要维护该语句,后续可能要增加修改主播管理人的数据
|
||||||
|
def insertorupdate_hosts_sql(values,country,updatedate):
|
||||||
|
files = 'host_id,host_name,owner_by,belong_yn,country,hosts_source,value_level,tenant_id,reserve_2,create_dt,update_dt'
|
||||||
|
sql = f"INSERT INTO hosts ({files}) VALUES ({values}) ON DUPLICATE KEY UPDATE " \
|
||||||
|
f"country = VALUES(country),update_dt = VALUES(update_dt)"
|
||||||
|
return sql
|
||||||
|
|
||||||
|
# 当表结构改变时,应当要维护该语句
|
||||||
|
def insert_country_info_sql(values):
|
||||||
|
files = "id,country_group,country_group_name,country_id,country_name,language,language_name,reserve_1,reserve_2,create_dt,create_by,update_dt,update_by"
|
||||||
|
sql = f"INSERT INTO country_info ({files}) VALUES ({values})"
|
||||||
|
return sql
|
||||||
|
|
||||||
|
# 当表结构改变时,应当要维护该语句
|
||||||
|
def insert_menus_sql(values):
|
||||||
|
files = "id,menu_id,menu_type,menu_name,tenant_id,active_yn,reserve_1,reserve_2,create_dt,create_by,update_dt,update_by"
|
||||||
|
sql = f"INSERT INTO menus ({files}) VALUES ({values})"
|
||||||
|
return sql
|
||||||
|
|
||||||
|
# 当表结构改变时,应当要维护该语句
|
||||||
|
def insert_param_dict_sql(values):
|
||||||
|
files = "id,param_type,param_meaning,param_code,param_code_meaning,tenant_id,reserve_1,reserve_2,create_dt,create_by"
|
||||||
|
sql = f"INSERT INTO param_dict ({files}) VALUES ({values})"
|
||||||
|
return sql
|
||||||
|
|
||||||
|
# 当表结构改变时,应当要维护该语句,此处应当不传
|
||||||
|
def insertorupdate_hosts_info_sql(values, key, value, hosts_info__create_dt):
|
||||||
|
files = "hosts_id,info_type,info_value,part_month,reserve_1,reserve_2,create_dt,create_by,update_dt,update_by"
|
||||||
|
sql = f"INSERT INTO hosts_info ({files}) VALUES ({values}) ON DUPLICATE KEY UPDATE" \
|
||||||
|
f" info_value = VALUES(info_value),update_dt = VALUES(create_dt)"
|
||||||
|
return sql
|
||||||
|
|
||||||
|
# 当表结构改变时,应当要维护该语句
|
||||||
|
def insert_user_sql(values):
|
||||||
|
files = "id,user_id,user_name,user_type,manager_by_id,active_yn,user_level,tenant_id,reserve_1,reserve_2,create_dt,update_dt"
|
||||||
|
sql = f"INSERT INTO hosts ({files}) VALUES ({values})"
|
||||||
|
return sql
|
||||||
|
|
||||||
113
src/assets/img/demos/2025-04/test1.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import time
|
||||||
|
from retrying import retry
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"accept": "application/json, text/plain, */*",
|
||||||
|
"accept-language": "zh-CN,zh;q=0.9",
|
||||||
|
"content-type": "application/json",
|
||||||
|
"faction-id": "101796",
|
||||||
|
"origin": "https://live-backstage.tiktok.com",
|
||||||
|
"priority": "u=1, i",
|
||||||
|
"referer": "https://live-backstage.tiktok.com/portal/overview",
|
||||||
|
"sec-ch-ua": "\"Google Chrome\";v=\"135\", \"Not-A.Brand\";v=\"8\", \"Chromium\";v=\"135\"",
|
||||||
|
"sec-ch-ua-mobile": "?0",
|
||||||
|
"sec-ch-ua-platform": "\"Windows\"",
|
||||||
|
"sec-fetch-dest": "empty",
|
||||||
|
"sec-fetch-mode": "cors",
|
||||||
|
"sec-fetch-site": "same-origin",
|
||||||
|
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36",
|
||||||
|
"x-appid": "1180",
|
||||||
|
"x-csrf-token": "undefined",
|
||||||
|
"x-language": "zh-Hans",
|
||||||
|
"x-secsdk-csrf-token": "000100000001d9f384e38c9d14525ea0d8c1bc17350eb313dbe6d845a85f1d7bec29bb57e42a1836b4af1c4da5da"
|
||||||
|
}
|
||||||
|
cookies = {
|
||||||
|
"_ga": "GA1.1.448833779.1744041395",
|
||||||
|
"FPID": "FPID2.2.%2B6nT0lCYtTkI1gb5P7uZVN0Jbuib3rku57vhOq52%2BCg%3D.1744041395",
|
||||||
|
"FPAU": "1.2.263606944.1744041395",
|
||||||
|
"_fbp": "fb.1.1744041395282.1072138350",
|
||||||
|
"passport_csrf_token": "41d035222604a0bc54df10cae762032e",
|
||||||
|
"passport_csrf_token_default": "41d035222604a0bc54df10cae762032e",
|
||||||
|
"d_ticket": "57e29296947fabd2646e70bd62414a0bf5414",
|
||||||
|
"tt-target-idc": "useast5",
|
||||||
|
"multi_sids": "7490613412293608478%3A685fa78967fddde3ee38ac63c70ddb65",
|
||||||
|
"cmpl_token": "AgQQAPNSF-RO0rfK75Gtu10n_ZWY7pVVv6kMYNgQaw",
|
||||||
|
"passport_auth_status": "1e5d40345023da2bdbf69f84213ccae5%2C6c68eba7966e629abf50375bd4ebafb5",
|
||||||
|
"passport_auth_status_ss": "1e5d40345023da2bdbf69f84213ccae5%2C6c68eba7966e629abf50375bd4ebafb5",
|
||||||
|
"uid_tt": "9351fd551dbbd03e132339307600dbed6fa061a044fb9a374a44b1e8fe54978d",
|
||||||
|
"uid_tt_ss": "9351fd551dbbd03e132339307600dbed6fa061a044fb9a374a44b1e8fe54978d",
|
||||||
|
"sid_tt": "685fa78967fddde3ee38ac63c70ddb65",
|
||||||
|
"sessionid": "685fa78967fddde3ee38ac63c70ddb65",
|
||||||
|
"sessionid_ss": "685fa78967fddde3ee38ac63c70ddb65",
|
||||||
|
"store-idc": "useast5",
|
||||||
|
"tt-target-idc-sign": "dBNONAXsQJLsZ5zjxrtvUusbU0ZakoP9eQxw6at2yu3-LcIH-w1WAXjN6xClVStBbblFhbm8YgW924k12esL6ohjHRWO0TYX7TxPr5SNnN8GlbNIX-v8KSisYDYWEROcGsj5CfLLvcL_eI6mUb_0LzjHCV6CWTAjEfgRLVJN10EBzL351Ay1jOPz9NGgCE4RJ5vqQMdpXnOx_N3-YJffB6Lfog4sehtsfZKBR-CFhkOe7oItplb-wRbsqlWuS_GvYmr5VkA_G9AjvRo4ZmvwCKyvEmuvyhNpbxiINwFLvdNOVA-RdKqP3qZ8g21irg1bzNQTaryWkgnqcJpQ0FCR_rxANDXAzApWvG_fwT-Q86nSWvY-WjHkfIuW6CQ4OmKmjyT17qoJluiroyeF2WlIDefy2Rpl1q0OvbfiwUUAWaqG1mvZmACGKLFeGoRG4I6gvNWm2Uj0YBprjIhW73bS8ASLE2TgGSI0tJEurOiEy0arNB3GqZ0GtkHqXLs5nezy",
|
||||||
|
"sid_guard": "685fa78967fddde3ee38ac63c70ddb65%7C1744045410%7C15551995%7CSat%2C+04-Oct-2025+17%3A03%3A25+GMT",
|
||||||
|
"sid_ucp_v1": "1.0.0-KGYzNThmNWZjMWQ2NTE0MmQ3NDM3MDRkZjU0M2U0ODhjOTIwZjlkZTUKGgieiKas4qaA-mcQ4orQvwYYsws4AkDxB0gEEAQaB3VzZWFzdDUiIDY4NWZhNzg5NjdmZGRkZTNlZTM4YWM2M2M3MGRkYjY1",
|
||||||
|
"ssid_ucp_v1": "1.0.0-KGYzNThmNWZjMWQ2NTE0MmQ3NDM3MDRkZjU0M2U0ODhjOTIwZjlkZTUKGgieiKas4qaA-mcQ4orQvwYYsws4AkDxB0gEEAQaB3VzZWFzdDUiIDY4NWZhNzg5NjdmZGRkZTNlZTM4YWM2M2M3MGRkYjY1",
|
||||||
|
"_ttp": "2vXFsq88lQe9hoRox4re4hQUiaF.tt.1",
|
||||||
|
"_tt_enable_cookie": "1",
|
||||||
|
"cookie-consent": "{%22optional%22:true%2C%22ga%22:true%2C%22af%22:true%2C%22fbp%22:true%2C%22lip%22:true%2C%22bing%22:true%2C%22ttads%22:true%2C%22reddit%22:true%2C%22hubspot%22:true%2C%22version%22:%22v10%22}",
|
||||||
|
"_ga_LWWPCY99PB": "GS1.1.1744382521.14.1.1744383188.0.0.713318025",
|
||||||
|
"store-country-code": "-",
|
||||||
|
"tt_chain_token": "TTyemrk6OaFJkzbhsum8Ng==",
|
||||||
|
"store-country-sign": "MEIEDLhPca5lDuItTVyQ9QQgSM-4yIu76XEpZptVfSw0EeBMp8u183cgnSCjPBhKFucEEMQqyEIjr4BqM3RA_GSRCtE",
|
||||||
|
"d_ticket_backstage": "97c4d5ed61d94747241582cbed849d68d8cde",
|
||||||
|
"sid_guard_backstage": "3473deca32c2724a8cbb72f4e91d3bb3%7C1744781232%7C5184000%7CSun%2C+15-Jun-2025+05%3A27%3A12+GMT",
|
||||||
|
"uid_tt_backstage": "e9caa200e9330d5aa359a4aea41168a3b2d1a56f13122a4dc5c56e50f5bedda8",
|
||||||
|
"uid_tt_ss_backstage": "e9caa200e9330d5aa359a4aea41168a3b2d1a56f13122a4dc5c56e50f5bedda8",
|
||||||
|
"sid_tt_backstage": "3473deca32c2724a8cbb72f4e91d3bb3",
|
||||||
|
"sessionid_backstage": "3473deca32c2724a8cbb72f4e91d3bb3",
|
||||||
|
"sessionid_ss_backstage": "3473deca32c2724a8cbb72f4e91d3bb3",
|
||||||
|
"sid_ucp_v1_backstage": "1.0.0-KDE0NDZlZTNlMTVhOTBlYzI3NzUyNGE4MzEwMGU1NGMwYTgyNzI0OTEKGAiSiNaglIHTtmcQsP_8vwYYwTU4AUDrBxADGgZtYWxpdmEiIDM0NzNkZWNhMzJjMjcyNGE4Y2JiNzJmNGU5MWQzYmIz",
|
||||||
|
"ssid_ucp_v1_backstage": "1.0.0-KDE0NDZlZTNlMTVhOTBlYzI3NzUyNGE4MzEwMGU1NGMwYTgyNzI0OTEKGAiSiNaglIHTtmcQsP_8vwYYwTU4AUDrBxADGgZtYWxpdmEiIDM0NzNkZWNhMzJjMjcyNGE4Y2JiNzJmNGU5MWQzYmIz",
|
||||||
|
"passport_fe_beating_status": "true",
|
||||||
|
"ttwid": "1%7CteADi5iWWeHjMjjXdIcKOaO44CWbJyrZlT_qXW8P7wc%7C1744781635%7Cf7184bf20feaf5d739a4fde669542d44b76dbd38d4b3460645c67aad7472b116",
|
||||||
|
"s_v_web_id": "verify_m9jhxrlf_RfkgZvzX_khII_4Awa_9Pgo_1nVgYhdqXNie",
|
||||||
|
"csrf_session_id": "8874de872b2755055a1c48760f97ec2e",
|
||||||
|
"_ga_GZB380RXJX": "GS1.1.1744780461.8.1.1744781640.0.0.862808384",
|
||||||
|
"ttcsid": "1744780465820.7.1744781641284",
|
||||||
|
"ttcsid_CQ6FR3RC77U6L0AM21H0": "1744780465816.7.1744781641893",
|
||||||
|
"msToken": "KJc-hIy2Hz-WZQG2KwdNhCxzhocSgR-fp8Y9-Mu2PU0pZNljWXpmQ_6WFHyP0lg5a63iqXWqIPvRBCrKh5jDgyo5sBxFL1WJdJ4_iA6lh_qR6dDRsMOH6xbo3h9u2HSzN10KffNtOw=="
|
||||||
|
}
|
||||||
|
url = "https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/"
|
||||||
|
msToken = "mtzl_MJ-pnO3ChopXcF_2I5a6hgYgIxUr-anVWajHYB3eZzQad8E6JvthPC1TQ4h_T5hQC7_NEmlNpyPIRWuVFRu8vdCYCHGa3F6B8L-mx1vYz7p4fvdtiDACP5f8v__74P4-x1AfaZQhRE="
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"msToken": msToken,
|
||||||
|
"X-Bogus": "DFSzswjLRoaBKlwBtgmhdzkX95m/",
|
||||||
|
"_signature": "_02B4Z6wo00001TB-YIwAAIDAfzpHmnTd6QEwfmQAACwC03"
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
"DisplayIDList": [
|
||||||
|
"刚方法j刚",
|
||||||
|
"等mm安安mm待"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
data = json.dumps(data, separators=(',', ':'))
|
||||||
|
# while True:
|
||||||
|
|
||||||
|
|
||||||
|
# response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
|
||||||
|
# print(response.text)
|
||||||
|
# while True:
|
||||||
|
response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data)
|
||||||
|
|
||||||
|
data = response.text
|
||||||
|
|
||||||
|
|
||||||
|
print(type(response.text),"3333")
|
||||||
|
print(response.text)
|
||||||
|
|
||||||
|
|
||||||
|
dict_data = json.loads(data)
|
||||||
|
|
||||||
|
|
||||||
|
print(dict_data['data'],"222")
|
||||||
|
print(response.text, "111")
|
||||||
|
print(response)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
215
src/assets/img/demos/2025-04/tiktokAPI 1.py
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
import base64
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage import Chromium, ChromiumOptions
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
from DrissionPage.common import Actions
|
||||||
|
from selenium.webdriver import ActionChains
|
||||||
|
from selenium.webdriver.common.devtools.v132.log import clear
|
||||||
|
|
||||||
|
|
||||||
|
class batch_check_anchor:
|
||||||
|
def __init__(self,username,password):
|
||||||
|
# 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
start_time=time.time()
|
||||||
|
false=False
|
||||||
|
true=True
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
#self.page.set.cookies(cookies)
|
||||||
|
#self.page.set.cookies.clear()
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
loginele=self.page.ele('登录')
|
||||||
|
|
||||||
|
|
||||||
|
if loginele:
|
||||||
|
#
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# 点击登录按钮
|
||||||
|
self.page.ele("登录").click()
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username,clear=True)
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(random.random())
|
||||||
|
self.page.ele("@class=semi-button semi-button-primary semi-button-size-large semi-button-block").click()
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loginele=self.page.ele('登录',timeout=1)
|
||||||
|
if not loginele:
|
||||||
|
print('登录成功')
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=5)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
while true:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
time.sleep(1)
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
end_time=time.time()
|
||||||
|
print('初始化完成 耗时:',end_time-start_time)
|
||||||
|
|
||||||
|
def get_ip(self):
|
||||||
|
# 提取代理API接口,获取1个代理IP
|
||||||
|
api_url = "https://dps.kdlapi.com/api/getdps/?secret_id=ohs2d9r6kqdtt2tau900&signature=gktsvou9sd0nq7o09q3ridg70aal97b1&num=1&pt=1&sep=1"
|
||||||
|
|
||||||
|
# 获取API接口返回的代理IP
|
||||||
|
proxy_ip = requests.get(api_url).text
|
||||||
|
|
||||||
|
# 用户名密码认证(私密代理/独享代理)
|
||||||
|
username = "d2400186192"
|
||||||
|
password = "5yv1r337"
|
||||||
|
proxies = {
|
||||||
|
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
|
||||||
|
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
|
||||||
|
}
|
||||||
|
return proxies
|
||||||
|
|
||||||
|
|
||||||
|
# 处理tiktok的验证码
|
||||||
|
def deal_identifying_code(self,b):
|
||||||
|
url = "http://api.jfbym.com/api/YmServer/customApi"
|
||||||
|
data = {
|
||||||
|
## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取
|
||||||
|
"token": "w7hWcZPPOgQG2WTg4os5vD2WnYZ38g9bLWnmBxGUHY4",
|
||||||
|
"type": "30101",
|
||||||
|
"image": b,
|
||||||
|
}
|
||||||
|
_headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
response = requests.request("POST", url, headers=_headers, json=data, proxies=self.get_ip()).json()
|
||||||
|
print(response)
|
||||||
|
return response['data']['data']
|
||||||
|
|
||||||
|
# text:传入邀约
|
||||||
|
def get_anchor(self,text):
|
||||||
|
start_time=time.time()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
inputele.click()
|
||||||
|
inputele.input(text,clear=True)
|
||||||
|
self.page.listen.start('https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
while True:
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
nextele.click()
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
while True:
|
||||||
|
checkele=self.page.ele('确认',timeout=3)
|
||||||
|
if checkele:
|
||||||
|
print("处理验证码")
|
||||||
|
# 发现验证码截图保存到本地
|
||||||
|
|
||||||
|
# 定位元素
|
||||||
|
element = self.page.ele("@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto")
|
||||||
|
# 截取该元素并保存
|
||||||
|
element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
|
||||||
|
time.sleep(random.random())
|
||||||
|
with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
|
||||||
|
# 处理验证码
|
||||||
|
result = self.deal_identifying_code(b)
|
||||||
|
print(result,type(result))
|
||||||
|
# 获取x,y的坐标
|
||||||
|
for i in result.split('|'):
|
||||||
|
x = int(i.split(',')[0])
|
||||||
|
y = int(i.split(',')[1])
|
||||||
|
ac = Actions(self.page)
|
||||||
|
|
||||||
|
ac.move_to(ele_or_loc=element,offset_x=0,offset_y=0).move(x,y).click()
|
||||||
|
|
||||||
|
self.page.ele("@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full").click()
|
||||||
|
while True:
|
||||||
|
checkele=self.page.ele('确认',timeout=3)
|
||||||
|
if not checkele:
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
print('重复点击')
|
||||||
|
res=self.page.listen.wait(1)
|
||||||
|
self.page.listen.stop()
|
||||||
|
while True:
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
backele.click()
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
print('重复点击')
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('报错的原因',e)
|
||||||
|
self.page.refresh()
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=5)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
while True:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
time.sleep(1)
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
end_time=time.time()
|
||||||
|
print('耗时:',end_time-start_time)
|
||||||
|
return res.response.body
|
||||||
|
|
||||||
|
if __name__=='__main__':
|
||||||
|
username = "ph@tiktok0.xyz"
|
||||||
|
password = "zxcvbnm123.."
|
||||||
|
|
||||||
|
b=batch_check_anchor(username,password)#'ph@tiktok0.xyz','zxcvbnm123..'
|
||||||
|
while True:
|
||||||
|
body=b.get_anchor('123456\ngeim123\nn223')
|
||||||
|
print(body)
|
||||||
|
# x=input('输入任意键继续')
|
||||||
|
# if x=='1':
|
||||||
|
# continue
|
||||||
|
# if x=='2':
|
||||||
|
# b.page.set.window.show()
|
||||||
|
# if x=='3':
|
||||||
|
# b.page.set.window.hide()
|
||||||
265
src/assets/img/demos/2025-04/tiktokAPI(1).py
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
import base64
|
||||||
|
import time
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage import ChromiumOptions
|
||||||
|
from PIL import Image,ImageDraw
|
||||||
|
|
||||||
|
import random
|
||||||
|
from DrissionPage.common import Actions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class batch_check_anchor:
|
||||||
|
|
||||||
|
def __init__(self,username,password, callback):
|
||||||
|
# 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
start_time=time.time()
|
||||||
|
false=False
|
||||||
|
true=True
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# co.incognito()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
self.page.set.window.max()
|
||||||
|
#self.page.set.cookies.clear()
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
loginele=self.page.ele("@data-id=login")
|
||||||
|
|
||||||
|
if loginele:
|
||||||
|
#
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# 点击登录按钮
|
||||||
|
self.page.ele("@data-id=login").click()
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username,clear=True)
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(random.random())
|
||||||
|
self.page.ele("@data-id=login-primary-button").click()
|
||||||
|
|
||||||
|
p = self.page.ele('@user-config-ele-id=tiktok-cookie-banner-config').shadow_root
|
||||||
|
b = p.eles('tag:button')
|
||||||
|
if b:
|
||||||
|
b[-1].click()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loginele=self.page.ele("@data-id=login",timeout=1)
|
||||||
|
if not loginele:
|
||||||
|
print('后台登录成功')
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
if callback:
|
||||||
|
callback()
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
|
||||||
|
print("3s 点击 关闭页面")
|
||||||
|
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
page = self.page.ele("@data-id=guide-ok")
|
||||||
|
if page:
|
||||||
|
page.click()
|
||||||
|
|
||||||
|
invite_btn = self.page.ele("@class=semi-button semi-button-primary semi-button-with-icon",timeout=1)
|
||||||
|
|
||||||
|
if not invite_btn:
|
||||||
|
btn = self.page.ele("@data-id=know")
|
||||||
|
if btn:
|
||||||
|
btn.click()
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
while true:
|
||||||
|
time.sleep(0.2)
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
self.get_anchor("测试")
|
||||||
|
print('初始化完成 耗时:',end_time-start_time)
|
||||||
|
|
||||||
|
def get_ip(self):
|
||||||
|
# 提取代理API接口,获取1个代理IP
|
||||||
|
api_url = "https://dps.kdlapi.com/api/getdps/?secret_id=ohs2d9r6kqdtt2tau900&signature=gktsvou9sd0nq7o09q3ridg70aal97b1&num=1&pt=1&sep=1"
|
||||||
|
|
||||||
|
# 获取API接口返回的代理IP
|
||||||
|
proxy_ip = requests.get(api_url).text
|
||||||
|
|
||||||
|
# 用户名密码认证(私密代理/独享代理)
|
||||||
|
username = "d2400186192"
|
||||||
|
password = "5yv1r337"
|
||||||
|
proxies = {
|
||||||
|
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
|
||||||
|
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
|
||||||
|
}
|
||||||
|
return proxies
|
||||||
|
|
||||||
|
# 法国 德国
|
||||||
|
|
||||||
|
# 处理tiktok的验证码
|
||||||
|
def deal_identifying_code(self,b):
|
||||||
|
url = "http://api.jfbym.com/api/YmServer/customApi"
|
||||||
|
data = {
|
||||||
|
## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取
|
||||||
|
"token": "w7hWcZPPOgQG2WTg4os5vD2WnYZ38g9bLWnmBxGUHY4",
|
||||||
|
"type": "30101",
|
||||||
|
"image": b,
|
||||||
|
}
|
||||||
|
_headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
response = requests.request("POST", url, headers=_headers, json=data, proxies=self.get_ip()).json()
|
||||||
|
print(response)
|
||||||
|
return response['data']['data']
|
||||||
|
|
||||||
|
# text:传入邀约
|
||||||
|
def get_anchor(self,text):
|
||||||
|
start_time=time.time()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
inputele.click()
|
||||||
|
inputele.input(text,clear=True)
|
||||||
|
print("点击了测试")
|
||||||
|
self.page.listen.start('https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
|
||||||
|
|
||||||
|
print("监听url")
|
||||||
|
while True:
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
print("点击下一步")
|
||||||
|
nextele.click()
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
|
||||||
|
max_retries = 3 # 定义最大重试次数
|
||||||
|
failure_count = 0 # 初始化失败计数器
|
||||||
|
|
||||||
|
while True:
|
||||||
|
checkele=self.page.ele('@class=TUXButton-content')
|
||||||
|
|
||||||
|
if failure_count >= max_retries:
|
||||||
|
print("验证失败超过3次,终止流程")
|
||||||
|
break #
|
||||||
|
|
||||||
|
if checkele:
|
||||||
|
|
||||||
|
# self.page.set.window.show()
|
||||||
|
print(f"第{failure_count + 1}次尝试处理验证码")
|
||||||
|
# 发现验证码截图保存到本地
|
||||||
|
failure_count += 1
|
||||||
|
# 定位元素
|
||||||
|
element = self.page.ele(
|
||||||
|
"@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto")
|
||||||
|
# 截取该元素并保存
|
||||||
|
element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
|
||||||
|
# time.sleep(random.random())
|
||||||
|
with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
|
||||||
|
# 处理验证码
|
||||||
|
result = self.deal_identifying_code(b)
|
||||||
|
print(result, type(result))
|
||||||
|
|
||||||
|
# 获取x,y的坐标
|
||||||
|
a = 1
|
||||||
|
for i in result.split('|'):
|
||||||
|
a += 1
|
||||||
|
x = int(int(i.split(',')[0]) * (348 / 552))
|
||||||
|
y = int(int(i.split(',')[1]) * (217 / 344))
|
||||||
|
ac = Actions(self.page)
|
||||||
|
|
||||||
|
ac.move_to(ele_or_loc=element, offset_x=0, offset_y=0).move(x, y).click()
|
||||||
|
# print(x,y)
|
||||||
|
# img = Image.open("tiktok_identifying_code.png")
|
||||||
|
# draw = ImageDraw.Draw(img)
|
||||||
|
# draw.ellipse([(x - 5, y - 5), (x + 5, y + 5)], fill='red') # 用红圈标记点击位置
|
||||||
|
# img.save(f"marked_identifying_code{a}.png")
|
||||||
|
self.page.ele(
|
||||||
|
"@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full").click()
|
||||||
|
back_btn = self.page.ele("@data-id=invite-host-back")
|
||||||
|
if back_btn:
|
||||||
|
back_btn.click()
|
||||||
|
continue
|
||||||
|
# else:
|
||||||
|
|
||||||
|
# break
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击1')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
res=self.page.listen.wait(1)
|
||||||
|
self.page.listen.stop()
|
||||||
|
while True:
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
backele.click()
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击2')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('报错的原因',e)
|
||||||
|
|
||||||
|
self.page.refresh()
|
||||||
|
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
else:
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
print('耗时:',end_time-start_time)
|
||||||
|
return res.response.body
|
||||||
|
|
||||||
|
|
||||||
273
src/assets/img/demos/2025-04/tiktokAPI(2).py
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
import base64
|
||||||
|
import time
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage import ChromiumOptions
|
||||||
|
from PIL import Image,ImageDraw
|
||||||
|
|
||||||
|
import random
|
||||||
|
from DrissionPage.common import Actions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class batch_check_anchor:
|
||||||
|
|
||||||
|
def __init__(self,username,password, callback):
|
||||||
|
# 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
start_time=time.time()
|
||||||
|
false=False
|
||||||
|
true=True
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# co.incognito()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
self.page.set.window.max()
|
||||||
|
#self.page.set.cookies.clear()
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
loginele=self.page.ele("@data-id=login")
|
||||||
|
|
||||||
|
cookie = self.page.ele("全部允许")
|
||||||
|
if cookie:
|
||||||
|
|
||||||
|
p = self.page.ele('@user-config-ele-id=tiktok-cookie-banner-config').shadow_root
|
||||||
|
b = p.eles('tag:button')
|
||||||
|
if b:
|
||||||
|
b[-1].click()
|
||||||
|
|
||||||
|
if loginele:
|
||||||
|
#
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# 点击登录按钮
|
||||||
|
self.page.ele("@data-id=login").click()
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username,clear=True)
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(random.random())
|
||||||
|
self.page.ele("@data-id=login-primary-button").click()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loginele=self.page.ele("@data-id=login",timeout=1)
|
||||||
|
if not loginele:
|
||||||
|
print('后台登录成功')
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
if callback:
|
||||||
|
callback()
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
|
||||||
|
print("3s 点击 关闭页面")
|
||||||
|
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
page = self.page.ele("@data-id=guide-ok")
|
||||||
|
if page:
|
||||||
|
page.click()
|
||||||
|
|
||||||
|
invite_btn = self.page.ele("@class=semi-button semi-button-primary semi-button-with-icon",timeout=1)
|
||||||
|
|
||||||
|
if not invite_btn:
|
||||||
|
btn = self.page.ele("@data-id=know")
|
||||||
|
if btn:
|
||||||
|
btn.click()
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
while true:
|
||||||
|
time.sleep(0.2)
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
self.get_anchor("测试")
|
||||||
|
print('初始化完成 耗时:',end_time-start_time)
|
||||||
|
|
||||||
|
def get_ip(self):
|
||||||
|
# 提取代理API接口,获取1个代理IP
|
||||||
|
api_url = "https://dps.kdlapi.com/api/getdps/?secret_id=ohs2d9r6kqdtt2tau900&signature=gktsvou9sd0nq7o09q3ridg70aal97b1&num=1&pt=1&sep=1"
|
||||||
|
|
||||||
|
# 获取API接口返回的代理IP
|
||||||
|
proxy_ip = requests.get(api_url).text
|
||||||
|
|
||||||
|
# 用户名密码认证(私密代理/独享代理)
|
||||||
|
username = "d2400186192"
|
||||||
|
password = "5yv1r337"
|
||||||
|
proxies = {
|
||||||
|
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
|
||||||
|
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
|
||||||
|
}
|
||||||
|
return proxies
|
||||||
|
|
||||||
|
# 法国 德国
|
||||||
|
|
||||||
|
# 处理tiktok的验证码
|
||||||
|
def deal_identifying_code(self,b):
|
||||||
|
url = "http://api.jfbym.com/api/YmServer/customApi"
|
||||||
|
data = {
|
||||||
|
## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取
|
||||||
|
"token": "w7hWcZPPOgQG2WTg4os5vD2WnYZ38g9bLWnmBxGUHY4",
|
||||||
|
"type": "30101",
|
||||||
|
"image": b,
|
||||||
|
}
|
||||||
|
_headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
response = requests.request("POST", url, headers=_headers, json=data, proxies=self.get_ip()).json()
|
||||||
|
print(response)
|
||||||
|
return response['data']['data']
|
||||||
|
|
||||||
|
# text:传入邀约
|
||||||
|
def get_anchor(self,text):
|
||||||
|
start_time=time.time()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
inputele.click()
|
||||||
|
inputele.input(text,clear=True)
|
||||||
|
print("点击了测试")
|
||||||
|
self.page.listen.start('https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
|
||||||
|
|
||||||
|
print("监听url")
|
||||||
|
while True:
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
time.sleep(0.5)
|
||||||
|
print("点击下一步")
|
||||||
|
nextele.click()
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
|
||||||
|
max_retries = 3 # 定义最大重试次数
|
||||||
|
failure_count = 0 # 初始化失败计数器
|
||||||
|
|
||||||
|
while True:
|
||||||
|
checkele=self.page.ele('@class=TUXButton-content')
|
||||||
|
|
||||||
|
if failure_count >= max_retries:
|
||||||
|
print("验证失败超过3次,终止流程")
|
||||||
|
break #
|
||||||
|
|
||||||
|
if checkele:
|
||||||
|
|
||||||
|
# self.page.set.window.show()
|
||||||
|
print(f"第{failure_count + 1}次尝试处理验证码")
|
||||||
|
# 发现验证码截图保存到本地
|
||||||
|
failure_count += 1
|
||||||
|
# 定位元素
|
||||||
|
element = self.page.ele(
|
||||||
|
"@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto")
|
||||||
|
# 截取该元素并保存
|
||||||
|
element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
|
||||||
|
# time.sleep(random.random())
|
||||||
|
with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
|
||||||
|
# 处理验证码
|
||||||
|
result = self.deal_identifying_code(b)
|
||||||
|
print(result, type(result))
|
||||||
|
|
||||||
|
# 获取x,y的坐标
|
||||||
|
a = 1
|
||||||
|
for i in result.split('|'):
|
||||||
|
a += 1
|
||||||
|
x = int(int(i.split(',')[0]) * (348 / 552))
|
||||||
|
y = int(int(i.split(',')[1]) * (217 / 344))
|
||||||
|
ac = Actions(self.page)
|
||||||
|
|
||||||
|
ac.move_to(ele_or_loc=element, offset_x=0, offset_y=0).move(x, y).click()
|
||||||
|
# print(x,y)
|
||||||
|
# img = Image.open("tiktok_identifying_code.png")
|
||||||
|
# draw = ImageDraw.Draw(img)
|
||||||
|
# draw.ellipse([(x - 5, y - 5), (x + 5, y + 5)], fill='red') # 用红圈标记点击位置
|
||||||
|
# img.save(f"marked_identifying_code{a}.png")
|
||||||
|
self.page.ele(
|
||||||
|
"@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full").click()
|
||||||
|
back_btn = self.page.ele("@data-id=invite-host-back")
|
||||||
|
if back_btn:
|
||||||
|
back_btn.click()
|
||||||
|
continue
|
||||||
|
# else:
|
||||||
|
|
||||||
|
# break
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击1')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
res=self.page.listen.wait(1)
|
||||||
|
self.page.listen.stop()
|
||||||
|
while True:
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
backele.click()
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击2')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('报错的原因',e)
|
||||||
|
|
||||||
|
self.page.refresh()
|
||||||
|
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
else:
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
print('耗时:',end_time-start_time)
|
||||||
|
return res.response.body
|
||||||
|
|
||||||
|
|
||||||
271
src/assets/img/demos/2025-04/tiktokAPI(3).py
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
import base64
|
||||||
|
import time
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage import ChromiumOptions
|
||||||
|
from PIL import Image,ImageDraw
|
||||||
|
|
||||||
|
import random
|
||||||
|
from DrissionPage.common import Actions
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class batch_check_anchor:
|
||||||
|
|
||||||
|
def __init__(self,username,password, callback):
|
||||||
|
# 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
start_time=time.time()
|
||||||
|
false=False
|
||||||
|
true=True
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# co.incognito()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
self.page.set.window.max()
|
||||||
|
#self.page.set.cookies.clear()
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
loginele=self.page.ele("@data-id=login")
|
||||||
|
|
||||||
|
cookie = self.page.ele("全部允许")
|
||||||
|
if cookie:
|
||||||
|
|
||||||
|
p = self.page.ele('@user-config-ele-id=tiktok-cookie-banner-config').shadow_root
|
||||||
|
b = p.eles('tag:button')
|
||||||
|
if b:
|
||||||
|
b[-1].click()
|
||||||
|
|
||||||
|
if loginele:
|
||||||
|
#
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# 点击登录按钮
|
||||||
|
self.page.ele("@data-id=login").click()
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username,clear=True)
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(random.random())
|
||||||
|
self.page.ele("@data-id=login-primary-button").click()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loginele=self.page.ele("@data-id=login",timeout=1)
|
||||||
|
if not loginele:
|
||||||
|
print('后台登录成功')
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
if callback:
|
||||||
|
callback()
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
|
||||||
|
print("3s 点击 关闭页面")
|
||||||
|
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
page = self.page.ele("@data-id=guide-ok")
|
||||||
|
if page:
|
||||||
|
page.click()
|
||||||
|
|
||||||
|
invite_btn = self.page.ele("@class=semi-button semi-button-primary semi-button-with-icon",timeout=1)
|
||||||
|
|
||||||
|
if not invite_btn:
|
||||||
|
btn = self.page.ele("@data-id=know")
|
||||||
|
if btn:
|
||||||
|
btn.click()
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
while true:
|
||||||
|
time.sleep(0.2)
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
self.get_anchor("测试")
|
||||||
|
print('初始化完成 耗时:',end_time-start_time)
|
||||||
|
|
||||||
|
def get_ip(self):
|
||||||
|
# 提取代理API接口,获取1个代理IP
|
||||||
|
api_url = "https://dps.kdlapi.com/api/getdps/?secret_id=ohs2d9r6kqdtt2tau900&signature=gktsvou9sd0nq7o09q3ridg70aal97b1&num=1&pt=1&sep=1"
|
||||||
|
|
||||||
|
# 获取API接口返回的代理IP
|
||||||
|
proxy_ip = requests.get(api_url).text
|
||||||
|
|
||||||
|
# 用户名密码认证(私密代理/独享代理)
|
||||||
|
username = "d2400186192"
|
||||||
|
password = "5yv1r337"
|
||||||
|
proxies = {
|
||||||
|
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
|
||||||
|
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
|
||||||
|
}
|
||||||
|
return proxies
|
||||||
|
|
||||||
|
# 法国 德国
|
||||||
|
|
||||||
|
# 处理tiktok的验证码
|
||||||
|
def deal_identifying_code(self,b):
|
||||||
|
url = "http://api.jfbym.com/api/YmServer/customApi"
|
||||||
|
data = {
|
||||||
|
## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取
|
||||||
|
"token": "w7hWcZPPOgQG2WTg4os5vD2WnYZ38g9bLWnmBxGUHY4",
|
||||||
|
"type": "30101",
|
||||||
|
"image": b,
|
||||||
|
}
|
||||||
|
_headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
response = requests.request("POST", url, headers=_headers, json=data, proxies=self.get_ip()).json()
|
||||||
|
print(response)
|
||||||
|
return response['data']['data']
|
||||||
|
|
||||||
|
# text:传入邀约
|
||||||
|
def get_anchor(self,text):
|
||||||
|
start_time=time.time()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
inputele.click()
|
||||||
|
inputele.input(text,clear=True)
|
||||||
|
print("点击了测试")
|
||||||
|
self.page.listen.start('https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
|
||||||
|
|
||||||
|
print("监听url")
|
||||||
|
while True:
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
time.sleep(0.5)
|
||||||
|
print("点击下一步")
|
||||||
|
nextele.click()
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
|
||||||
|
max_retries = 3 # 定义最大重试次数
|
||||||
|
failure_count = 0 # 初始化失败计数器
|
||||||
|
|
||||||
|
while True:
|
||||||
|
checkele=self.page.ele('@class=TUXButton-content')
|
||||||
|
|
||||||
|
if failure_count >= max_retries:
|
||||||
|
print("验证失败超过3次,终止流程")
|
||||||
|
break #
|
||||||
|
|
||||||
|
if checkele:
|
||||||
|
# self.page.set.window.show()
|
||||||
|
print(f"第{failure_count + 1}次尝试处理验证码")
|
||||||
|
# 发现验证码截图保存到本地
|
||||||
|
failure_count += 1
|
||||||
|
# 定位元素
|
||||||
|
element = self.page.ele(
|
||||||
|
"@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto")
|
||||||
|
# 截取该元素并保存
|
||||||
|
element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
# time.sleep(random.random())
|
||||||
|
with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
|
||||||
|
# 处理验证码
|
||||||
|
result = self.deal_identifying_code(b)
|
||||||
|
print(result, type(result))
|
||||||
|
|
||||||
|
# 获取x,y的坐标
|
||||||
|
a = 1
|
||||||
|
for i in result.split('|'):
|
||||||
|
a += 1
|
||||||
|
x = int(int(i.split(',')[0]) * (348 / 552))
|
||||||
|
y = int(int(i.split(',')[1]) * (216.87 / 324))
|
||||||
|
ac = Actions(self.page)
|
||||||
|
|
||||||
|
ac.move_to(ele_or_loc=element, offset_x=0, offset_y=0).move(x, y).click()
|
||||||
|
# print(x,y)
|
||||||
|
# img = Image.open("tiktok_identifying_code.png")
|
||||||
|
# draw = ImageDraw.Draw(img)
|
||||||
|
# draw.ellipse([(x - 5, y - 5), (x + 5, y + 5)], fill='red') # 用红圈标记点击位置
|
||||||
|
# img.save(f"marked_identifying_code{a}.png")
|
||||||
|
self.page.ele(
|
||||||
|
"@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full").click()
|
||||||
|
back_btn = self.page.ele("@data-id=invite-host-back")
|
||||||
|
if back_btn:
|
||||||
|
back_btn.click()
|
||||||
|
continue
|
||||||
|
# else:
|
||||||
|
|
||||||
|
# break
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击1')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
res=self.page.listen.wait(1)
|
||||||
|
self.page.listen.stop()
|
||||||
|
while True:
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
backele.click()
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击2')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('报错的原因',e)
|
||||||
|
|
||||||
|
self.page.refresh()
|
||||||
|
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
else:
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
print('耗时:',end_time-start_time)
|
||||||
|
return res.response.body
|
||||||
|
|
||||||
|
|
||||||
261
src/assets/img/demos/2025-04/tiktokAPI(4).py
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
import base64
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage import ChromiumOptions
|
||||||
|
from PIL import Image,ImageDraw
|
||||||
|
import random
|
||||||
|
from DrissionPage.common import Actions
|
||||||
|
|
||||||
|
class batch_check_anchor:
|
||||||
|
|
||||||
|
def __init__(self,username,password, callback):
|
||||||
|
# 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
start_time=time.time()
|
||||||
|
false=False
|
||||||
|
true=True
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# co.incognito()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
self.page.set.window.max()
|
||||||
|
#self.page.set.cookies.clear()
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
|
||||||
|
loginele=self.page.ele("@data-id=login")
|
||||||
|
|
||||||
|
cookie = self.page.ele("全部允许")
|
||||||
|
if cookie:
|
||||||
|
|
||||||
|
p = self.page.ele('@user-config-ele-id=tiktok-cookie-banner-config').shadow_root
|
||||||
|
b = p.eles('tag:button')
|
||||||
|
if b:
|
||||||
|
b[-1].click()
|
||||||
|
|
||||||
|
if loginele:
|
||||||
|
#
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# 点击登录按钮
|
||||||
|
self.page.ele("@data-id=login").click()
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username,clear=True)
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(random.random())
|
||||||
|
self.page.ele("@data-id=login-primary-button").click()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loginele=self.page.ele("@data-id=login",timeout=1)
|
||||||
|
if not loginele:
|
||||||
|
print('后台登录成功')
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
if callback:
|
||||||
|
callback()
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
|
||||||
|
print("3s 点击 关闭页面")
|
||||||
|
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
page = self.page.ele("@data-id=guide-ok")
|
||||||
|
if page:
|
||||||
|
page.click()
|
||||||
|
|
||||||
|
invite_btn = self.page.ele("@class=semi-button semi-button-primary semi-button-with-icon",timeout=1)
|
||||||
|
|
||||||
|
if not invite_btn:
|
||||||
|
btn = self.page.ele("@data-id=know")
|
||||||
|
if btn:
|
||||||
|
btn.click()
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
while true:
|
||||||
|
time.sleep(0.2)
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
self.get_anchor("测试")
|
||||||
|
print('初始化完成 耗时:',end_time-start_time)
|
||||||
|
|
||||||
|
def get_ip(self):
|
||||||
|
# 提取代理API接口,获取1个代理IP
|
||||||
|
api_url = "https://dps.kdlapi.com/api/getdps/?secret_id=ohs2d9r6kqdtt2tau900&signature=gktsvou9sd0nq7o09q3ridg70aal97b1&num=1&pt=1&sep=1"
|
||||||
|
|
||||||
|
# 获取API接口返回的代理IP
|
||||||
|
proxy_ip = requests.get(api_url).text
|
||||||
|
|
||||||
|
# 用户名密码认证(私密代理/独享代理)
|
||||||
|
username = "d2400186192"
|
||||||
|
password = "5yv1r337"
|
||||||
|
proxies = {
|
||||||
|
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
|
||||||
|
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
|
||||||
|
}
|
||||||
|
return proxies
|
||||||
|
|
||||||
|
# 法国 德国
|
||||||
|
|
||||||
|
# 处理tiktok的验证码
|
||||||
|
def deal_identifying_code(self,b):
|
||||||
|
url = "http://api.jfbym.com/api/YmServer/customApi"
|
||||||
|
data = {
|
||||||
|
## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取
|
||||||
|
"token": "w7hWcZPPOgQG2WTg4os5vD2WnYZ38g9bLWnmBxGUHY4",
|
||||||
|
"type": "30101",
|
||||||
|
"image": b,
|
||||||
|
}
|
||||||
|
_headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
response = requests.request("POST", url, headers=_headers, json=data, proxies=self.get_ip()).json()
|
||||||
|
print(response)
|
||||||
|
return response['data']['data']
|
||||||
|
|
||||||
|
# text:传入邀约
|
||||||
|
def get_anchor(self,text):
|
||||||
|
start_time=time.time()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
inputele.click()
|
||||||
|
inputele.input(text,clear=True)
|
||||||
|
print("点击了测试")
|
||||||
|
self.page.listen.start('https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
|
||||||
|
|
||||||
|
print("监听url")
|
||||||
|
while True:
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
time.sleep(0.5)
|
||||||
|
print("点击下一步")
|
||||||
|
nextele.click()
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
|
||||||
|
max_retries = 3 # 定义最大重试次数
|
||||||
|
failure_count = 0 # 初始化失败计数器
|
||||||
|
|
||||||
|
# while True:
|
||||||
|
# checkele=self.page.ele('@class=TUXButton-content')
|
||||||
|
#
|
||||||
|
# if failure_count >= max_retries:
|
||||||
|
# print("验证失败超过3次,终止流程")
|
||||||
|
# break #
|
||||||
|
#
|
||||||
|
# if checkele:
|
||||||
|
# # self.page.set.window.show()
|
||||||
|
# print(f"第{failure_count + 1}次尝试处理验证码")
|
||||||
|
# # 发现验证码截图保存到本地
|
||||||
|
# failure_count += 1
|
||||||
|
# # 定位元素
|
||||||
|
# element = self.page.ele(
|
||||||
|
# "@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto")
|
||||||
|
# # 截取该元素并保存
|
||||||
|
# element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
# # time.sleep(random.random())
|
||||||
|
# with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
# b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
#
|
||||||
|
# # 处理验证码
|
||||||
|
# result = self.deal_identifying_code(b)
|
||||||
|
# print(result, type(result))
|
||||||
|
#
|
||||||
|
# # 获取x,y的坐标
|
||||||
|
# a = 1
|
||||||
|
# for i in result.split('|'):
|
||||||
|
# a += 1
|
||||||
|
# x = int(int(i.split(',')[0]) * (348 / 552))
|
||||||
|
# y = int(int(i.split(',')[1]) * (216.87 / 324))
|
||||||
|
# ac = Actions(self.page)
|
||||||
|
#
|
||||||
|
# ac.move_to(ele_or_loc=element, offset_x=0, offset_y=0).move(x, y).click()
|
||||||
|
# # print(x,y)
|
||||||
|
# # img = Image.open("tiktok_identifying_code.png")
|
||||||
|
# # draw = ImageDraw.Draw(img)
|
||||||
|
# # draw.ellipse([(x - 5, y - 5), (x + 5, y + 5)], fill='red') # 用红圈标记点击位置
|
||||||
|
# # img.save(f"marked_identifying_code{a}.png")
|
||||||
|
# self.page.ele(
|
||||||
|
# "@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full").click()
|
||||||
|
# back_btn = self.page.ele("@data-id=invite-host-back")
|
||||||
|
# if back_btn:
|
||||||
|
# back_btn.click()
|
||||||
|
# continue
|
||||||
|
# else:
|
||||||
|
|
||||||
|
# break
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击1')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
res=self.page.listen.wait(1)
|
||||||
|
self.page.listen.stop()
|
||||||
|
while True:
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
backele.click()
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击2')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('报错的原因',e)
|
||||||
|
|
||||||
|
self.page.refresh()
|
||||||
|
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
else:
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
print('耗时:',end_time-start_time)
|
||||||
|
return res.response.body
|
||||||
|
|
||||||
|
|
||||||
355
src/assets/img/demos/2025-04/tiktokAPI(5).py
Normal file
@@ -0,0 +1,355 @@
|
|||||||
|
|
||||||
|
import base64
|
||||||
|
import time
|
||||||
|
import requests
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage import ChromiumOptions
|
||||||
|
from PIL import Image,ImageDraw
|
||||||
|
import random
|
||||||
|
from DrissionPage.common import Actions
|
||||||
|
|
||||||
|
class batch_check_anchor:
|
||||||
|
|
||||||
|
def __init__(self,username,password, callback):
|
||||||
|
# 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
start_time=time.time()
|
||||||
|
false=False
|
||||||
|
true=True
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# co.incognito()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
self.page.set.window.max()
|
||||||
|
#self.page.set.cookies.clear()
|
||||||
|
self.page.set.timeouts(1)
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
loginele=self.page.ele("@data-id=login")
|
||||||
|
|
||||||
|
print("1 检测登录按钮",loginele)
|
||||||
|
start_time1 = time.time()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end_time1 = time.time()
|
||||||
|
print('1.初始化完成 耗时:', end_time1 - start_time1)
|
||||||
|
|
||||||
|
if loginele:
|
||||||
|
|
||||||
|
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# 点击登录按钮
|
||||||
|
# self.page.ele("@data-id=login").click()
|
||||||
|
loginele.click()
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username,clear=True)
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(random.random())
|
||||||
|
self.page.ele("@data-id=login-primary-button").click()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
loginele=self.page.ele("@data-id=login",timeout=1)
|
||||||
|
if not loginele:
|
||||||
|
print('3 后台登录成功')
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=3)
|
||||||
|
|
||||||
|
print("3s 点击 关闭页面")
|
||||||
|
|
||||||
|
if ele:
|
||||||
|
print("5 点击旧页面的窗口")
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
page = self.page.ele("@data-id=guide-ok")
|
||||||
|
if page:
|
||||||
|
print("6 点击新页面的窗口")
|
||||||
|
page.click()
|
||||||
|
|
||||||
|
invite_btn = self.page.wait.ele_displayed("@class=semi-button semi-button-primary semi-button-with-icon",timeout=3)
|
||||||
|
print("invite",invite_btn)
|
||||||
|
if not invite_btn:
|
||||||
|
print("7 没有邀请主播按钮")
|
||||||
|
a = time.time()
|
||||||
|
btn = self.page.ele("@data-id=know")
|
||||||
|
b = time.time()
|
||||||
|
|
||||||
|
print(f"第七步: 7{b-a}")
|
||||||
|
if btn:
|
||||||
|
print("8 点击新页面的右上角窗口")
|
||||||
|
btn.click()
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
print("9 点击切换到旧页面")
|
||||||
|
check_btn.click()
|
||||||
|
while true:
|
||||||
|
time.sleep(0.2)
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn',timeout=3)
|
||||||
|
print("10 检测邀请主播的按钮ele",ele)
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
print("11 点击邀请主播")
|
||||||
|
time.sleep(0.5)
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
print("12 调用另一个方法")
|
||||||
|
self.get_anchor("测试")
|
||||||
|
if callback:
|
||||||
|
callback()
|
||||||
|
print('初始化完成 耗时:',end_time-start_time)
|
||||||
|
|
||||||
|
def get_ip(self):
|
||||||
|
# 提取代理API接口,获取1个代理IP
|
||||||
|
api_url = "https://dps.kdlapi.com/api/getdps/?secret_id=ohs2d9r6kqdtt2tau900&signature=gktsvou9sd0nq7o09q3ridg70aal97b1&num=1&pt=1&sep=1"
|
||||||
|
|
||||||
|
# 获取API接口返回的代理IP
|
||||||
|
proxy_ip = requests.get(api_url).text
|
||||||
|
|
||||||
|
# 用户名密码认证(私密代理/独享代理)
|
||||||
|
username = "d2400186192"
|
||||||
|
password = "5yv1r337"
|
||||||
|
proxies = {
|
||||||
|
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
|
||||||
|
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
|
||||||
|
}
|
||||||
|
return proxies
|
||||||
|
|
||||||
|
# 法国 德国
|
||||||
|
|
||||||
|
# 处理tiktok的验证码
|
||||||
|
def deal_identifying_code(self,b):
|
||||||
|
url = "http://api.jfbym.com/api/YmServer/customApi"
|
||||||
|
data = {
|
||||||
|
## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取
|
||||||
|
"token": "w7hWcZPPOgQG2WTg4os5vD2WnYZ38g9bLWnmBxGUHY4",
|
||||||
|
"type": "30101",
|
||||||
|
"image": b,
|
||||||
|
}
|
||||||
|
_headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
response = requests.request("POST", url, headers=_headers, json=data, proxies=self.get_ip()).json()
|
||||||
|
print(response)
|
||||||
|
return response['data']['data']
|
||||||
|
|
||||||
|
# text:传入邀约
|
||||||
|
def get_anchor(self,text):
|
||||||
|
start_time=time.time()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
|
||||||
|
if inputele:
|
||||||
|
print("13 点击窗口进行输入测试")
|
||||||
|
inputele.click()
|
||||||
|
inputele.input(text,clear=True)
|
||||||
|
print("14 点击了测试")
|
||||||
|
self.page.listen.start('https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
|
||||||
|
print("监听url")
|
||||||
|
|
||||||
|
cookie = self.page.ele("全部允许", timeout=3)
|
||||||
|
print("2 检测全部允许按钮")
|
||||||
|
if cookie:
|
||||||
|
|
||||||
|
p = self.page.ele('@user-config-ele-id=tiktok-cookie-banner-config').shadow_root
|
||||||
|
b = p.eles('tag:button')
|
||||||
|
if b:
|
||||||
|
b[-1].click()
|
||||||
|
print("2.1 点击全部允许按钮")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
time.sleep(1)
|
||||||
|
print("15 点击下一步")
|
||||||
|
nextele.click()
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
|
||||||
|
max_retries = 1 # 定义最大重试次数
|
||||||
|
failure_count1 = 0 # 初始化失败计数器
|
||||||
|
failure_count2 = 0 # 初始化失败计数器
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
while True:
|
||||||
|
checkele = self.page.ele('@class=TUXButton-label',timeout=3)
|
||||||
|
|
||||||
|
if failure_count1 >= max_retries:
|
||||||
|
print(f"验证失败超过{failure_count1}次,终止流程")
|
||||||
|
break #
|
||||||
|
|
||||||
|
if checkele:
|
||||||
|
# self.page.set.window.show()
|
||||||
|
print(f"16 第一种方案{failure_count1 + 1}次尝试处理验证码")
|
||||||
|
# 发现验证码截图保存到本地
|
||||||
|
failure_count1 += 1
|
||||||
|
# 定位元素
|
||||||
|
element = self.page.ele(
|
||||||
|
"@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto",timeout=3)
|
||||||
|
# 截取该元素并保存
|
||||||
|
element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
# time.sleep(random.random())
|
||||||
|
with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
|
||||||
|
# 处理验证码
|
||||||
|
result = self.deal_identifying_code(b)
|
||||||
|
print(result, type(result))
|
||||||
|
|
||||||
|
# 获取x,y的坐标
|
||||||
|
for i in result.split('|'):
|
||||||
|
# x = int(int(i.split(',')[0]) * (363 / 552))
|
||||||
|
# y = int(int(i.split(',')[1]) * (236 / 344))
|
||||||
|
|
||||||
|
x = int(int(i.split(',')[0]) )
|
||||||
|
y = int(int(i.split(',')[1]) )
|
||||||
|
print(x,y)
|
||||||
|
ac = Actions(self.page)
|
||||||
|
|
||||||
|
ac.move_to(ele_or_loc=element, offset_x=0, offset_y=0).move(x, y).click()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
yzm = self.page.ele(
|
||||||
|
"@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full",timeout=3)
|
||||||
|
|
||||||
|
if yzm:
|
||||||
|
yzm.click()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
while True:
|
||||||
|
checkele=self.page.ele('@class=TUXButton-label',timeout=3)
|
||||||
|
print(checkele,"12231313")
|
||||||
|
if failure_count2 >= max_retries:
|
||||||
|
print(f"验证失败超过{failure_count2}次,终止流程")
|
||||||
|
break #
|
||||||
|
if checkele:
|
||||||
|
# self.page.set.window.show()
|
||||||
|
print(f"17 第二种方案{failure_count2 + 1}次尝试处理验证码")
|
||||||
|
# 发现验证码截图保存到本地
|
||||||
|
failure_count2 += 1
|
||||||
|
# 定位元素
|
||||||
|
element = self.page.ele(
|
||||||
|
"@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto",timeout=3)
|
||||||
|
# 截取该元素并保存
|
||||||
|
element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
# time.sleep(random.random())
|
||||||
|
with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
|
||||||
|
# 处理验证码
|
||||||
|
result = self.deal_identifying_code(b)
|
||||||
|
print(result, type(result))
|
||||||
|
|
||||||
|
# 获取x,y的坐标
|
||||||
|
for i in result.split('|'):
|
||||||
|
x = int(int(i.split(',')[0]) * (363 / 552))
|
||||||
|
y = int(int(i.split(',')[1]) * (236 / 344))
|
||||||
|
# x = int(int(i.split(',')[0]) )
|
||||||
|
# y = int(int(i.split(',')[1]) )
|
||||||
|
ac = Actions(self.page)
|
||||||
|
|
||||||
|
ac.move_to(ele_or_loc=element, offset_x=0, offset_y=0).move(x, y).click()
|
||||||
|
|
||||||
|
yzm = self.page.ele(
|
||||||
|
"@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full",timeout=3)
|
||||||
|
|
||||||
|
if yzm:
|
||||||
|
yzm.click()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
checkele = self.page.ele(
|
||||||
|
"@class=TUXButton-content",timeout=3)
|
||||||
|
if checkele:
|
||||||
|
print("18 验证码还在 继续验证")
|
||||||
|
failure_count1 = 0 # 初始化失败计数器
|
||||||
|
failure_count2 = 0
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
print("19 验证码识别完毕 跳出")
|
||||||
|
break
|
||||||
|
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击1')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
res=self.page.listen.wait(1)
|
||||||
|
self.page.listen.stop()
|
||||||
|
while True:
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
backele.click()
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
print('重复点击2')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('报错的原因',e)
|
||||||
|
|
||||||
|
self.page.refresh()
|
||||||
|
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
else:
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn',timeout=3)
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
print('耗时:',end_time-start_time)
|
||||||
|
return res.response.body
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
228
src/assets/img/demos/2025-04/tiktokAPI.py
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
import base64
|
||||||
|
import requests
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage import ChromiumOptions
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
from DrissionPage.common import Actions
|
||||||
|
|
||||||
|
class batch_check_anchor:
|
||||||
|
|
||||||
|
def __init__(self,username,password, callback):
|
||||||
|
# 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
start_time=time.time()
|
||||||
|
false=False
|
||||||
|
true=True
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# co.incognito()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
# 全局隐藏窗口
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
#self.page.set.cookies.clear()
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
loginele=self.page.ele("@data-id=login")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# btn = self.page.ele("全部允许")
|
||||||
|
# if btn:
|
||||||
|
# print("123456")
|
||||||
|
#
|
||||||
|
# btn.click()
|
||||||
|
if loginele:
|
||||||
|
#
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# 点击登录按钮
|
||||||
|
self.page.ele("@data-id=login").click()
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username,clear=True)
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(random.random())
|
||||||
|
self.page.ele("@class=semi-button semi-button-primary semi-button-size-large semi-button-block").click()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loginele=self.page.ele("@data-id=login",timeout=1)
|
||||||
|
if not loginele:
|
||||||
|
print('后台登录成功')
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
if callback:
|
||||||
|
callback()
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
|
||||||
|
print("3s 点击 关闭页面")
|
||||||
|
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
invite_btn = self.page.ele("@class=semi-button semi-button-primary semi-button-with-icon",timeout=1)
|
||||||
|
|
||||||
|
if not invite_btn:
|
||||||
|
btn = self.page.ele("@data-id=know")
|
||||||
|
if btn:
|
||||||
|
btn.click()
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
while true:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
time.sleep(1)
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
self.get_anchor("测试")
|
||||||
|
print('初始化完成 耗时:',end_time-start_time)
|
||||||
|
|
||||||
|
def get_ip(self):
|
||||||
|
# 提取代理API接口,获取1个代理IP
|
||||||
|
api_url = "https://dps.kdlapi.com/api/getdps/?secret_id=ohs2d9r6kqdtt2tau900&signature=gktsvou9sd0nq7o09q3ridg70aal97b1&num=1&pt=1&sep=1"
|
||||||
|
|
||||||
|
# 获取API接口返回的代理IP
|
||||||
|
proxy_ip = requests.get(api_url).text
|
||||||
|
|
||||||
|
# 用户名密码认证(私密代理/独享代理)
|
||||||
|
username = "d2400186192"
|
||||||
|
password = "5yv1r337"
|
||||||
|
proxies = {
|
||||||
|
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
|
||||||
|
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
|
||||||
|
}
|
||||||
|
return proxies
|
||||||
|
|
||||||
|
|
||||||
|
# 处理tiktok的验证码
|
||||||
|
def deal_identifying_code(self,b):
|
||||||
|
url = "http://api.jfbym.com/api/YmServer/customApi"
|
||||||
|
data = {
|
||||||
|
## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取
|
||||||
|
"token": "w7hWcZPPOgQG2WTg4os5vD2WnYZ38g9bLWnmBxGUHY4",
|
||||||
|
"type": "30101",
|
||||||
|
"image": b,
|
||||||
|
}
|
||||||
|
_headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
response = requests.request("POST", url, headers=_headers, json=data, proxies=self.get_ip()).json()
|
||||||
|
print(response)
|
||||||
|
return response['data']['data']
|
||||||
|
|
||||||
|
# text:传入邀约
|
||||||
|
def get_anchor(self,text):
|
||||||
|
start_time=time.time()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
inputele.click()
|
||||||
|
inputele.input(text,clear=True)
|
||||||
|
self.page.listen.start('https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
while True:
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
nextele.click()
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
while True:
|
||||||
|
checkele=self.page.ele('确认')
|
||||||
|
if checkele:
|
||||||
|
|
||||||
|
print("请手动点击验证码")
|
||||||
|
# # self.page.set.window.show()
|
||||||
|
# print("处理验证码")
|
||||||
|
# # 发现验证码截图保存到本地
|
||||||
|
#
|
||||||
|
# # 定位元素
|
||||||
|
# element = self.page.ele("@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto")
|
||||||
|
# # 截取该元素并保存
|
||||||
|
# element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
#
|
||||||
|
# time.sleep(random.random())
|
||||||
|
# with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
# b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
#
|
||||||
|
# # 处理验证码
|
||||||
|
# result = self.deal_identifying_code(b)
|
||||||
|
# print(result,type(result))
|
||||||
|
# # 获取x,y的坐标
|
||||||
|
# for i in result.split('|'):
|
||||||
|
# x = int(i.split(',')[0])
|
||||||
|
# y = int(i.split(',')[1])
|
||||||
|
# ac = Actions(self.page)
|
||||||
|
#
|
||||||
|
# ac.move_to(ele_or_loc=element,offset_x=0,offset_y=0).move(x,y).click()
|
||||||
|
#
|
||||||
|
# self.page.ele("@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full").click()
|
||||||
|
# back_btn = self.page.ele("@data-id=invite-host-back")
|
||||||
|
# if back_btn:
|
||||||
|
# back_btn.click()
|
||||||
|
# time.sleep(10)
|
||||||
|
# # self.page.set.window.hide()
|
||||||
|
# while True:
|
||||||
|
# checkele=self.page.ele('确认')
|
||||||
|
# if not checkele:
|
||||||
|
# # self.page.set.window.hide()
|
||||||
|
# break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
# continue
|
||||||
|
break
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
print('重复点击')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
res=self.page.listen.wait(1)
|
||||||
|
self.page.listen.stop()
|
||||||
|
while True:
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
backele.click()
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
print('重复点击')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('报错的原因',e)
|
||||||
|
self.page.refresh()
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
while True:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
time.sleep(1)
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
print('耗时:',end_time-start_time)
|
||||||
|
return res.response.body
|
||||||
431
src/assets/img/demos/2025-04/tiktokApiCopy.py
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
# import base64
|
||||||
|
# import requests
|
||||||
|
# from DrissionPage import ChromiumPage
|
||||||
|
# from DrissionPage import ChromiumOptions
|
||||||
|
# import time
|
||||||
|
# import random
|
||||||
|
# from DrissionPage.common import Actions
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# class batch_check_anchor_copy:
|
||||||
|
#
|
||||||
|
# def __init__(self,username,password, callback):
|
||||||
|
# from infos.autohostinfo import checkAnchorObjs
|
||||||
|
# # 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
# start_time=time.time()
|
||||||
|
# false=False
|
||||||
|
# true=True
|
||||||
|
# co = ChromiumOptions()
|
||||||
|
# # 设置不加载图片、静音
|
||||||
|
# co.mute(True)
|
||||||
|
# co.headless(False)
|
||||||
|
# co.auto_port(True)
|
||||||
|
# self.page = ChromiumPage(co)
|
||||||
|
#
|
||||||
|
# #self.page.set.cookies.clear()
|
||||||
|
# self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
# loginele=self.page.ele('登录')
|
||||||
|
#
|
||||||
|
# if loginele:
|
||||||
|
# #
|
||||||
|
# # self.page.set.window.show()
|
||||||
|
# # 点击登录按钮
|
||||||
|
# self.page.ele("登录").click()
|
||||||
|
# time.sleep(random.random())
|
||||||
|
# # 输入账号
|
||||||
|
# self.page.ele("@class=semi-input semi-input-default").input(username,clear=True)
|
||||||
|
# time.sleep(random.random())
|
||||||
|
# # 输入密码
|
||||||
|
# self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,clear=True)
|
||||||
|
# # 点击进行登录
|
||||||
|
# time.sleep(random.random())
|
||||||
|
# self.page.ele("@class=semi-button semi-button-primary semi-button-size-large semi-button-block").click()
|
||||||
|
#
|
||||||
|
# while True:
|
||||||
|
# try:
|
||||||
|
# loginele=self.page.ele('登录',timeout=1)
|
||||||
|
# if not loginele:
|
||||||
|
# print('后台登录成功')
|
||||||
|
# # self.page.set.window.hide()
|
||||||
|
# if callback:
|
||||||
|
# callback()
|
||||||
|
# break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
# except:
|
||||||
|
# pass
|
||||||
|
# ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=5)
|
||||||
|
# if ele:
|
||||||
|
# ele.click()
|
||||||
|
#
|
||||||
|
# while true:
|
||||||
|
# ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
# try:
|
||||||
|
# if ele:
|
||||||
|
# ele.click()
|
||||||
|
# time.sleep(1)
|
||||||
|
# inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
# if inputele:
|
||||||
|
# break
|
||||||
|
# except:
|
||||||
|
# ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
# if ele:
|
||||||
|
# ele.click()
|
||||||
|
# # self.page.set.window.hide()
|
||||||
|
# end_time=time.time()
|
||||||
|
# print('初始化完成 耗时:',end_time-start_time)
|
||||||
|
#
|
||||||
|
# def get_ip(self):
|
||||||
|
# # 提取代理API接口,获取1个代理IP
|
||||||
|
# api_url = "https://dps.kdlapi.com/api/getdps/?secret_id=ohs2d9r6kqdtt2tau900&signature=gktsvou9sd0nq7o09q3ridg70aal97b1&num=1&pt=1&sep=1"
|
||||||
|
#
|
||||||
|
# # 获取API接口返回的代理IP
|
||||||
|
# proxy_ip = requests.get(api_url).text
|
||||||
|
#
|
||||||
|
# # 用户名密码认证(私密代理/独享代理)
|
||||||
|
# username = "d2400186192"
|
||||||
|
# password = "5yv1r337"
|
||||||
|
# proxies = {
|
||||||
|
# "http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
|
||||||
|
# "https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
|
||||||
|
# }
|
||||||
|
# return proxies
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# # 处理tiktok的验证码
|
||||||
|
# def deal_identifying_code(self,b):
|
||||||
|
# url = "http://api.jfbym.com/api/YmServer/customApi"
|
||||||
|
# data = {
|
||||||
|
# ## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取
|
||||||
|
# "token": "w7hWcZPPOgQG2WTg4os5vD2WnYZ38g9bLWnmBxGUHY4",
|
||||||
|
# "type": "30101",
|
||||||
|
# "image": b,
|
||||||
|
# }
|
||||||
|
# _headers = {
|
||||||
|
# "Content-Type": "application/json"
|
||||||
|
# }
|
||||||
|
# response = requests.request("POST", url, headers=_headers, json=data, proxies=self.get_ip()).json()
|
||||||
|
# print(response)
|
||||||
|
# return response['data']['data']
|
||||||
|
#
|
||||||
|
# # text:传入邀约
|
||||||
|
# def get_anchor(self,text):
|
||||||
|
# start_time=time.time()
|
||||||
|
# while True:
|
||||||
|
# try:
|
||||||
|
# inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
# if inputele:
|
||||||
|
# inputele.click()
|
||||||
|
# inputele.input(text,clear=True)
|
||||||
|
# self.page.listen.start('https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
# while True:
|
||||||
|
# nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
# nextele.click()
|
||||||
|
# backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
# if backele:
|
||||||
|
# break
|
||||||
|
# while True:
|
||||||
|
# checkele=self.page.ele('确认',timeout=3)
|
||||||
|
# if checkele:
|
||||||
|
# print("请手动点击验证码")
|
||||||
|
# # print("处理验证码")
|
||||||
|
# # # 发现验证码截图保存到本地
|
||||||
|
# #
|
||||||
|
# # # 定位元素
|
||||||
|
# # element = self.page.ele("@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto")
|
||||||
|
# # # 截取该元素并保存
|
||||||
|
# # element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
# #
|
||||||
|
# # time.sleep(random.random())
|
||||||
|
# # with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
# # b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
# #
|
||||||
|
# # # 处理验证码
|
||||||
|
# # result = self.deal_identifying_code(b)
|
||||||
|
# # print(result,type(result))
|
||||||
|
# # # 获取x,y的坐标
|
||||||
|
# # for i in result.split('|'):
|
||||||
|
# # x = int(i.split(',')[0])
|
||||||
|
# # y = int(i.split(',')[1])
|
||||||
|
# # ac = Actions(self.page)
|
||||||
|
# #
|
||||||
|
# # ac.move_to(ele_or_loc=element,offset_x=0,offset_y=0).move(x,y).click()
|
||||||
|
# #
|
||||||
|
# # self.page.ele("@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full").click()
|
||||||
|
# # while True:
|
||||||
|
# # checkele=self.page.ele('确认',timeout=3)
|
||||||
|
# # if not checkele:
|
||||||
|
# # # self.page.set.window.hide()
|
||||||
|
# # break
|
||||||
|
# # time.sleep(0.2)
|
||||||
|
# # continue
|
||||||
|
# break
|
||||||
|
# backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
# if backele:
|
||||||
|
# break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
# print('重复点击')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# res=self.page.listen.wait(1)
|
||||||
|
# self.page.listen.stop()
|
||||||
|
# while True:
|
||||||
|
# backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
# backele.click()
|
||||||
|
# nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
# if nextele:
|
||||||
|
# break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
# print('重复点击')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# break
|
||||||
|
# except Exception as e:
|
||||||
|
# print('报错的原因',e)
|
||||||
|
# self.page.refresh()
|
||||||
|
# ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=5)
|
||||||
|
# if ele:
|
||||||
|
# ele.click()
|
||||||
|
# while True:
|
||||||
|
# ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
# try:
|
||||||
|
# if ele:
|
||||||
|
# ele.click()
|
||||||
|
# time.sleep(1)
|
||||||
|
# inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
# if inputele:
|
||||||
|
# break
|
||||||
|
# except:
|
||||||
|
# ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
# if ele:
|
||||||
|
# ele.click()
|
||||||
|
# end_time=time.time()
|
||||||
|
# print('耗时:',end_time-start_time)
|
||||||
|
# return res.response.body
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import base64
|
||||||
|
import requests
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage import ChromiumOptions
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
from DrissionPage.common import Actions
|
||||||
|
|
||||||
|
class batch_check_anchor_copy:
|
||||||
|
|
||||||
|
def __init__(self,username,password, callback):
|
||||||
|
# 在初始化时进行一系列的自动化操作,登录->关闭窗口->点击邀约主播
|
||||||
|
start_time=time.time()
|
||||||
|
false=False
|
||||||
|
true=True
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# co.incognito()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
# 全局隐藏窗口
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
#self.page.set.cookies.clear()
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
loginele=self.page.ele("@data-id=login")
|
||||||
|
|
||||||
|
print("cookie允许")
|
||||||
|
|
||||||
|
# btn = self.page.ele("全部允许")
|
||||||
|
# if btn:
|
||||||
|
# print("123456")
|
||||||
|
# btn.click()
|
||||||
|
if loginele:
|
||||||
|
#
|
||||||
|
# self.page.set.window.show()
|
||||||
|
# 点击登录按钮
|
||||||
|
self.page.ele("@data-id=login").click()
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username,clear=True)
|
||||||
|
time.sleep(random.random())
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password,clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(random.random())
|
||||||
|
self.page.ele("@class=semi-button semi-button-primary semi-button-size-large semi-button-block").click()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
loginele=self.page.ele("@data-id=login",timeout=1)
|
||||||
|
if not loginele:
|
||||||
|
print('后台登录成功')
|
||||||
|
# self.page.set.window.hide()
|
||||||
|
if callback:
|
||||||
|
callback()
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
|
||||||
|
print("3s 点击 关闭页面")
|
||||||
|
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
invite_btn = self.page.ele("@class=semi-button semi-button-primary semi-button-with-icon",timeout=1)
|
||||||
|
|
||||||
|
if not invite_btn:
|
||||||
|
btn = self.page.ele("@data-id=know")
|
||||||
|
if btn:
|
||||||
|
btn.click()
|
||||||
|
check_btn = self.page.ele("@data-id=workplace-switch-button")
|
||||||
|
if check_btn:
|
||||||
|
check_btn.click()
|
||||||
|
while true:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
time.sleep(1)
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
self.get_anchor("测试")
|
||||||
|
print('初始化完成 耗时:',end_time-start_time)
|
||||||
|
|
||||||
|
def get_ip(self):
|
||||||
|
# 提取代理API接口,获取1个代理IP
|
||||||
|
api_url = "https://dps.kdlapi.com/api/getdps/?secret_id=ohs2d9r6kqdtt2tau900&signature=gktsvou9sd0nq7o09q3ridg70aal97b1&num=1&pt=1&sep=1"
|
||||||
|
|
||||||
|
# 获取API接口返回的代理IP
|
||||||
|
proxy_ip = requests.get(api_url).text
|
||||||
|
|
||||||
|
# 用户名密码认证(私密代理/独享代理)
|
||||||
|
username = "d2400186192"
|
||||||
|
password = "5yv1r337"
|
||||||
|
proxies = {
|
||||||
|
"http": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip},
|
||||||
|
"https": "http://%(user)s:%(pwd)s@%(proxy)s/" % {"user": username, "pwd": password, "proxy": proxy_ip}
|
||||||
|
}
|
||||||
|
return proxies
|
||||||
|
|
||||||
|
|
||||||
|
# 处理tiktok的验证码
|
||||||
|
def deal_identifying_code(self,b):
|
||||||
|
url = "http://api.jfbym.com/api/YmServer/customApi"
|
||||||
|
data = {
|
||||||
|
## 关于参数,一般来说有3个;不同类型id可能有不同的参数个数和参数名,找客服获取
|
||||||
|
"token": "w7hWcZPPOgQG2WTg4os5vD2WnYZ38g9bLWnmBxGUHY4",
|
||||||
|
"type": "30101",
|
||||||
|
"image": b,
|
||||||
|
}
|
||||||
|
_headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
response = requests.request("POST", url, headers=_headers, json=data, proxies=self.get_ip()).json()
|
||||||
|
print(response)
|
||||||
|
return response['data']['data']
|
||||||
|
|
||||||
|
# text:传入邀约
|
||||||
|
def get_anchor(self,text):
|
||||||
|
start_time=time.time()
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
inputele.click()
|
||||||
|
inputele.input(text,clear=True)
|
||||||
|
self.page.listen.start('https://live-backstage.tiktok.com/creators/live/union_platform_api/agency/union_invite/batch_check_anchor/')
|
||||||
|
while True:
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
nextele.click()
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
while True:
|
||||||
|
checkele=self.page.ele('确认')
|
||||||
|
if checkele:
|
||||||
|
|
||||||
|
print("请手动点击验证码")
|
||||||
|
# # self.page.set.window.show()
|
||||||
|
# print("处理验证码")
|
||||||
|
# # 发现验证码截图保存到本地
|
||||||
|
#
|
||||||
|
# # 定位元素
|
||||||
|
# element = self.page.ele("@class=cap-rounded-lg cap-cursor-pointer cap-w-full cap-h-auto")
|
||||||
|
# # 截取该元素并保存
|
||||||
|
# element.get_screenshot("tiktok_identifying_code.png")
|
||||||
|
#
|
||||||
|
# time.sleep(random.random())
|
||||||
|
# with open('tiktok_identifying_code.png', 'rb') as f:
|
||||||
|
# b = base64.b64encode(f.read()).decode() ## 图片二进制流base64字符串
|
||||||
|
#
|
||||||
|
# # 处理验证码
|
||||||
|
# result = self.deal_identifying_code(b)
|
||||||
|
# print(result,type(result))
|
||||||
|
# # 获取x,y的坐标
|
||||||
|
# for i in result.split('|'):
|
||||||
|
# x = int(i.split(',')[0])
|
||||||
|
# y = int(i.split(',')[1])
|
||||||
|
# ac = Actions(self.page)
|
||||||
|
#
|
||||||
|
# ac.move_to(ele_or_loc=element,offset_x=0,offset_y=0).move(x,y).click()
|
||||||
|
#
|
||||||
|
# self.page.ele("@class=TUXButton TUXButton--default TUXButton--medium TUXButton--primary cap-my-8 cap-w-full").click()
|
||||||
|
# back_btn = self.page.ele("@data-id=invite-host-back")
|
||||||
|
# if back_btn:
|
||||||
|
# back_btn.click()
|
||||||
|
# time.sleep(10)
|
||||||
|
# # self.page.set.window.hide()
|
||||||
|
# while True:
|
||||||
|
# checkele=self.page.ele('确认')
|
||||||
|
# if not checkele:
|
||||||
|
# # self.page.set.window.hide()
|
||||||
|
# break
|
||||||
|
# time.sleep(0.2)
|
||||||
|
# continue
|
||||||
|
break
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
if backele:
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
print('重复点击')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
res=self.page.listen.wait(1)
|
||||||
|
self.page.listen.stop()
|
||||||
|
while True:
|
||||||
|
backele=self.page.ele('@data-id=invite-host-back')
|
||||||
|
backele.click()
|
||||||
|
nextele=self.page.eles('@data-id=invite-host-next')[0]
|
||||||
|
if nextele:
|
||||||
|
break
|
||||||
|
time.sleep(0.2)
|
||||||
|
print('重复点击')
|
||||||
|
# self.page.set.window.show()
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print('报错的原因',e)
|
||||||
|
self.page.refresh()
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only')
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
while True:
|
||||||
|
ele=self.page.ele('@data-id=add-host-btn')
|
||||||
|
try:
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
time.sleep(1)
|
||||||
|
inputele=self.page.eles('@class=semi-input-textarea semi-input-textarea-autosize')[1]
|
||||||
|
if inputele:
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
ele=self.page.ele('@class=semi-button semi-button-tertiary semi-button-size-small semi-button-borderless semi-modal-close semi-button-with-icon semi-button-with-icon-only',timeout=1)
|
||||||
|
if ele:
|
||||||
|
ele.click()
|
||||||
|
|
||||||
|
end_time=time.time()
|
||||||
|
print('耗时:',end_time-start_time)
|
||||||
|
return res.response.body
|
||||||
51
src/assets/img/demos/2025-04/tiktok_cookies(1).py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import re
|
||||||
|
import time
|
||||||
|
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage._configs.chromium_options import ChromiumOptions
|
||||||
|
|
||||||
|
|
||||||
|
def monitor_url_and_cookies():
|
||||||
|
co = ChromiumOptions()
|
||||||
|
co.incognito() # 使用无痕模式避免缓存
|
||||||
|
page = ChromiumPage(co)
|
||||||
|
page.get('https://www.tiktok.com/login')
|
||||||
|
|
||||||
|
# 获取初始URL和Cookies
|
||||||
|
current_url = page.url
|
||||||
|
print(f"初始URL: {current_url}")
|
||||||
|
|
||||||
|
# login_url = "https://www.tiktok.com/login"
|
||||||
|
# barcode_url = "https://www.tiktok.com/login/qrcode"
|
||||||
|
# phone_url = "https://www.tiktok.com/login/phone-or-email"
|
||||||
|
# email_url = "https://www.tiktok.com/login/phone-or-email/email"
|
||||||
|
|
||||||
|
|
||||||
|
chrome_url = "chrome://newtab/"
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
# if page.url != current_url and page.url != barcode_url and page.url != phone_url and page.url != login_url and page.url != chrome_url and page.url != email_url:
|
||||||
|
if not re.match(r'https://www\.tiktok\.com/login(/.*)?', page.url) and page.url != chrome_url and page.url != current_url:
|
||||||
|
new_url = page.url
|
||||||
|
print(f"检测到URL变化: {new_url}")
|
||||||
|
if page.cookies():
|
||||||
|
cookies = page.cookies()
|
||||||
|
print(cookies)
|
||||||
|
for cookie in cookies:
|
||||||
|
if (cookie["name"] == 'msToken'):
|
||||||
|
token = cookie["value"]
|
||||||
|
print(token)
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
except Exception as e:
|
||||||
|
print("用户中断监控",e)
|
||||||
|
finally:
|
||||||
|
page.quit()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
monitor_url_and_cookies()
|
||||||
|
|
||||||
|
|
||||||
|
# 最新Cookies: [{'name': 'store-country-sign', 'value': 'MEIEDBhQzC1i4DLdX86soAQgoJaw235vGvRyvEQnIgbBNGUO-cN47EiVHvk-M0ZEbM4EEIx_vV3D83yUzh8j8-g43A8', 'domain': '.tiktok.com'}, {'name': 'last_login_method', 'value': 'sms_verification', 'domain': 'www.tiktok.com'}, {'name': 'tt-target-idc-sign', 'value': 'hKLPLDWAK6XKzlPQNvI-AheN2Sf2BdhwyW_dv9uLHV65wCYz6fFnztQMv8vQplapuWiIjgsUPbxI4ZyMJOXS3-rAO0bPJp0omk6chCOuGiERVZ1qKcrcNlN-2NqDXufNOxOL6Rt9GrztXKXigK6RDr2ErkRJGRQ45LA7BO3s-y_HDCCtQ5j6roM1GbAs0U3TxjyOGo7zs_Mr8yCxIYdjn9DHO8MtqubCLEdePCaKodR5_G3VE5VW5Ee8dPQEITg2FSzltHwBE4Z13IaHDY0Ckcd-agQEnWoiZo4WklsDJ7lOVAxSSfVAOYiUyJFeN96ngpuWqlKIKd5jHkmfO2Xmfq1k7TqVVuCcpNvjucyVdk2c-MlbG5gc897_mzIa3kYk3JxRPE9lEzukokuIyqI1iHTHVx_GzZLzGZenZikTVNZVeapIFmmrhJo_fc2RqA1-pjqQfcZjAIpXTEDoATXJm7gnjaaXBFCxkg5w4GI9RXdxxT7Z0uSywE2fKeI7o1V6', 'domain': '.tiktok.com'}, {'name': 'cmpl_token', 'value': 'AgQQAPNSF-RO0rfK75Gtu10n_ZS52rpfv4SLYNgVrg', 'domain': '.tiktok.com'}, {'name': 'store-idc', 'value': 'useast5', 'domain': '.tiktok.com'}, {'name': 'sid_tt', 'value': 'ca9b365605b07f17c848304f1b21f1b1', 'domain': '.tiktok.com'}, {'name': 'sessionid_ss', 'value': 'ca9b365605b07f17c848304f1b21f1b1', 'domain': '.tiktok.com'}, {'name': 'store-country-code', 'value': 'us', 'domain': '.tiktok.com'}, {'name': 'sid_guard', 'value': 'ca9b365605b07f17c848304f1b21f1b1%7C1744118054%7C15552000%7CSun%2C+05-Oct-2025+13%3A14%3A14+GMT', 'domain': '.tiktok.com'}, {'name': 'ssid_ucp_v1', 'value': '1.0.0-KDZiZmQ0MzUwYTVkZDBkMDNjZDVmYjEzNmMxY2YzNTg4ZmFkZGFmODkKGgieiKas4qaA-mcQpsLUvwYYsws4AkDxB0gEEAQaB3VzZWFzdDgiIGNhOWIzNjU2MDViMDdmMTdjODQ4MzA0ZjFiMjFmMWIx', 'domain': '.tiktok.com'}, {'name': 'uid_tt_ss', 'value': 'e1ac4f4771b59119252e3c6e2d228723aa252bca67d109800fe590c08d189a2b', 'domain': '.tiktok.com'}, {'name': 'msToken', 'value': 'M3kAGVk-2YuPwYBH_sa52mklJY7oefj-_ur-Zy2dJ4AEw_zrUCrJ9H0B5UWyuQjSy9y8PEQCa__pIQZiFdqsLB8gpAWdyBZBq-QT9P50zDGz-Nl64qQ1iR58d_REWkFcx8E2R1j3NXOzjA==', 'domain': 'www.tiktok.com'}, {'name': 'passport_auth_status_ss', 'value': 'de453ede07a5dc52b2d72f2d6ce7e1b1%2C', 'domain': '.tiktok.com'}, {'name': 'passport_auth_status', 'value': 'de453ede07a5dc52b2d72f2d6ce7e1b1%2C', 'domain': '.tiktok.com'}, {'name': 'ttwid', 'value': '1%7CEOVVkXdnrWEn93yKcVp_-RqArMpUob7WPkxXYzQ0v-Q%7C1744118054%7Cadd08c3f8609426f2d210e77646080af1f66b31f855e4f71f59af53be2b76de9', 'domain': '.tiktok.com'}, {'name': 's_v_web_id', 'value': 'verify_m98iu0if_zRj795Z5_lMqS_4RX4_BugR_hlAqYfCv7sUA', 'domain': '.tiktok.com'}, {'name': 'sid_ucp_v1', 'value': '1.0.0-KDZiZmQ0MzUwYTVkZDBkMDNjZDVmYjEzNmMxY2YzNTg4ZmFkZGFmODkKGgieiKas4qaA-mcQpsLUvwYYsws4AkDxB0gEEAQaB3VzZWFzdDgiIGNhOWIzNjU2MDViMDdmMTdjODQ4MzA0ZjFiMjFmMWIx', 'domain': '.tiktok.com'}, {'name': 'd_ticket', 'value': '619388ab7c3c2c8a3e704738f1d0a23c07177', 'domain': '.tiktok.com'}, {'name': 'store-country-code-src', 'value': 'uid', 'domain': '.tiktok.com'}, {'name': 'tt_csrf_token', 'value': 'nS8qfODs-xjVemoiTDYYm8wijlhN0XkMPGRY', 'domain': '.tiktok.com'}, {'name': 'fblo_1862952583919182', 'value': 'y', 'domain': 'www.tiktok.com'}, {'name': 'msToken', 'value': 'LhE9T6hkMhHjKedKt2PuxuA435tCx7BUjKtPMrJIuHEY32WS40xcqKt-XaVF1-tNwZ0-JG_wINnqRgOK23dwFWxzq9VX26nYZcxqpQKIiQENSdRILk-mj0Oj51q8ZhRPBhgi6p4rY605XQ==', 'domain': '.tiktok.com'}, {'name': 'passport_csrf_token_default', 'value': 'cb83facc338b76cf19efb1939ff364b2', 'domain': '.tiktok.com'}, {'name': 'multi_sids', 'value': '7490613412293608478%3Aca9b365605b07f17c848304f1b21f1b1', 'domain': '.tiktok.com'}, {'name': 'tiktok_webapp_theme_source', 'value': 'light', 'domain': '.www.tiktok.com'}, {'name': 'tt_chain_token', 'value': '5Dl6k0jmQfjg8xPw+YsRSw==', 'domain': '.tiktok.com'}, {'name': 'tt-target-idc', 'value': 'useast5', 'domain': '.tiktok.com'}, {'name': 'passport_csrf_token', 'value': 'cb83facc338b76cf19efb1939ff364b2', 'domain': '.tiktok.com'}, {'name': 'sessionid', 'value': 'ca9b365605b07f17c848304f1b21f1b1', 'domain': '.tiktok.com'}, {'name': 'uid_tt', 'value': 'e1ac4f4771b59119252e3c6e2d228723aa252bca67d109800fe590c08d189a2b', 'domain': '.tiktok.com'}, {'name': 'tiktok_webapp_theme', 'value': 'light', 'domain': '.www.tiktok.com'}]
|
||||||
74
src/assets/img/demos/2025-04/tiktok_cookies(2).py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import re
|
||||||
|
import time
|
||||||
|
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage._configs.chromium_options import ChromiumOptions
|
||||||
|
from playwright.sync_api import sync_playwright
|
||||||
|
|
||||||
|
|
||||||
|
def monitor_url_and_cookies():
|
||||||
|
from utils.JsInteraction import fetch_data_config
|
||||||
|
|
||||||
|
co = ChromiumOptions()
|
||||||
|
co.incognito()
|
||||||
|
page = ChromiumPage(co)
|
||||||
|
page.get('https://www.tiktok.com/login')
|
||||||
|
|
||||||
|
# 获取初始URL和Cookies
|
||||||
|
current_url = page.url
|
||||||
|
print(f"初始URL: {current_url}")
|
||||||
|
|
||||||
|
tiktok_url = "https://www.tiktok.com/foryou?lang=zh-Hans"
|
||||||
|
chrome_url = "chrome://newtab/"
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
if (page.url == tiktok_url) or not re.match(r'https://www\.tiktok\.com/login(/.*)?',
|
||||||
|
page.url) and page.url != chrome_url and page.url != current_url:
|
||||||
|
new_url = page.url
|
||||||
|
print(f"检测到URL变化: {new_url}")
|
||||||
|
if page.cookies():
|
||||||
|
fetch_data_config.headers = page._headers
|
||||||
|
print("headers = " , page._headers)
|
||||||
|
|
||||||
|
cookies = page.cookies()
|
||||||
|
fetch_data_config.cookie = cookies
|
||||||
|
for cookie in cookies:
|
||||||
|
if (cookie["name"] == 'msToken'):
|
||||||
|
token = cookie["value"]
|
||||||
|
fetch_data_config.msToken = token
|
||||||
|
else:
|
||||||
|
print("用户未登录")
|
||||||
|
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
except Exception as e:
|
||||||
|
print("用户中断监控",e)
|
||||||
|
finally:
|
||||||
|
print("执行完毕,关闭窗口")
|
||||||
|
page.quit()
|
||||||
|
|
||||||
|
def get_api_headers(url):
|
||||||
|
with sync_playwright() as p:
|
||||||
|
browser = p.chromium.launch(headless=False)
|
||||||
|
page = browser.new_page()
|
||||||
|
|
||||||
|
# 存储目标请求的 headers
|
||||||
|
target_headers = {}
|
||||||
|
|
||||||
|
# 监听所有网络请求
|
||||||
|
def on_request(request):
|
||||||
|
if url in request.url: # 匹配目标接口
|
||||||
|
target_headers.update(request.headers)
|
||||||
|
print("Headers:", request.headers)
|
||||||
|
|
||||||
|
page.on("request", on_request)
|
||||||
|
|
||||||
|
# 访问页面(示例:打开一个会触发目标接口的网页)
|
||||||
|
page.goto("https://example.com") # 替换为实际页面
|
||||||
|
page.wait_for_timeout(5000) # 等待请求完成
|
||||||
|
|
||||||
|
browser.close()
|
||||||
|
return target_headers
|
||||||
|
if __name__ == '__main__':
|
||||||
|
monitor_url_and_cookies()
|
||||||
58
src/assets/img/demos/2025-04/tiktok_cookies(3).py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import re
|
||||||
|
import time
|
||||||
|
|
||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage._configs.chromium_options import ChromiumOptions
|
||||||
|
|
||||||
|
|
||||||
|
def monitor_url_and_cookies():
|
||||||
|
from utils.JsInteraction import fetch_data_config
|
||||||
|
co = ChromiumOptions()
|
||||||
|
|
||||||
|
page = ChromiumPage(co)
|
||||||
|
page.get('https://www.tiktok.com/login')
|
||||||
|
|
||||||
|
# 获取初始URL和Cookies
|
||||||
|
current_url = page.url
|
||||||
|
print(f"初始URL: {current_url}")
|
||||||
|
tiktok_url = "https://www.tiktok.com/foryou?lang=zh-Hans"
|
||||||
|
chrome_url = "chrome://newtab/"
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
if (page.url == tiktok_url) or not re.match(r'https://www\.tiktok\.com/login(/.*)?',
|
||||||
|
page.url) and page.url != chrome_url and page.url != current_url:
|
||||||
|
new_url = page.url
|
||||||
|
print(f"检测到URL变化: {new_url}")
|
||||||
|
if page.cookies():
|
||||||
|
cookies = page.cookies()
|
||||||
|
fetch_data_config.cookies_dict = {cookie['name']: cookie['value'] for cookie in cookies}
|
||||||
|
|
||||||
|
print(fetch_data_config.cookies_dict)
|
||||||
|
if 'sid_guard' in fetch_data_config.cookies_dict:
|
||||||
|
for cookie in cookies:
|
||||||
|
if (cookie["name"] == 'msToken'):
|
||||||
|
token = cookie["value"]
|
||||||
|
fetch_data_config.msToken = token
|
||||||
|
print("用户登录", token)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("用户未登录1")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("用户未登录2")
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
except Exception as e:
|
||||||
|
print("用户中断监控", e)
|
||||||
|
finally:
|
||||||
|
print("执行完毕,关闭窗口")
|
||||||
|
page.quit()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
monitor_url_and_cookies()
|
||||||
|
|
||||||
|
# [{'name': 'ttwid', 'value': '1%7CvanRPv1of0nPRzF_0x3HnC1_Sf5EKmOQiyjn0OA7oC0%7C1744273288%7C3e7012f595ba249565d109df5681b0cf2c6a7b383820fe4ebfca075619739c29', 'domain': '.tiktok.com'}, {'name': 'tiktok_webapp_theme', 'value': 'dark', 'domain': '.www.tiktok.com'}, {'name': 'tt_chain_token', 'value': 'vJUyXPhw6ixK3juREYULHw==', 'domain': '.tiktok.com'}, {'name': 'tt_csrf_token', 'value': '95kdv40l-RZZWrFe4y9nylyTOkXCCSO3OFrQ', 'domain': '.tiktok.com'}, {'name': 'msToken', 'value': '0vDx94cr2tXAIAZhfIbsoha9gRJc5Sd3-VDfwIz6T9xJQhdPGIfRJd62goLYggZxOnLaIR1ZvD0BE1iNohLfgMt_hfW1pes1ZFzZvs1y09_Gu1TPOFV4aUt_j9WDq56Zb0luA7E=', 'domain': 'www.tiktok.com'}, {'name': 'msToken', 'value': '8QbVY-Phwl0FJfhu9VHxgUhOf-62P4tO5tFoIKA5snktzCpXuKjZkfiSm2nZysTUvQSQrEQ9w8xdli6WiZryf6dWuzxtryzjEI6OP6Z3bKPEQMf3fVE6KXy3vXHZSfhjGBPOjQ==', 'domain': '.tiktok.com'}, {'name': 'passport_csrf_token_default', 'value': 'ebe9d256aa75184036dcd21df1880793', 'domain': '.tiktok.com'}, {'name': 'tiktok_webapp_theme_source', 'value': 'auto', 'domain': '.www.tiktok.com'}, {'name': 'passport_csrf_token', 'value': 'ebe9d256aa75184036dcd21df1880793', 'domain': '.tiktok.com'}]
|
||||||
|
# [{'name': 'msToken', 'value': '9llqbTFWPouwDYuty_c-NFpZy7GMUV7wB16gV_HKz-bSy9Qe8Zc7Ls59iJRzhWNFfSzxRmzaCwI0VFp0gyiwepMfJRdB3Hejc9if3c6Sue7_8c_GzKajGoZRD4CQgdcC9Iudzg==', 'domain': 'www.tiktok.com'}, {'name': 'ttwid', 'value': '1%7CvanRPv1of0nPRzF_0x3HnC1_Sf5EKmOQiyjn0OA7oC0%7C1744273213%7C10889e658bad344c996adc8efd0949003b385b162112cd9ab4b7c3ed35fc3e83', 'domain': '.tiktok.com'}, {'name': 'tiktok_webapp_theme', 'value': 'light', 'domain': '.www.tiktok.com'}, {'name': 'tiktok_webapp_theme_source', 'value': 'light', 'domain': '.www.tiktok.com'}, {'name': 'tt_csrf_token', 'value': '95kdv40l-RZZWrFe4y9nylyTOkXCCSO3OFrQ', 'domain': '.tiktok.com'}]
|
||||||
|
# [{'name': 'tiktok_webapp_theme', 'value': 'dark', 'domain': '.www.tiktok.com'}, {'name': 'tiktok_webapp_theme_source', 'value': 'auto', 'domain': '.www.tiktok.com'}, {'name': 'ttwid', 'value': '1%7Csa7eEWP87ZS1gtue3VXl1zpVbC6RKeQq7n7rdiggW68%7C1744273026%7C737005dbcc404500e56f2e11afc43a5bd871371b2496052a8c961e6eab1bc71a', 'domain': '.tiktok.com'}, {'name': 'perf_feed_cache', 'value': '{%22expireTimestamp%22:1744441200000%2C%22itemIds%22:[%227477343231156555026%22%2C%227490761799852313862%22%2C%227489980636183153950%22]}', 'domain': '.www.tiktok.com'}, {'name': 'store-country-sign', 'value': 'MEIEDMcgZeJ036VJaKTHaAQgmxq9OvL0fmSNPBnvx9EESTgbhGIWUL4v1hOBnwlgJ1oEEF5opCR7Hyo0UHPqqZMIaRo', 'domain': '.tiktok.com'}, {'name': 'ssid_ucp_v1', 'value': '1.0.0-KDRjYzczYTQ1OTBkNzQ0NzFhY2Q5NDZhYTkyZWNmYjhkYmIxNDM5MTUKGgieiKas4qaA-mcQ-tLdvwYYsws4AkDxB0gEEAQaB3VzZWFzdDUiIGJiOTdkYTZlMDk2NzM4Y2FhYWZjMGQyZjBkOGQ3ZGU5', 'domain': '.tiktok.com'}, {'name': 'msToken', 'value': 'h0khQ6gYzX9DDutItyXfPZURLimHXfXimNp3Qmx1GLVRMpZYcjz-NVD6Ex-GQBPdPqg3wjyWLvVrkafiBnHtPF76XKgMVygF-gnzeAXVh4VRy3vm6J4A6iLZPGP7lmo5Pwk7eMAGJloH6h2VNc7O8As=', 'domain': 'www.tiktok.com'}, {'name': 'passport_auth_status_ss', 'value': 'e3b267a948817fba9cfcf571d786ebf8%2C', 'domain': '.tiktok.com'}, {'name': 'odin_tt', 'value': 'e2bb38160f4c443324a91a838cc85ef9eed8e85604c3ab86f4d380530b3665fbcf65d7031ecc24272a441bf2dc26cce8c9e70681b6cebb2a5ab0c07497fa953f43e295a8aa4521fd98b6b8777aa52aff', 'domain': '.tiktok.com'}, {'name': 'passport_csrf_token', 'value': '43b8095e41fe8d2420e22b766a26a898', 'domain': '.tiktok.com'}, {'name': 'tt-target-idc', 'value': 'useast5', 'domain': '.tiktok.com'}, {'name': 'tt_chain_token', 'value': 'gfzRgmma2qZcAB9zjh0xQw==', 'domain': '.tiktok.com'}, {'name': 'tt-target-idc-sign', 'value': 'UvMyO-B3BL9ZhIS2t_c413SApBUzvWDtdPiJrlWMrx31vq5kBQAPN4NkLIDsa9CtokMKrq0vjjsMPVVCX3nTrZdVhjH6Lt7MgbB5FAWQNn3hb9oRofmH1Vdi07roVjjwU-JM3yN2GD5L_aHZI8_6jzzTVNefJOM8N2hloBBBmcpuVsbm-LJQTCVXRgl6ycqDahoJXLvU9tw179W58pe92zkqBkp9IkqueZLhK31JIFSMNmRBjs4SoQQLkIHsto-bCr5tR4_8XxGZGMoRSHpHvvlvfxNI1iDqIODLRxkKTzut_v7Gydv2fsqo96ONdxssrFk9So-Mi8s6K-GaAuezfCnfaHsMCDYuPIxVoVaNzTm3yw-GJnxzd_rF-38lPx_-POsko1NHHlaZUJczluwlPpyhg4WQpomB7GF13K9J2o9u9wi4gRVZY92XkHEltytIW0mtSFzUbPM8WKehlVZ6OYGHJjSqq7fLPo1SKR1F0pbH99W-4srHizMMM8N6PuAn', 'domain': '.tiktok.com'}, {'name': 'cmpl_token', 'value': 'AgQQAPNSF-RO0rfK75Gtu10n_ZbKhWlWv6jZYNgOTw', 'domain': '.tiktok.com'}, {'name': 'store-idc', 'value': 'useast5', 'domain': '.tiktok.com'}, {'name': 'sid_guard', 'value': 'bb97da6e096738caaafc0d2f0d8d7de9%7C1744267642%7C15546491%7CTue%2C+07-Oct-2025+05%3A15%3A33+GMT', 'domain': '.tiktok.com'}, {'name': 'store-country-code', 'value': 'us', 'domain': '.tiktok.com'}, {'name': 'sessionid_ss', 'value': 'bb97da6e096738caaafc0d2f0d8d7de9', 'domain': '.tiktok.com'}, {'name': 'd_ticket', 'value': 'a2e1da528f5f15d6042a0fd2cb9b86d2c0cf8', 'domain': '.tiktok.com'}, {'name': 'sid_ucp_v1', 'value': '1.0.0-KDRjYzczYTQ1OTBkNzQ0NzFhY2Q5NDZhYTkyZWNmYjhkYmIxNDM5MTUKGgieiKas4qaA-mcQ-tLdvwYYsws4AkDxB0gEEAQaB3VzZWFzdDUiIGJiOTdkYTZlMDk2NzM4Y2FhYWZjMGQyZjBkOGQ3ZGU5', 'domain': '.tiktok.com'}, {'name': 'uid_tt', 'value': '818716f9dd32bf135ad6227463afdef538dd6d9c2bc1a405962d2aff42854dd8', 'domain': '.tiktok.com'}, {'name': 'sessionid', 'value': 'bb97da6e096738caaafc0d2f0d8d7de9', 'domain': '.tiktok.com'}, {'name': 'sid_tt', 'value': 'bb97da6e096738caaafc0d2f0d8d7de9', 'domain': '.tiktok.com'}, {'name': 'delay_guest_mode_vid', 'value': '5', 'domain': '.www.tiktok.com'}, {'name': 'uid_tt_ss', 'value': '818716f9dd32bf135ad6227463afdef538dd6d9c2bc1a405962d2aff42854dd8', 'domain': '.tiktok.com'}, {'name': 'tt_csrf_token', 'value': 'btSF4WK1-oDF_JO8_75KzH0DSsxf2fMPo5AQ', 'domain': '.tiktok.com'}, {'name': 'store-country-code-src', 'value': 'uid', 'domain': '.tiktok.com'}, {'name': 'passport_auth_status', 'value': 'e3b267a948817fba9cfcf571d786ebf8%2C', 'domain': '.tiktok.com'}, {'name': 'last_login_method', 'value': 'sms_verification', 'domain': 'www.tiktok.com'}, {'name': 'multi_sids', 'value': '7490613412293608478%3Abb97da6e096738caaafc0d2f0d8d7de9', 'domain': '.tiktok.com'}, {'name': 'msToken', 'value': '3bAzXN5RKGiylvPVAsm51_MriKVmAbErcw09EAKIB9Alw1fkFY7he_21IU3JGe-A8peutfScjlSZJM1ZCg1DnV_4DHazlRVGhru_x04aeW5M6lpzUSO-PMUnyvJcSKpqxmU33i36MyLWOIzFaJUV-oI=', 'domain': '.tiktok.com'}, {'name': 'passport_csrf_token_default', 'value': '43b8095e41fe8d2420e22b766a26a898', 'domain': '.tiktok.com'}] 我是cookie
|
||||||
48
src/assets/img/demos/2025-04/tiktok_cookies.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
from DrissionPage import ChromiumPage
|
||||||
|
from DrissionPage import ChromiumOptions
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Cookies:
|
||||||
|
def __init__(self,username,password):
|
||||||
|
co = ChromiumOptions()
|
||||||
|
# 设置不加载图片、静音
|
||||||
|
co.mute(True)
|
||||||
|
co.headless(False)
|
||||||
|
co.auto_port(True)
|
||||||
|
co.headless(True)
|
||||||
|
self.page = ChromiumPage(co)
|
||||||
|
self.page.get('https://live-backstage.tiktok.com/portal/overview')
|
||||||
|
|
||||||
|
|
||||||
|
def get_mstoken(self):
|
||||||
|
loginele = self.page.ele('登录')
|
||||||
|
if loginele:
|
||||||
|
# 点击登录按钮
|
||||||
|
self.page.ele("登录").click()
|
||||||
|
time.sleep(0.1)
|
||||||
|
# 输入账号
|
||||||
|
self.page.ele("@class=semi-input semi-input-default").input(username, clear=True)
|
||||||
|
time.sleep(0.1)
|
||||||
|
# 输入密码
|
||||||
|
self.page.ele("@class=semi-input semi-input-default semi-input-sibling-modebtn").input(password, clear=True)
|
||||||
|
# 点击进行登录
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.page.ele("@class=semi-button semi-button-primary semi-button-size-large semi-button-block").click()
|
||||||
|
cookies = self.page.cookies()
|
||||||
|
for cookie in cookies:
|
||||||
|
if(cookie["name"] == 'msToken'):
|
||||||
|
token = cookie["value"]
|
||||||
|
print(token)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__=='__main__':
|
||||||
|
username = "ph@tiktok0.xyz"
|
||||||
|
password = "zxcvbnm123.."
|
||||||
|
|
||||||
|
cookies = Cookies(username,password)
|
||||||
|
cookies.get_mstoken()
|
||||||
|
|
||||||
|
|
||||||
BIN
src/assets/img/demos/2025-04/tk-page.rar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT(1).jar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT(2).jar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT(3).jar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT(4).jar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT(5).jar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT(6).jar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT(7).jar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT(8).jar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT(9).jar
Normal file
BIN
src/assets/img/demos/2025-04/tkinterface-0.0.1-SNAPSHOT.jar
Normal file
BIN
src/assets/img/demos/2025-04/vue-admin-template.rar
Normal file
BIN
src/assets/img/demos/2025-04/vv_super_logo.ico
Normal file
|
After Width: | Height: | Size: 57 KiB |