初始化仓库

This commit is contained in:
2025-07-01 21:14:03 +08:00
commit 7fa984a122
334 changed files with 40250 additions and 0 deletions

23
.gitignore vendored Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

56
package.json Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

21
public/index.html Normal file
View 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
View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View 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

View 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

Binary file not shown.

View 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>

View 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>

View 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>

View 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)

View 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&region=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&region=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&region_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&current_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&region=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&current_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&region=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&region={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&region=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

Binary file not shown.

View 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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&region=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

View 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}")

View 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}")

View 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)

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

View 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>

View 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

View 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)

View 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))
# 获取xy的坐标
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()

View 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))
# 获取xy的坐标
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

View 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))
# 获取xy的坐标
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

View 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))
# 获取xy的坐标
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

View 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))
#
# # 获取xy的坐标
# 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

View 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))
# 获取xy的坐标
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))
# 获取xy的坐标
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

View 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))
# # 获取xy的坐标
# 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

View 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))
# # # 获取xy的坐标
# # 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))
# # 获取xy的坐标
# 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

View 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'}]

View 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()

View 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

View 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()

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More