شما 20,000 نقد محصول را اسکرپ میکنید تا ببینید کدام شکایتها بیشتر تکرار میشوند. قرار بود فقط امتیاز و متن را نگه دارید. وقتی فایل CSV را باز میکنید، نام نویسندگان، لینک صفحه پروفایل آنها و در چند صد نقد، نشانی ایمیل یا شماره تلفنی هم در آن هست که نویسنده در متن نوشته است. هیچکدام از اینها به تحلیل کمکی نمیکند، اما حالا روی لپتاپ شما و در نسخه پشتیبان دیشب نشسته است.
این نوشته توضیح میدهد در یک مجموعهداده اسکرپشده چه چیزی داده شخصی به شمار میرود (که اغلب با نام PII یعنی personally identifiable information یا «اطلاعات هویتی شخصی» شناخته میشود؛ یعنی هر چیزی که به فردی مشخص اشاره کند)، چرا «عمومی بود» پاسخ پرسش نیست و چگونه باید با آن رفتار کرد: کمتر گردآوری کنید، آنچه از دستتان در میرود را بپوشانید، کلیدهای لازم را با نام مستعار جایگزین کنید و طبق برنامه حذف کنید. همچنین نشان میدهد چرا هش کردن ایمیل ضعیفتر از آن است که به نظر میرسد، یک اسکریپت آزموده پایتون برای پوشاندن داده ارائه میکند و به GDPR، قانون KVKK در Türkiye و CCPA در کالیفرنیا ارجاع میدهد.
در یک مجموعهداده اسکرپشده چه چیزی داده شخصی است؟
تعریف GDPR در بند 1 ماده 4 گسترده است: هر اطلاعاتی که به یک شخص حقیقیِ شناساییشده یا قابل شناسایی مربوط باشد، بهطور مستقیم یا غیرمستقیم، با نمونههایی مانند نام، شماره شناسایی، داده مکانی و شناسه آنلاین. قانون شماره 6698 حفاظت از دادههای شخصی Türkiye (KVKK) در ماده 3 خود از همان تعبیر اصلی استفاده میکند.
در یک پروژه اسکرپینگ، داده شخصی در سه جا پیدا میشود:
- فیلدهایی که عمداً انتخاب کردهاید. نام نویسنده، نام کاربری، نشانی پروفایل، تصویر نمایه، عنوان شغلی در صفحه یک شرکت، نام فروشنده در یک بازارگاه آنلاین.
- متن آزاد. نقدها، نظرها، پستهای انجمن و توضیحات آگهی، جایی که مردم ایمیل، شماره تلفن، نام خیابان یا پلاک خودروی خود را مینویسند.
- لاگهای خود شما. لاگ درخواستها و خروجی خطاها اغلب HTML کامل صفحه را نگه میدارند، با همه موارد بالا.
دشوارتر از همه، فیلدهایی است که بهتنهایی کسی را شناسایی نمیکنند. یک نام کاربری، یک شهر، یک تاریخ و یک محصول کمیاب با هم میتوانند به یک نفر اشاره کنند؛ پس مجموعهدادهای که ستون «نام» ندارد هم ممکن است داده شخصی داشته باشد.
آیا «عمومی» یعنی آزاد برای استفاده؟
بهطور کلی نه، و پاسخ از قانونی به قانون دیگر فرق میکند.
- GDPR. هیچ استثنایی برای دادههای شخصیِ در دسترس عموم وجود ندارد. داده اسکرپشده همچنان به مبنای قانونی نیاز دارد و باید از اصول ماده 5 پیروی کند. ماده 14 تعیین میکند در برابر کسانی که دادهشان را از جایی جز خودشان به دست آوردهاید چه تعهداتی دارید.
- KVKK. ماده 5 شرایط پردازش بدون رضایت صریح را برمیشمارد. یکی از آنها این است که خود شخص داده را عمومی کرده باشد. این یک چک سفید امضا نیست: اصول ماده 4، مانند هدف مشخص و تناسب، همچنان پابرجاست.
- CCPA. تعریف کالیفرنیا از اطلاعات شخصی در Civil Code 1798.140 نشانی IP و ایمیل را جزو شناسهها میآورد و سپس اطلاعات «publicly available» (در دسترس عموم) را مستثنا میکند، با تعریفی محدود: مثلاً سوابق دولتی یا اطلاعاتی که خود مصرفکننده در دسترس عموم قرار داده است.
پرسش حقوقی گستردهتر، از جمله شرایط استفاده و حق نشر، در نوشته آیا اسکرپینگ وب قانونی است؟ بررسی شده است.
مدیریت داده شخصی در یک پایپلاین اسکرپینگ
ماده 25 GDPR «حفاظت از داده در طراحی و بهطور پیشفرض» را میخواهد: تدابیر حفاظتی بخشی از طراحیاند، نه یک کار پاکسازی در پایان. همراه با اصل «کمینهسازی داده» در ماده 5، برای یک اسکرپر این یعنی:
- هدف را بنویسید. «یافتن رایجترین شکایتهای مربوط به ارسال برای هر محصول» یک هدف است. «گردآوری نقدها برای اینکه شاید به کار بیایند» هدف نیست.
- فیلدهایی را که به هدف خدمت میکنند فهرست کنید. برای مثال بالا: محصول، تاریخ، امتیاز و متن. نام نویسنده و نشانی پروفایل در فهرست نیستند.
- هنگام گردآوری فیلتر کنید. چیزی را که استفاده نمیکنید انتخاب نکنید.
- متن آزاد را هنگام دریافت بپوشانید. ایمیلها و شماره تلفنها را پیش از آنکه ردیف در جایی نوشته شود با جاینگهدار جایگزین کنید.
- کلیدهای لازم را با نام مستعار جایگزین کنید. اگر باید نویسندگان تکراری را بشمارید، بهجای شناسه نویسنده هش کلیددار آن را نگه دارید.
- کلید را جدا نگه دارید. کلید ناممستعارسازی در یک مدیر اسرار یا متغیر محیطی نگهداری میشود، هرگز در مجموعهداده یا همان مخزن کد.
- فضای ذخیرهسازی را ایمن کنید. داده ذخیرهشده را رمزنگاری کنید، دسترسی را به افرادی که روی پروژه کار میکنند محدود کنید و خروجیهای خام را از درایوهای اشتراکی دور نگه دارید.
- طبق برنامه حذف کنید. HTML خام و فایلهای پوشاندهنشده دوره نگهداری کوتاهی دارند؛ مجموعهداده پاکشده دوره خودش را دارد که به هدف گره خورده است.
- آنچه انجام دادهاید را ثبت کنید. هدف، فیلدها، دوره نگهداری و مبنای قانونی، در یک یادداشت کوتاه.
پوشاندن، ناممستعارسازی و ناشناسسازی: تفاوت چیست؟
این اصطلاحها جایگزین یکدیگر نیستند و همین تفاوت تعیین میکند که آیا قانون هنوز بر داده شما حاکم است یا نه.
| روش | چه میکند | آیا میتوان شخص را دوباره شناسایی کرد؟ | آیا هنوز داده شخصی است؟ |
|---|---|---|---|
| حذف هنگام گردآوری | فیلد هرگز ذخیره نمیشود | نه، داده وجود ندارد | نه، برای آن فیلد |
| پوشاندن (masking) | مقدار را با جاینگهداری مانند [EMAIL] جایگزین میکند | نه از روی مقدار پوشاندهشده، اما شاید از روی فیلدهای دیگر | بستگی دارد در ردیف چه مانده باشد |
| ناممستعارسازی (pseudonymization) | شناسه را با یک توکن جایگزین میکند؛ پیوند در اطلاعاتی جداگانه و محافظتشده است | بله، با کلید یا جدول تطبیق | بله (بند مقدماتی 26 GDPR) |
| ناشناسسازی (anonymization) | داده را آنقدر حذف یا کلی میکند که هیچکس با ابزارهایی که بهطور معقول محتملاند شناسایی نشود | نه | نه |
| رمزنگاری | داده را بدون کلید ناخوانا میکند | بله، برای هر کسی که کلید دارد | بله |
| تجمیع | فقط شمارش، میانگین یا گروهها را نگه میدارد | فقط اگر گروهها بسیار کوچک باشند | معمولاً نه، اگر گروهها به اندازه کافی بزرگ باشند |
GDPR درباره ناممستعارسازی چه میگوید؟
بند 5 ماده 4 ناممستعارسازی را پردازش داده شخصی به شیوهای تعریف میکند که دیگر نتوان آن را «بدون استفاده از اطلاعات اضافی» به یک شخص معین نسبت داد، به این شرط که آن اطلاعات جداگانه نگهداری و محافظت شود. بند مقدماتی 26 سپس مرز را روشن میکند: دادهای که با نام مستعار جایگزین شده و با اطلاعات اضافی قابل نسبت دادن به یک شخص است، باید اطلاعاتی درباره یک شخص حقیقیِ قابل شناسایی به شمار آید. اطلاعات ناشناس بیرون از دامنه این مقررات است.
برای تشخیص اینکه آیا کسی قابل شناسایی است، بند مقدماتی 26 از شما میخواهد «همه ابزارهایی را که بهطور معقول احتمال استفاده از آنها میرود» در نظر بگیرید، چه از سوی کنترلکننده داده و چه از سوی هر شخص دیگر، از جمله هزینه، زمان و فناوری در دسترس. به همین دلیل ناشناسسازی متن اسکرپشده دشوار است: حذف نام کمتر فایده دارد وقتی نقد هنوز شهر، تاریخ و مدل خودرو را ذکر میکند.
هیئت حفاظت از داده اروپا رهنمود 01/2025 درباره ناممستعارسازی را در ژانویه 2025 تصویب کرد. پیشنهاد «Digital Omnibus» کمیسیون اروپا در نوامبر 2025 شیوه اعمال تعریف داده شخصی بر دادههای ناممستعارشده را تغییر میدهد؛ طبق صفحه قطار قانونگذاری پارلمان اروپا، این پیشنهاد هنگام نگارش این نوشته هنوز تصویب نشده بود. تا وقتی تغییری لازمالاجرا نشده، داده ناممستعارشده را داده شخصی بدانید.
KVKK ناممستعارسازی را تعریف نمیکند. ماده 3 آن ناشناسسازی را اینگونه تعریف میکند: داده را به شکلی درآوردن که «حتی با تطبیق با دادههای دیگر» به هیچ شخصی پیوند نخورد؛ و ماده 7 حذف، نابودی یا ناشناسسازی داده را پس از برطرف شدن دلیل پردازش الزامی میکند.
چرا هش کردن ایمیل ناشناسسازی نیست
یک میانبر رایج این است که sha256(email) را اجرا کنند و ستون را ناشناس بنامند. این ستون ناشناس نیست، به دو دلیل.
نخست، هش همیشه یکسان است. هر کسی که فهرستی از نشانیهای ایمیل دارد، مثلاً فهرستی که در یک نشت اطلاعات بیرون آمده، میتواند همه نشانیهای آن را هش کند و به دنبال تطابق بگردد؛ در آزمون ما یک فهرست حدس دوتایی نشانی «ناشناس» را فوراً پیدا کرد. همین فهرستهای نشتکرده خوراک credential stuffing هم هستند، و این دلیل دیگری است برای اینکه ایمیلهای خامی را که لازم ندارید نگه ندارید.
دوم، فضای جستوجوی برخی شناسهها کوچک است. شماره تلفن داخلی تعداد ارقام محدودی دارد، پس هش کردن همه شمارههای ممکن در آن بازه با سختافزار معمولی شدنی است و توکنِ منطبق شماره را برمیگرداند.
آنچه بهتر کار میکند:
- هش کلیددار (HMAC) با یک کلید مخفی که دور از داده نگهداری میشود. نتیجه داده ناممستعارشده است، نه ناشناس.
- یک توکن تصادفی و یک جدول تطبیق که جداگانه نگهداری میشود، اگر به برگرداندن نگاشت نیاز دارید.
- هیچ شناسهای، اگر فقط به شمارش نیاز دارید. اول تجمیع کنید و کلید را کنار بگذارید.
نمونه پایتون: پوشاندن ایمیل و شماره تلفن
این اسکریپت یک فایل CSV از نقدهای اسکرپشده را میخواند و نسخهای پاکشده مینویسد: ستونهای غیرلازم را حذف میکند، ایمیل و شماره تلفن را در ستون متن آزاد میپوشاند و شناسه نویسنده را با هش کلیددار جایگزین میکند تا همچنان بتوان نویسندگان تکراری را شمرد. فقط از کتابخانه استاندارد استفاده میکند و با Python 3.13 آزموده شده است.
import csv
import hashlib
import hmac
import os
import re
# Columns we never need for the analysis: drop them on ingest
DROP_COLUMNS = {"author_name", "profile_url"}
# Column we keep only as a pseudonym, to count repeat reviewers
PSEUDONYM_COLUMN = "author_id"
# Free-text columns where people type contact details; structured columns stay untouched
TEXT_COLUMNS = {"text"}
EMAIL_RE = re.compile(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}")
# Phone-like runs: optional + or (, then 9-15 digits with spaces, dots, dashes or brackets between them
PHONE_RE = re.compile(r"(?<!\w)[+(]?\d(?:[\s.()-]*\d){8,14}(?!\w)")
# The key lives outside the dataset (env var, secrets manager), never in the same file
SECRET = os.environ.get("PSEUDONYM_KEY", "").encode()
def mask_text(text: str) -> str:
text = EMAIL_RE.sub("[EMAIL]", text)
return PHONE_RE.sub("[PHONE]", text)
def pseudonym(value: str) -> str:
# Keyed hash (HMAC-SHA256): without the key, nobody can rebuild the mapping by hashing guesses
return hmac.new(SECRET, value.encode(), hashlib.sha256).hexdigest()[:16]
def clean_row(row: dict) -> dict:
out = {}
for col, value in row.items():
if col in DROP_COLUMNS:
continue
if col == PSEUDONYM_COLUMN:
out[col] = pseudonym(value)
elif col in TEXT_COLUMNS:
out[col] = mask_text(value)
else:
out[col] = value
return out
def main(src: str, dst: str) -> None:
if not SECRET:
raise SystemExit("Set PSEUDONYM_KEY first")
with open(src, newline="", encoding="utf-8") as f_in, \
open(dst, "w", newline="", encoding="utf-8") as f_out:
reader = csv.DictReader(f_in)
fields = [c for c in reader.fieldnames if c not in DROP_COLUMNS]
writer = csv.DictWriter(f_out, fieldnames=fields)
writer.writeheader()
for row in reader:
writer.writerow(clean_row(row))
if __name__ == "__main__":
main("reviews_raw.csv", "reviews_clean.csv")آن را با کلیدی که در محیط تنظیم شده اجرا کنید (export PSEUDONYM_KEY=... در لینوکس و macOS و $env:PSEUDONYM_KEY="..." در PowerShell) و سپس python mask_pii.py را بزنید. در نمونه ساختگی ما، Call me on +90 532 000 00 00 or (0212) 000-0000 به Call me on [PHONE] or [PHONE] تبدیل شد، ایمیلها به [EMAIL] تبدیل شدند و دو نقد یک نویسنده توکن یکسانی گرفتند.
محدودیتها را بشناسید:
- عبارت باقاعده بیش از حد میپوشاند. در آزمونهای ما الگوی تلفن یک ISBN سیزدهرقمی، یک شماره سفارش دهرقمی و تاریخی را که همراه ساعت نوشته شده بود هم پوشاند. به همین دلیل اسکریپت فقط به ستونهای متن آزاد دست میزند.
- عبارت باقاعده همه چیز را نمیگیرد. شمارههایی که با حروف نوشته شدهاند، «name at domain dot com»، شماره IBAN، نشانیها و نامهای درون متن شناسایی نمیشوند؛ برای اینها به یک مدل تشخیص موجودیتهای نامدار یا بازبینی دستی یک نمونه نیاز است.
- پوشاندن ناشناسسازی نیست. ردیف هنوز متن، تاریخ و محصول را دارد؛ بررسی کنید که آیا همینها بهتنهایی میتوانند به یک شخص اشاره کنند.
این مرحله را همان جایی اجرا کنید که ردیفها برای نخستین بار نوشته میشوند، نه بهعنوان کاری در مرحله بعد. راهنمای پاکسازی با pandas نشان میدهد این مرحله در یک پاکسازی کامل کجا قرار میگیرد و ذخیره دادههای اسکرپینگ در CSV، JSON و SQLite به ذخیرهسازی میپردازد.
امنیت ذخیرهسازی، دسترسی و نگهداری
ماده 32 GDPR امنیتی «متناسب با خطر» میخواهد و از ناممستعارسازی و رمزنگاری، سامانههای تابآور، بازیابی داده پس از رخداد و آزمون منظم نام میبرد. ماده 12 KVKK تکلیف مشابهی تعیین میکند. برای یک اسکرپر این یعنی:
- رمزنگاری داده ذخیرهشده برای دیسکها، باکتها و پایگاههای دادهای که خروجی خام اسکرپ را نگه میدارند.
- منطقههای جدا. HTML خام و ردیفهای پوشاندهنشده در یک جای محدود؛ مجموعهداده پاکشده جایی که تحلیلگران کار میکنند.
- کمترین دسترسی. فقط افراد و حسابهای سرویسی که به منطقه خام نیاز دارند بتوانند آن را بخوانند.
- نگهداری بهصورت کد. یک کار زمانبندیشده حذف از یک سند سیاستنامه کارآمدتر است.
- نسخههای پشتیبان هم حساب میشوند. فایلی که در نسخه پشتیبان یک سال پیش زنده مانده حذف نشده است. دو دوره نگهداری را با هم هماهنگ کنید.
صفحه امنیت داده ما به کاربرد پروکسیها در کارهای امنیتی میپردازد؛ پروکسی IP مبدأ درخواست را تغییر میدهد، نه آنچه را ذخیره میکنید.
این موضوع کجا پیش میآید
- پایش قیمت و موجودی. صفحههای محصول بهندرت داده شخصی دارند، اما نام فروشندگان در بازارگاهها ممکن است داشته باشد. نوشته رصد قیمت رقبا را ببینید.
- تحلیل نقدها و تحلیل احساسات. فیلدهای نویسنده و اطلاعات تماس درون متن. صفحه تحقیقات بازار را ببینید.
- پژوهش و دادهکاوی. پستهای انجمنها پر از داده شخصیاند؛ زود تجمیع کنید. نوشته دادهکاوی را ببینید.
- خزشهای بزرگ. یک وب کراولر عمومی صفحهها را کامل گردآوری میکند، پس اگر فیلتر نکنید هر چه در آنهاست به فضای ذخیرهسازی شما میرسد.
- فهرست مشتریان بالقوه. گردآوری اطلاعات تماس افراد برای بازاریابی پرخطرترین مورد در این فهرست است؛ پیش از هر کاری قانون و شرایط استفاده سایت را بررسی کنید.
اشتباههای رایج
- اسکرپ کردن کل صفحه «برای احتیاط» و نگه داشتن خروجی خام برای همیشه.
- «ناشناسشده» نامیدن SHA-256 یک ایمیل.
- نگه داشتن کلید ناممستعارسازی در همان مخزن کد یا باکتی که داده در آن است.
- پوشاندن جدول تحلیل اما نه لاگها، خروجی خطاها یا HTML اشکالزدایی.
- نادیده گرفتن
robots.txtو شرایط استفاده سایت به این بهانه که داده «بههرحال عمومی است». فایل robots.txt میگوید صاحب سایت به خزندهها اجازه دریافت چه چیزی را میدهد. - نگه داشتن داده پس از پایان پروژه چون هیچکس مسئول حذف آن نیست.
- فرض اینکه قوانین کشور خودتان حاکم است، در حالی که افراد درون مجموعهداده جای دیگری زندگی میکنند.
راهنمای انتخاب
| نیاز | توصیه |
|---|---|
| تحلیل قیمت، موجودی یا داده محصول | فیلدهای فروشنده یا کاربر را اصلاً گردآوری نکنید |
| تحلیل متن نقدها یا نظرها | فیلدهای نویسنده را حذف کنید و اطلاعات تماس درون متن را هنگام دریافت بپوشانید |
| شمارش نویسندگان تکراری یا دنبال کردن یک حساب در طول زمان | هش کلیددار (HMAC) شناسه، با کلیدی که جداگانه نگهداری میشود |
| به اشتراک گذاشتن مجموعهداده با مشتری یا انتشار آن | تجمیع کنید، سپس گروههای کوچک و ترکیبهای کمیاب را بررسی کنید |
| نگه داشتن HTML خام برای اشکالزدایی | نگهداری کوتاه، منطقه محدود، رمزنگاریشده |
| هدف، خودِ اطلاعات تماس افراد است | دست نگه دارید و پیش از گردآوری مشاوره حقوقی بگیرید |
پرسشهای متداول
آیا داده عمومیِ اسکرپشده از GDPR مستثناست؟
نه. GDPR هیچ استثنای کلی برای دادههای شخصیِ در دسترس عموم ندارد. همچنان به مبنای قانونی نیاز دارید، ماده 5 همچنان اعمال میشود و ماده 14 اطلاعاتی را پوشش میدهد که به افرادی بدهکارید که دادهشان را از خودشان گردآوری نکردهاید.
آیا نشانی IP داده شخصی است؟
میتواند باشد. GDPR در بند 1 ماده 4 از شناسههای آنلاین نام میبرد و CCPA عبارت «Internet Protocol address» (نشانی IP) را در میان نمونههای شناسه آورده است. در اسکرپینگ این موضوع بیشتر درباره لاگهای خود شما اهمیت دارد.
آیا هش کردن داده را ناشناس میکند؟
نه. هش ساده یک ایمیل یا شماره تلفن را میتوان با هش کردن فهرستی از حدسها برگرداند. هش کلیددار با کلید مخفیای که جای دیگری نگهداری میشود ناممستعارسازی است و GDPR همچنان آن را داده شخصی میداند.
KVKK درباره دادهای که خود شخص عمومی کرده چه میگوید؟
ماده 5 پردازش بدون رضایت صریح را در صورتی مجاز میداند که خود شخص داده را عمومی کرده باشد. اصول ماده 4، مانند هدف مشخص و تناسب، همچنان پابرجاست.
داده شخصیِ اسکرپشده را تا چه مدت میتوانم نگه دارم؟
فقط تا وقتی که هدف به آن نیاز دارد. ماده 5 GDPR این را «محدودیت ذخیرهسازی» مینامد و ماده 7 KVKK پس از برطرف شدن دلیل پردازش، حذف، نابودی یا ناشناسسازی را الزامی میکند.
آیا استفاده از پروکسی تعهدات من را تغییر میدهد؟
نه. پروکسی درخواستها را از یک نشانی IP دیگر عبور میدهد. این کار تغییری در آنچه گردآوری میکنید، جایی که آن را ذخیره میکنید یا قوانینی که اعمال میشوند نمیدهد.
خلاصه
داده شخصی بهندرت به این دلیل وارد مجموعهداده اسکرپشده میشود که کسی آن را خواسته باشد؛ همراه صفحه میآید. راهحل بیشتر مهندسی است: هدف را مشخص کنید، فقط فیلدهایی را گردآوری کنید که به آن خدمت میکنند، آنچه را به متن آزاد راه پیدا میکند بپوشانید، کلیدها را با یک راز که جای دیگری نگهداری میشود با نام مستعار جایگزین کنید، فضای ذخیرهسازی را رمزنگاری کنید و طبق برنامه حذف کنید. داده ناممستعارشده در GDPR همچنان داده شخصی است؛ ناشناس یعنی هیچکس با ابزارهایی که بهطور معقول محتملاند قابل شناسایی نباشد. برای بخش گردآوری، صفحه اسکرپینگ داده وب را ببینید: پروکسی مسکونی امکان هدفگیری کشور و شهر را میدهد، پروکسی چرخشی درخواستها را پخش میکند و صفحه خدمات پروکسی ما همه محصولات را فهرست میکند.




