初始化仓库
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 |