टिकटॉक डेटा पाइपलाइन बनाएं ताकि दोहरावदार विश्लेषण हो सके
Senior Web Scraping Engineer
TL;DR:
- एक TikTok डेटा पाइपलाइन को सामान्यीकरण से पहले कच्ची प्रतिक्रियाएँ संरक्षित करनी चाहिए। स्रोत पेलोड पार्सर परिवर्तनों और फ़ील्ड ड्रिफ्ट की समीक्षा करने योग्य बनाते हैं।
- संग्रह चलानों को अपनी स्थिति तालिका की आवश्यकता है। एक असफल अनुरोध एक कवरेज गैप है, खाली प्रोफ़ाइल, पोस्ट सूची, या उत्पाद नहीं।
- TikTok पहचाने गए पाठ स्तंभों में होने चाहिए। स्ट्रिंग स्टोरेज लंबे आईडी को संख्यात्मक रूपांतरण द्वारा बदलने से रोकता है।
- स्नैपशॉट तालिकाएँ समय के साथ अवलोकनों का वर्णन करती हैं। उन्हें पूर्व निर्माता, पोस्ट, या दुकान के मानों को अधिलेखित नहीं करना चाहिए।
- इतिहास कवरेज एकत्रित पृष्ठों और सत्यापित निरंतरता डेटा पर निर्भर करती है। एक पहले पृष्ठ की प्रतिक्रिया पूरी खाता इतिहास नहीं है।
- शुरू करने के लिए स्वतंत्र। नए Scrapeless खाते Scrapeless डैशबोर्ड के माध्यम से मुफ्त क्रेडिट शामिल करते हैं।
Introduction: analytics begins with collection evidence
एक डैशबोर्ड केवल उन रिकॉर्डों को समझा सकता है जो इसके डेटाबेस तक पहुँचे। कच्चे पेलोड, रन स्थिति, और संग्रह टाइमस्टैम्प के बिना, एक खाली चार्ट कोई गतिविधि को असफल संग्रह या पार्सर परिवर्तन से अलग नहीं कर सकता।
यह गाइड Scrapeless TikTok अभिनेताओं से SQLite के लिए एक संक्षिप्त TikTok डेटा पाइपलाइन का निर्माण करती है। डिज़ाइन कच्चा JSON संरक्षित करता है, निर्माता, पोस्ट, और दुकान स्नैपशॉट को सामान्यीकृत करता है, डेटा-गुणवत्ता जांच करता है, और विश्लेषण के लिए छोटे SQL क्वेरी को उजागर करता है। शेड्यूलिंग, उत्पादन डेटाबेस संचालन, और व्यावसायिक-बुद्धि वितरण एप्लिकेशन की जिम्मेदारियाँ बनी रहती हैं।
TikTok अभिनेता गाइड वह अभिनेता मानचित्र प्रलेखित करता है जिसका उपयोग संग्राहक द्वारा किया जाता है।
Pipeline at a Glance
| Stage | Action | Output |
|---|---|---|
| Collect | प्रोफ़ाइल, पोस्ट, और वैकल्पिक दुकान अभिनेताओं को कॉल करें | API प्रतिक्रियाएँ |
| Preserve | अभिनेता और रन मेटाडेटा के साथ कच्चा JSON संग्रहित करें | अपरिवर्तनीय स्रोत परत |
| Normalize | आईडी, काउंटर, टाइमस्टैम्प, और आयामों का पार्स करें | स्नैपशॉट तालिकाएँ |
| Validate | कुंजियाँ, प्रकार, शून्य, और रन कवरेज की जांच करें | डेटा-गुणवत्ता परिणाम |
| Query | परिवर्तनों और वर्तमान स्थिति को संचित करें | विश्लेषणात्मक दृश्य |
पाइपलाइन रिकॉर्ड करती है कि प्रत्येक अनुरोध ने क्या वापस किया। यह पूरी TikTok इतिहास का दावा नहीं करती जब तक कि हर आवश्यक पृष्ठ और निरंतरता मान एकत्र और सत्यापित नहीं किया गया है।
Prerequisites
- Scrapeless डैशबोर्ड से Scrapeless खाता और API कुंजी
- मानक पुस्तकालय और SQLite के साथ Python 3
- प्रोफ़ाइल और पोस्ट संग्रह के लिए एक सार्वजनिक TikTok उपयोगकर्ता नाम
- उत्पाद स्नैपशॉट के लिए वैकल्पिक TikTok दुकान उत्पाद आईडी और क्षेत्र
- एक भंडारण स्थान, संरक्षण नीति, और संग्रह अनुसूची
SCRAPELESS_API_KEYऔरTIKTOK_USERNAMEसंग्रहकर्ता के लिए; दुकान पर्यावरण चर वैकल्पिक हैं
अंत-से-अंत कोड एक पूर्वापेक्षा गैप है क्योंकि एक सक्रिय Scrapeless क्रेडेंशियल और लक्षित पहचाने वाले पन्नों से आता है। अभिनेता नाम, इनपुट फ़ील्ड, और सामान्यीकृत कॉलम प्रदान किए गए इंटरफ़ेस दस्तावेज़ का पालन करते हैं बिना आविष्कारित उत्पादन प्रस्तुत किए।
Stage 1: Give Every Collection Attempt an Identity
एक तार्किक संग्रह के लिए एक run_id बनाएं और प्रत्येक अभिनेता अनुरोध के लिए एक पंक्ति। अभिनेता का नाम, अनुरोध इनपुट, संग्रह समय, स्थिति, और कोई भी त्रुटि विवरण संग्रहित करें। कच्चे पेलोड तालिका को उसी रन को संदर्भित करना चाहिए और एक पार्सर संस्करण रिकॉर्ड करना चाहिए।
HTTP प्रतिक्रिया प्रबंधन को सफल आवेदन प्रतिक्रियाओं को असफलताओं से अलग करना चाहिए। HTTP वृत्तांत विनिर्देश ग्राहकों और सर्वरों द्वारा उपयोग किए जाने वाले स्थिति-कोड ढांचे को परिभाषित करता है।
एक कवरेज तालिका तब तीन मूलभूत प्रश्नों के उत्तर दे सकती है:
- कौन से संस्थाएँ अनुरोध की गई थीं?
- कौन से अनुरोध उपयोगी पेलोड उत्पन्न करते हैं?
- कौन सी सामान्यीकृत तालिकाएँ प्रत्येक पेलोड से पंक्तियाँ प्राप्त करती हैं?
एक असफल पोस्ट अनुरोध को एक खाली items एरे के रूप में प्रदर्शित न करें। उन राज्यों का विश्लेषणात्मक मतलब अलग होता है।
Stage 2: Preserve Raw JSON Before Parsing
कच्ची प्रतिक्रियाएँ TikTok API से डेटाबेस कार्यप्रवाह के लिए ऑडिट परत हैं। अभिनेता का नाम, अनुरोधित इनपुट, संग्रह समय, प्रतिक्रिया JSON, और पार्सर संस्करण को एक साथ संग्रहित करें। Python की JSON दस्तावेज़ उदाहरण में उपयोग की गई क्रमण इंटरफ़ेस को परिभाषित करता है।
कच्चा भंडारण तीन व्यावहारिक उद्देश्यों की सेवा करता है:
- एक स्कीमा परिवर्तन के बाद एक पार्सर को फिर से चलाया जा सकता है।
- एक संदिग्ध सामान्यीकृत मान को उसके स्रोत फ़ील्ड तक पहुंचाया जा सकता है।
- नए फ़ील्ड को सुरक्षित पेलोड से बिना संग्रह दोहराए भरा जा सकता है।
अनुरोध मेटाडेटा लिखने से पहले रहस्यों को छुपाएं। API कुंजी प्रक्रिया कॉन्फ़िगरेशन में होती है और इसे कभी भी कच्चे पेलोड या रन तालिकाओं में नहीं आना चाहिए।
Scrapeless के साथ स्क्रैपिंग शुरू करें
Scrapeless के साथ अपनी वेब स्क्रैपिंग और स्वचालन कार्यप्रवाह को शक्ति दें!
आज साइन अप करें और $5 का मुफ्त क्रेडिट प्राप्त करें — कोई क्रेडिट कार्ड की आवश्यकता नहीं।
अपने मुफ्त क्रेडिट को Scrapeless डैशबोर्ड में अभी प्राप्त करें।
चरण 3: निर्माता, पोस्ट और उत्पाद स्नैपशॉट को सामान्य बनाना
प्राकृतिक पहचानकर्ताओं को पाठ के रूप में रखें और हर स्नैपशॉट कुंजी में collected_at शामिल करें। एक निर्माता प्रोफ़ाइल बदल सकती है, पोस्ट काउंटर बढ़ सकते हैं, और एक दुकान का उत्पाद मूल्य, स्टॉक, रेटिंग या समीक्षाओं की संख्या बदल सकता है।
मानकीकृत परत इन तालिकाओं से शुरू हो सकती है:
| तालिका | इकाई कुंजी | स्नैपशॉट फ़ील्ड |
|---|---|---|
profile_snapshots |
खाता आईडी + संग्रह समय | उपयोगकर्ता नाम, अनुयायी, पसंद, वीडियो |
post_snapshots |
पोस्ट आईडी + संग्रह समय | निर्माता आईडी, अवधि, प्ले, पसंद, टिप्पणियाँ, शेयर |
product_snapshots |
उत्पाद आईडी + क्षेत्र + संग्रह समय | नाम, मूल्य, मुद्रा, स्टॉक, रेटिंग, समीक्षा संख्या |
post_hashtags |
पोस्ट आईडी + संग्रह समय + हैशटैग | मानकीकृत टैग |
SQLite का CREATE TABLE दस्तावेज़ीकरण इस मॉडल के पीछे प्राथमिक-कुंजी और प्रकार प्रतिबंधों का वर्णन करता है।
नोट: नीचे का कोड लाइव
SCRAPELESS_API_KEYऔरTIKTOK_USERNAMEमानों की आवश्यकता करता है।TIKTOK_SHOP_PRODUCT_IDऔरTIKTOK_SHOP_REGIONवैकल्पिक हैं और दुकान शाखा को सक्षम करते हैं।
python
import json
import os
import sqlite3
import uuid
from datetime import datetime, timezone
from urllib.request import Request, urlopen
ENDPOINT = "https://api.scrapeless.com/api/v1/scraper/request"
PARSER_VERSION = "tiktok-v1"
def utc_now():
return datetime.now(timezone.utc).isoformat()
def request_actor(actor, actor_input):
body = json.dumps({"actor": actor, "input": actor_input}).encode()
request = Request(
ENDPOINT,
data=body,
headers={
"content-type": "application/json",
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
},
method="POST",
)
with urlopen(request, timeout=60) as response:
return json.load(response)
def integer(value):
try:
return int(value)
except (TypeError, ValueError):
return None
database = sqlite3.connect("tiktok-analytics.sqlite3")
database.executescript("""
CREATE TABLE IF NOT EXISTS collection_runs (
run_id TEXT NOT NULL, actor TEXT NOT NULL, collected_at TEXT NOT NULL,
request_json TEXT NOT NULL, status TEXT NOT NULL, detail TEXT,
PRIMARY KEY (run_id, actor)
);
CREATE TABLE IF NOT EXISTS raw_payloads (
run_id TEXT NOT NULL, actor TEXT NOT NULL, parser_version TEXT NOT NULL,
payload_json TEXT NOT NULL, PRIMARY KEY (run_id, actor)
);
CREATE TABLE IF NOT EXISTS profile_snapshots (
collected_at TEXT NOT NULL, account_id TEXT NOT NULL, unique_id TEXT,
followers INTEGER, likes INTEGER, videos INTEGER,
PRIMARY KEY (collected_at, account_id)
);
CREATE TABLE IF NOT EXISTS post_snapshots (
collected_at TEXT NOT NULL, post_id TEXT NOT NULL, account_id TEXT NOT NULL,
video_duration INTEGER, play_count INTEGER, like_count INTEGER,
comment_count INTEGER, share_count INTEGER,
PRIMARY KEY (collected_at, post_id)
);
CREATE TABLE IF NOT EXISTS post_hashtags (
collected_at TEXT NOT NULL, post_id TEXT NOT NULL, hashtag TEXT NOT NULL,
PRIMARY KEY (collected_at, post_id, hashtag)
);
CREATE TABLE IF NOT EXISTS product_snapshots (
collected_at TEXT NOT NULL, product_id TEXT NOT NULL, region TEXT NOT NULL,
name TEXT, sale_price TEXT, currency TEXT, available_quantity INTEGER,
rating TEXT, review_count INTEGER,
PRIMARY KEY (collected_at, product_id, region)
);
""")
run_id = str(uuid.uuid4())
collected_at = utc_now()
def collect(actor, actor_input):
request_json = json.dumps(actor_input, sort_keys=True)
try:
payload = request_actor(actor, actor_input)
database.execute(
"INSERT INTO raw_payloads VALUES (?, ?, ?, ?)",
(run_id, actor, PARSER_VERSION, json.dumps(payload, ensure_ascii=False)),
)
status, detail = "success", None
except Exception as error:
payload = None
status, detail = "failed", f"{type(error).__name__}: {error}"
database.execute(
"INSERT INTO collection_runs VALUES (?, ?, ?, ?, ?, ?)",
(run_id, actor, collected_at, request_json, status, detail),
)
return payload
profile = collect(
"scraper.tiktok.user.detail",
{"unique_id": os.environ["TIKTOK_USERNAME"]},
)
if profile:
stats = profile.get("statistics") or {}
account_id = str(profile.get("account_id") or "")
database.execute(
"INSERT INTO profile_snapshots VALUES (?, ?, ?, ?, ?, ?)",
(
collected_at, account_id, profile.get("unique_id"),
integer(stats.get("followers")), integer(stats.get("likes")),
integer(stats.get("videos")),
),
)
posts = collect(
"scraper.tiktok.user.work",
{"sec_uid": profile["sec_uid"], "cursor": "0", "count": 10},
)
if posts:
for post in posts.get("items") or []:
post_id = str(post.get("post_id") or post.get("video_id") or "")
database.execute(
"INSERT INTO post_snapshots VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
(
collected_at, post_id, account_id,
integer(post.get("video_duration")),
integer(post.get("play_count")), integer(post.get("like_count")),
integer(post.get("comment_count")), integer(post.get("share_count")),
),
)
for hashtag in set(post.get("hashtags") or []):
normalized = str(hashtag).strip().removeprefix("#").casefold()
if normalized:
database.execute(
"INSERT INTO post_hashtags VALUES (?, ?, ?)",
(collected_at, post_id, normalized),
)
product_id = os.getenv("TIKTOK_SHOP_PRODUCT_ID")
product_region = os.getenv("TIKTOK_SHOP_REGION")
if product_id and product_region:
product = collect(
"scraper.tiktok.shop.page",
{"product_id": product_id, "region": product_region},
)
if product:
price = product.get("price") or {}
stock = product.get("stock") or {}
database.execute(
"INSERT INTO product_snapshots VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
(
collected_at, str(product.get("product_id") or product_id),
str(product.get("region") or product_region).casefold(),
product.get("name"), price.get("sale_price"),
price.get("currency"), integer(stock.get("available_quantity")),
str(product.get("rating")) if product.get("rating") is not None else None,
integer(product.get("review_count")),
),
)
database.commit()
database.close()
उदाहरण केवल पहले अनुरोधित पोस्ट पृष्ठ को इकट्ठा करता है। यह पूर्ण खाता इतिहास का वादा नहीं करता है क्योंकि सत्यापित प्रतिक्रिया के परे कोई निरंतरता फ़ील्ड नहीं मानी जाती है।
चरण 4: विश्लेषण से पहले डेटा गुणवत्ता जांचें
गुणवत्ता जांच संग्रह और सामान्यीकृत परतों पर चलनी चाहिए। न्यूनतम, फ्लैग करें:
collection_runsमें असफल अभिनेता अनुरोध- सफल कच्चे पेलोड जो अपेक्षित इकाई पंक्तियों का उत्पादन नहीं करते हैं
- खाली खाता, पोस्ट, या उत्पाद आईडी
- नकारात्मक काउंटर
- अवधि विश्लेषण में शून्य या गायब वीडियो अवधि
- उत्पाद पंक्तियाँ क्षेत्र या मुद्रा संदर्भ गायब
- एक संग्रह समय के लिए डुप्लिकेट इकाई कुंजी
जांचों को कंसोल-केवल संदेशों के बजाय क्वेरी करने योग्य परिणामों के रूप में रखें। एक डैशबोर्ड तब उस मेट्रिक के बगल में कवरेज गैप दिखा सकता है जिसे यह प्रभावित करता है।
चरण 5: समय मिटाए बिना स्नैपशॉट क्वेरी करें
विंडो फ़ंक्शन प्रत्येक इकाई की उसके पिछले अवलोकन के साथ तुलना करते हैं। SQLite का विंडो-फ़ंक्शन दस्तावेज़ीकरण इस उपयोग के मामले के लिए LAG() को परिभाषित करता है।
sql
-- Illustrative follower-change query over the normalized schema.
SELECT
account_id,
collected_at,
followers,
followers - LAG(followers) OVER (
PARTITION BY account_id ORDER BY collected_at
) AS follower_change
FROM profile_snapshots;
-- Illustrative run-coverage query.
SELECT actor, status, COUNT(*) AS run_count
FROM collection_runs
GROUP BY actor, status
ORDER BY actor, status;
डैशबोर्ड के लिए वर्तमान-राज्य दृश्य का उपयोग करें जबकि अंतर्निहित तालिकाओं को केवल-जोड़ा हुआ बनाए रखें। वही पैटर्न पोस्ट काउंटर परिवर्तनों, हैशटैग रिपोर्ट, अवधि-बैंड तुलना, उत्पाद मूल्य परिवर्तनों, इन्वेंट्री घटनाओं और रेटिंग मॉनिटरिंग का समर्थन करता है।
Scrapeless टिक टोक के अभिनेताओं को Scraping API के माध्यम से प्रदान करता है। इकाई कवरेज और संग्रह की आवृत्ति चुनने से पहले वर्तमान मूल्य निर्धारण पृष्ठ की समीक्षा करें।
टिक टोक डेटा को जिम्मेदारी से संभालें
उन सार्वजनिक फ़ील्ड्स को इकट्ठा करें जो एक निर्धारित विश्लेषणात्मक उद्देश्य के लिए आवश्यक हैं, कच्चे पेलोड्स तक पहुंच को प्रतिबंधित करें, और निर्माता स्तर के डेटा के लिए रखरखाव सीमाएँ निर्धारित करें। NIST प्राइवेसी फ्रेमवर्क गोपनीयता-जोखिम शासन और डेटा न्यूनता के लिए सामान्य मार्गदर्शन प्रदान करता है।
कार्यात्मक कॉन्फ़िगरेशन को उन डेटाबेस पंक्तियों से बाहर रखें जो विश्लेषकों के साथ साझा की गई हैं। API कुंजियाँ, आंतरिक अलर्ट रूट, और पहुंच क्रेडेंशियल को एप्लिकेशन वातावरण द्वारा नियंत्रित एक सीक्रेट सिस्टम में रहना चाहिए।
निष्कर्ष: प्रत्येक मेट्रिक के बगल में कवरेज को स्पष्ट बनाएं
एक विश्वसनीय टिक टोक डेटा पाइपलाइन कच्चे JSON, रन स्थिति, पार्सर संस्करण, संग्रह समय, और स्थिर आईडी के माध्यम से जुड़े सामान्यीकृत स्नैपशॉट को बनाए रखती है। यह संरचना विश्लेषकों को वास्तविक शून्य गतिविधि को गायब संग्रह से अलग करने, फ़ील्ड परिवर्तनों के बाद पार्सर को फिर से चलाने, और हर मेट्रिक को एक अवलोकन से ट्रेस करने की अनुमति देती है। उत्पादन अनुसूची, भंडार स्केलिंग, और BI वितरण समान साक्ष्य मॉडल के चारों ओर बढ़ सकते हैं।
क्या आप TikTok विश्लेषण पाइपलाइन बनाने के लिए तैयार हैं?
स्नैपशॉट और गोदाम स्कीमाओं पर चर्चा करने के लिए Scrapeless Discord या Telegram समुदाय में शामिल हों। जब पहला इकाई सूची तैयार हो जाए तो Scrapeless डैशबोर्ड में एक खाता बनाएं।
अक्सर पूछा जाने वाला सवाल
प्रश्न: TikTok API को डेटाबेस से कैसे जोड़ा जाना चाहिए?
एक TikTok API को एक कलेक्टर के माध्यम से डेटाबेस से जोड़ा जाना चाहिए जो रन स्थिति को रिकॉर्ड करता है, कच्चे JSON को सहेजता है, फ़ील्डों को मान्य करता है, और टाइमस्टैम्प किए गए इकाई स्नैपशॉट को सम्मिलित करता है।
प्रश्न: कच्चे TikTok प्रतिक्रियाओं को क्यों संग्रहीत करें?
कच्ची TikTok प्रतिक्रियाएँ एक टीम को सामान्यीकृत मानों का पता लगाने, योजना परिवर्तनों की समीक्षा करने, और रिटेन किए गए स्रोत डेटा के खिलाफ पार्सर को फिर से चलाने की अनुमति देती हैं।
प्रश्न: क्या TikTok IDs को पूर्णांक कॉलम का उपयोग करना चाहिए?
TikTok IDs को पाठ कॉलम का उपयोग करना चाहिए क्योंकि पहचानकर्ता अप्रकाशित स्ट्रिंग होते हैं और इन्हें संख्यात्मक रूपांतरण द्वारा नहीं बदला जाना चाहिए।
प्रश्न: क्या पहले पोस्ट अनुरोध में पूर्ण खाता इतिहास होता है?
पहला पोस्ट अनुरोध पूर्ण खाता इतिहास स्थापित नहीं करता है। कवरेज संग्रहीत पृष्ठों और सत्यापित निरंतरता डेटा पर निर्भर करता है।
प्रश्न: क्या Scrapeless शेड्यूलर और डेटा वेयरहाउस का प्रबंधन करता है?
Scrapeless संग्रह के लिए संरचित अभिनेता प्रतिक्रियाएँ प्रदान करता है। कॉलर शेड्यूलिंग, डेटाबेस संचालन, रूपांतरण, गुणवत्ता निगरानी और BI डिलीवरी का प्रबंधन करता है।
प्रश्न: क्या सार्वजनिक TikTok डेटा स्क्रैप करना कानूनी है?
कानूनी स्थिति क्षेत्राधिकार, उद्देश्य, पहुँच विधि, लागू शर्तों और संग्रहित क्षेत्रों पर निर्भर करती है। अनुमति प्राप्त उद्देश्य के लिए सार्वजनिक डेटा का उपयोग करें और इच्छित पाइपलाइन के लिए कानूनी सलाह प्राप्त करें।
स्क्रैपलेस में, हम केवल सार्वजनिक रूप से उपलब्ध डेटा का उपयोग करते हैं, जबकि लागू कानूनों, विनियमों और वेबसाइट गोपनीयता नीतियों का सख्ती से अनुपालन करते हैं। इस ब्लॉग में सामग्री केवल प्रदर्शन उद्देश्यों के लिए है और इसमें कोई अवैध या उल्लंघन करने वाली गतिविधियों को शामिल नहीं किया गया है। हम इस ब्लॉग या तृतीय-पक्ष लिंक से जानकारी के उपयोग के लिए सभी देयता को कोई गारंटी नहीं देते हैं और सभी देयता का खुलासा करते हैं। किसी भी स्क्रैपिंग गतिविधियों में संलग्न होने से पहले, अपने कानूनी सलाहकार से परामर्श करें और लक्ष्य वेबसाइट की सेवा की शर्तों की समीक्षा करें या आवश्यक अनुमतियाँ प्राप्त करें।



