در این آموزش، نحوه استفاده از Python برای تشخیص Cannibalzation کلمات کلیدی را بررسی خواهیم کرد و به شما این امکان را میدهیم که این سیستم را به طور موثر در گردشهای کاری SEO خود بگنجانید.
مخزن GitHub: github.com/jmelm93/seo_cannibalization_analysis
این پست نسبت به آموزشی که مدتی قبل به اشتراک گذاشته بودیم، بهبود یافته است.
Cannibalization کلمات کلیدی SEO چیست؟
آدم خواری کلمات کلیدی سئو زمانی اتفاق می افتد که URL های متعدد در یک وب سایت، هدف یکسان کاربر را برآورده کند، بنابراین باعث می شود آنها برای رتبه بندی کلمات کلیدی ارگانیک با یکدیگر رقابت کنند.
این یک چالش رایج در دنیای بهینه سازی موتورهای جستجو است.
برای اطلاعات بیشتر در مورد مفهوم آدمخواری کلمه کلیدی، بررسی کنید این پست از وبلاگ Ahrefs – کلمه کلیدی آدمخواری: واقعاً چیست و چگونه آن را برطرف کنیم.
چالش های تکنیک های تجزیه و تحلیل آدم خواری
در حالی که آدم خواری کلمات کلیدی یک مفهوم شناخته شده در جامعه SEO است، اکثر تکنیک های شناسایی مسائل دارای اشکالات قابل توجهی هستند.
به عنوان مثال، متداولترین روش مورد استفاده شامل بررسی پرسوجوها با صفحات متعددی است که کلیکها و نمایشهایی را برای یک جستار منحصر به فرد دریافت میکنند. با این حال، این رویکرد اغلب نتایج گمراه کننده ای به همراه دارد، زیرا عوامل کلیدی مانند حجم ترافیک در صفحات و اهمیت یک پرس و جو خاص در هدایت ترافیک کلی به صفحه داده شده را نادیده می گیرد.
برای پرداختن به این چالشها، من یک اسکریپت پایتون را توسعه دادهام که رویکرد مرسوم را با چندین لایه بررسی بهبود میبخشد تا تعیین کند آیا آدمخواری کلمات کلیدی وجود دارد یا خیر و آیا ادغام صفحات همپوشانی راهحل مناسبی است یا خیر.
ابزار انسان خواری کلمات کلیدی رایگان
برای هر کسی که با برنامه نویسی پایتون راحت نیست، من این فرآیند را به صورت رایگان در seoworkflows.com/tools/opportunity/keyword-cannibalization-checker در دسترس قرار داده ام.
این به گونه ای طراحی شده است که برای کاربران غیر فنی قابل دسترسی باشد و به شما این امکان را می دهد که مسائل مربوط به آدم خواری کلمات کلیدی را بدون دردسر شناسایی کرده و به آنها رسیدگی کنید.
توضیح ساده فرآیندهای پایتون
بخش 1: پردازش و پاکسازی اولیه داده در پایتون
در مرحله اول اسکریپت، با تمیز کردن و آماده سازی داده ها برای تجزیه و تحلیل شروع می کنیم. این به ما کمک می کند تا زمینه را برای تجزیه و تحلیل آدم خواری سئو فراهم کنیم و زمینه را برای تجزیه و تحلیل بیشتر فراهم کنیم.
در اینجا آنچه در طول این مرحله اتفاق می افتد آمده است:
- خواندن داده ها: ما داده های کنسول جستجوی گوگل (GSC) را از یک فایل CSV می خوانیم.
- حذف کلمات کلیدی مارک دار: ما هر گونه تغییر کلمه کلیدی مارک دار را از مجموعه داده حذف می کنیم تا روی کلمات کلیدی غیر مارک تمرکز کنیم.
- فیلتر کردن کلمات کلیدی: ما مجموعه داده را فیلتر می کنیم تا فقط کلیدواژه هایی را شامل شود که حداقل دو صفحه باعث کلیک روی یک کلمه کلیدی هدف می شوند.
بخش 2: ساخت بخش های سطح کلمه کلیدی
بخشهای سطح کلمه کلیدی برای شناسایی فرصتهای ادغام بسیار مهم هستند. در این قسمت از اسکریپت، دو بخش ایجاد و استفاده می کنیم:
- ‘clicks_pct_vs_query‘: این بخش درصد کلیک هایی که هر صفحه برای یک کلمه کلیدی خاص دریافت می کند را محاسبه می کند.
- ‘clicks_pct_vs_page‘: این بخش درصد کلیک های صفحه اصلی مرتبط با یک کلمه کلیدی را محاسبه می کند.
این بخشها به ما کمک میکنند تا بفهمیم آیا ادغام صفحات ایده خوبی است یا خیر.
آنها بینش هایی را در مورد میزان همپوشانی در سطح کلمه کلیدی ارائه می دهند و کمک می کنند تا اطمینان حاصل شود که صفحات به شدت تحت تأثیر کلمه کلیدی هدف قرار می گیرند.
ما همچنین یک ستون جدید به نام “نظر” ایجاد می کنیم که بر اساس منطق زیر با “فرصت بالقوه” یا “ریسک” پر شده است:
منطق: اگر ‘clicks_pct_vs_query‘ بزرگتر یا مساوی 10 درصد است و ‘clicks_pct_vs_page‘ بزرگتر یا مساوی 10٪ است، سپس به عنوان a علامت گذاری می شود ‘فرصت بالقوه‘. در غیر این صورت، به عنوان یک برچسب گذاری شده است ‘خطر‘.
به عبارت سادهتر، این منطق به ما میگوید که اگر یک کلمه کلیدی تعداد قابل توجهی کلیک را هم برای کلمه کلیدی منفرد و هم برای کل صفحه ایجاد کند، ممکن است یک فرصت بالقوه برای یکپارچهسازی وجود داشته باشد.
قسمت 3: پاکسازی و ساخت مجموعه داده نهایی
مجموعه دادههای ساخته شده در طول پردازش دادههای اولیه و تقسیمبندی در سطح کلمه کلیدی را برای شناسایی فرصتهای فوری SEO و نوشتن مجموعه دادههای نهایی در خروجی خود میگیریم.
این چیزی است که اتفاق می افتد:
- شناسایی فرصت های فوری: برای تسریع اقدامات سئو، با انتخاب ردیفهایی که ستون «نظر» بهعنوان «فرصت بالقوه» علامتگذاری شده است، «فرصتهای فوری» را مشخص میکنیم و اطمینان حاصل میکنیم که حداقل دو ردیف برای یک کلمه کلیدی وجود دارد. این سیگنال یک فرصت ادغام قوی با کاهش ریسک است.
- تولید خروجی نهایی: مجموعه داده ها سازماندهی و مرتب می شوند در حالی که معیارهای عددی گرد هستند. سپس مجموعه داده های نهایی شده در خروجی نهایی نوشته می شوند.
خروجی های مورد انتظار
این اسکریپت یک فایل اکسل با چندین برگه تولید میکند که هر کدام شامل مجموعه دادههای مختلفی برای استفاده برای تجزیه و تحلیل است:
- ‘all_potential_opps‘: این شامل مجموعه داده ایجاد شده در قسمت 1: پردازش و تمیز کردن داده های اولیه است، که در آن مجموعه داده برای همه کلمات کلیدی که حداقل 2 صفحه با کلیک دارند فیلتر می شود.
- ‘high_likelihood_opps‘: این پرسوجوها را با صفحات متعددی که بهعنوان «فرصتهای بالقوه» علامتگذاری شدهاند، فهرست میکند، بر اساس منطق توضیح داده شده در قسمت 2: ساخت بخشهای سطح کلمه کلیدی.
- ‘risk_qa_data‘: این داده های سطح پرس و جو را برای صفحاتی که در صفحه نمایش داده می شوند فراهم می کندall_potential_oppsبرگه
فرآیند گام به گام برای اجرای اسکریپت
- مخزن کد (لینک مخزن GitHub) را در دستگاه محلی خود شبیه سازی یا دانلود کنید.
- مجموعه داده صفحه پرس و جو را از API کنسول جستجوی گوگل دانلود کنید.
- راه های مختلفی برای انجام این کار وجود دارد، مانند استفاده از Search Analytics برای Sheets یا ابزار رایگان GSC API Data Extractor در SEO Workflows.
- متغیرهای پیکربندی را در بالای فایل main.py به روز کنید.
- نیازمندی ها را دانلود کنید.
- من استفاده از یک محیط مجازی را توصیه می کنم (منبع: Python Virtual Environments)
- «python main.py» را در فهرست اصلی پروژه اجرا کنید.
شکست کد
بیایید به اجزای جداگانه اسکریپت بپردازیم:
متغیرهای پیکربندی
- ‘EXPORT_NAME‘: پیشوند فایل خروجی تولید شده را تعریف می کند.
- ‘محل فایل‘: مکان جستجوی صفحه CSV کنسول جستجوی Google.
- ‘BRAND_VARIANTS‘: فهرست انواع نام های تجاری برای حذف از تجزیه و تحلیل.
وظیفه اصلی: شغل
این تابع تمام مراحل بالا را با هم ترکیب می کند، به طور متوالی داده ها را پردازش می کند و در ایجاد مجموعه داده خروجی نهایی به اوج خود می رسد.
def job(file_location, brand_variants):
"""
Main function for the job.
"""
print('-- Start: Creating primary analysis df')
initial_df = pd.read_csv(file_location)
non_brand_df = initial_df
not_empty_spaces = all([brand_variant != '' for brand_variant in brand_variants])
if brand_variants and not_empty_spaces:
non_brand_df = remove_brand_queries(initial_df, brand_variants)
query_page_counts = calculate_query_page_metrics(non_brand_df)
query_counts = filter_queries_by_clicks_and_pages(query_page_counts)
wip_df = merge_and_aggregate(query_page_counts, query_counts)
wip_df = calculate_click_percentage(wip_df)
wip_df = filter_by_click_percentage(wip_df)
wip_df = merge_with_page_clicks(wip_df, initial_df)
wip_df = define_opportunity_levels(wip_df)
final_df = sort_and_finalize_output(wip_df)
print('-- End: Creating primary analysis df')
print('-- Start: Creating supporting dfs')
qa_df = create_qa_dataframe(initial_df, final_df)
immediate_opps_df = immediate_opps(final_df)
instructions_df = create_instructions_df()
print('-- End: Creating supporting dfs')
dict_of_dfs = {
"instructions": instructions_df,
"all_potential_opps": final_df,
"high_likelihood_opps": immediate_opps_df,
"risk_qa_data": qa_df
}
print('-- Start: Creating excel file')
create_excel_file(dict_of_dfs, EXPORT_NAME)
print('-- End: Creating excel file')
return "Job complete!"
توابع کمکی
1. remove_brand_queries
این تابع هرگونه درخواست جستجویی را که شامل انواع برند باشد مستثنی می کند. پارامتر ‘brand_variants’ فهرستی از کلیدواژه های مارک دار است، و اینها می توانند منطبقات جزئی را شامل شوند (به عنوان مثال، کلمه جزئی “exam” می تواند با “مثال” مطابقت داشته باشد).
قطعه کد پایتون
def remove_brand_queries(df, brand_variants):
"""
Remove queries that contain brand variants.
"""
df = df[~df['query'].str.contains('|'.join(brand_variants))]
print("'|'.join(brand_variants)", '|'.join(brand_variants))
return df
2. account_query_page_metrics
این تابع دادهها را در سطح جستجوی صفحه گروهبندی و جمعآوری میکند و مواردی را حذف میکند که در آن ابعاد مختلف مانند «تاریخ» یا «دستگاه» منجر به چندین نمونه از یک ترکیب جستجوی صفحه میشود.
قطعه کد پایتون
def calculate_query_page_metrics(df):
"""
Calculate metrics for each combination of "query" and "page".
"""
query_page_counts = df.groupby(['query', 'page']).agg({
'clicks': 'sum',
'impressions': 'sum',
'position': 'mean'
}).reset_index()
query_page_counts = query_page_counts.rename(columns={'position': 'avg_position'})
return query_page_counts
3. filter_queries_by_clicks_and_pages
این تابع یک مجموعه داده حاوی داده های صفحه پرس و جو را می گیرد، آن را بر اساس پرس و جوها گروه بندی می کند و تعداد صفحات مجزا و کل کلیک ها را برای هر پرس و جو محاسبه می کند.
سپس پرسوجوها را فیلتر میکند تا فقط شامل مواردی شود که حداقل دو صفحه مجزا و حداقل یک کلیک دارند، و مجموعه دادهای را با این نتایج جستجوی تصفیهشده برمیگرداند.
قطعه کد پایتون
def filter_queries_by_clicks_and_pages(query_page_counts):
"""
Filter queries based on the click condition and distinct pages.
"""
query_counts = query_page_counts.groupby('query').agg({
'page': 'nunique',
'clicks': 'sum'
}).reset_index()
query_counts = query_counts[(query_counts['page'] >= 2) & (query_counts['clicks'] >= 1)]
return query_counts
4. merge_and_agregate
این تابع داده های دو مجموعه داده را ترکیب و خلاصه می کند.
ابتدا مجموعه داده “query_page_counts” را با مجموعه ای فیلتر شده از پرس و جوها از “query_counts” ادغام می کند و فقط عبارت های منطبق را حفظ می کند تا اطمینان حاصل شود که ما فقط به کلمات کلیدی با بیش از 2 صفحه که باعث کلیک می شود نگاه می کنیم.
سپس، این داده های ادغام شده را گروه بندی می کند و تجمیع های لازم را برای معیارهای موجود برای استفاده بعدی فراهم می کند.
قطعه کد پایتون
def merge_and_aggregate(query_page_counts, query_counts):
"""
Merge metrics and join with filtered queries.
"""
df = query_page_counts.merge(query_counts[['query']], on='query', how='inner')
df = df.groupby(['page', 'query']).agg({
'clicks': 'sum',
'impressions': 'sum',
'avg_position': 'mean'
}).reset_index()
return df
5. محاسبه_کلیک_درصد
این تابع درصد کلیکهایی را که یک ترکیب جستجوی صفحه خاص از کل کلیکهای آن پرسوجو دریافت میکند، محاسبه میکند.
برای مثال، اگر صفحه مثال A 10 کلیک برای کلمه کلیدی مثال A دریافت کند، و کلمه کلیدی مثال A در مجموع 100 کلیک در تمام صفحات وب سایت جمع کند، ردیف داده برای مثال صفحه A/Keyword Example A یک ‘clicks_pct_vs_query’ را نشان می دهد. 0.10، نشان دهنده 10٪ از کل کلیک ها برای آن پرس و جو است.
قطعه کد پایتون
def calculate_click_percentage(df):
"""
Calculate percentage of clicks for each page per query.
"""
df['clicks_pct_vs_query'] = df.groupby('query')['clicks'].transform(lambda x: x / x.sum())
return df
6. فیلتر_با_کلیک_درصد
این تابع با انتخاب کلمات کلیدی که حداقل 10٪ از کل کلیک ها برای آن کلمه کلیدی بین حداقل دو صفحه مختلف توزیع شده است، مجموعه داده را اصلاح می کند.
هدف شناسایی نگرانیهای واقعی سئو خواری است، جایی که چندین صفحه برای کلیک رقابت میکنند. بنابراین، کلمات کلیدی با یک صفحه غالب که بیشترین کلیک ها را به همراه دارد از مجموعه داده حذف می شوند.
قطعه کد پایتون
def filter_by_click_percentage(df):
"""
Identify and filter by queries that meet specific conditions.
Only keep queries that have at least 2 pages with 10% or more clicks
"""
queries_to_keep = df[df['clicks_pct_vs_query'] >= 0.1].groupby('query').filter(lambda x: len(x) >= 2)['query'].unique()
df = df[df['query'].isin(queries_to_keep)]
return df
7. merge_with_page_clicks
این تابع دادههای کلیک در سطح صفحه را در مجموعه دادههای کاری ترکیب میکند و درصد کلیکهایی را که یک ترکیب جستجوی صفحه خاص از کل کلیکهای آن صفحه دریافت میکند، محاسبه میکند.
به عنوان مثال، اگر صفحه مثال A 10 کلیک برای کلمه کلیدی مثال A دریافت کند، و صفحه مثال A در کل 500 کلیک در تمام پرس و جوها جمع آوری کند، ردیف داده برای مثال صفحه A/کلمه کلیدی مثال A یک ‘clicks_pct_vs_page’ 0.02 را نشان می دهد، که نشان می دهد 2٪ از کل کلیک ها.
قطعه کد پایتون
def merge_with_page_clicks(wip_df, initial_df):
"""
Merge with page-level click metrics and calculate percentage metrics.
"""
page_clicks = initial_df.groupby('page').agg({'clicks': 'sum'}).reset_index()
wip_df = wip_df.merge(page_clicks, on='page', how='inner')
wip_df['clicks_pct_vs_page'] = wip_df['clicks_x'] / wip_df['clicks_y']
wip_df = wip_df.rename(columns={'clicks_x': 'clicks_query', 'clicks_y': 'clicks_page'})
return wip_df
8. سطوح_فرصت را تعریف کنید
یک ستون «نظر» جدید بر اساس معیارهای «clicks_pct_vs_query» و «clicks_pct_vs_page» ایجاد میکند که هر ترکیب صفحه-پرس و جو را بهعنوان «فرصت بالقوه» یا «ریسک» طبقهبندی میکند.
این ستون بعد اصلی است که برای تجزیه و تحلیل استفاده می شود تا بفهمیم آیا ادغام صفحات منطقی است یا خیر.
قطعه کد پایتون
def define_opportunity_levels(wip_df):
"""
Create 'comment' column based on 'clicks_pct_vs_query' and 'clicks_pct_vs_page'.
"""
wip_df['comment'] = np.where(
(wip_df['clicks_pct_vs_query'] >= 0.1) & (wip_df['clicks_pct_vs_page'] >= 0.1),
'Potential Opportunity',
'Risk - Low percentage of either query-level or page-level clicks'
)
return wip_df
9. immediate_opps
این تابع “فرصت های فوری” را از DataFrame ورودی (final_df) شناسایی و استخراج می کند.
این کار را با انتخاب ردیفهایی انجام میدهد که در آن ستون «نظر» بهعنوان «فرصت بالقوه» علامتگذاری شده است و اطمینان حاصل میکند که حداقل دو ردیف برای یک کلمه کلیدی وجود دارد.
به این دلیل که داشتن حداقل دو ردیف برای یک کلمه کلیدی که به عنوان “فرصت بالقوه” مشخص شده است، نشانگر یک فرصت ادغام قوی با درجه ریسک کمتر است.
قطعه کد پایتون
def immediate_opps(final_df):
"""
If 2+ pages for a query are marked as 'Potential Opportunity,' then return those rows as they're 'Immediate Opportunities.'
"""
return final_df[final_df['comment'] == 'Potential Opportunity'].groupby('query').filter(lambda x: len(x) >= 2)
نتیجه
در نتیجه، می توان از این اسکریپت جامع برای رسیدگی به چالش های مرتبط با رویکردهای مرسوم برای شناسایی آدم خواری کلمات کلیدی استفاده کرد.
با تقویت تجزیه و تحلیل با چندین لایه بررسی و اصلاح روش، اسکریپت درک دقیقتر و دقیقتری از مسائل آدمخواری ارائه میدهد. این به متخصصان سئو قدرت می دهد تا تصمیمات آگاهانه ای در مورد تلفیق و بهینه سازی کلمات کلیدی بگیرند.
در صورت داشتن هر گونه سوال در تماس باشید!
بنیانگذار seoworkflows.com، معاون SEO در DEPT. با تجربه در تیم ها و استراتژی های سئو برای بیش از 100 برند. همچنین در مهندسی پایگاه داده و توسعه تمام پشته مهارت دارد.