تويتر ليس مجرد مصدر ممتد للأخبار، بل هو بلا شك أحد أفضل العينات لأفكار العالم. مع وجود أكثر من 330 مليون مستخدم نشط، فإنه يعد أحد أهم المنصات التي يحب الناس مشاركة أفكارهم عليها. يمكن استخدام بيانات تويتر لمجموعة متنوعة من الأغراض مثل الأبحاث, آراء المستهلكين, الرؤى الديموغرافية، وغيرها الكثير.
وبالتالي، فإن الهدف الأساسي من هذا البرنامج التعليمي هو تعليمك كيفية الحصول على عينة من بيانات تويتر ذات الصلة بمشروعك أو عملك التجاري.
قبل المتابعة، تأكد من أن جميع هذه المتغيرات متوفرة لديك:
- Consumer Key
- Consumer Secret
- Access Token
- Access Token Secret
إذا كنت تريد معرفة كيفية الحصول على التفاصيل المذكورة أعلاه، فاقرأ منشور المدونة هذا الذي كتبه زميلي Dattatray Upase.
الآن لنبدأ بكتابة بعض الكود!
تحديد متغيرات الإدخال
أولاً، عليك تحديد بعض المتغيرات العامة التي ستحتاجها للبرنامج:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import sys start_date = sys.argv[1] #"2018-01-09" end_date = sys.argv[2] #"2018-01-10" consumerKey="Enter_Your_Consumer_Key_Here" consumerSecret="Enter_Your_Consumer_Secret_Here" accessToken="Enter_Your_Access_Token_Here" accessTokenSecret="Enter_Your_Access_Token_Secret_Here" keyword= sys.argv[3] #"tcs" lang="en" #شاهد ما يقدمه تويتر لتصفية اللغة data={} |
أقوم باستيراد ‘sys’ للحصول على وسيطات سطر الأوامر، لأنني قد أرغب في تغيير الكلمات الرئيسية أو تاريخ البدء أو تاريخ الانتهاء. بالنسبة للغة، اخترت اللغة الإنجليزية، ولكن قد ترغب في التحقق من اللغات الأخرى المدعومة. سيتم تخزين النتائج في ‘data’ في النهاية.
ونتيجة لذلك، سيكون الاستخدام النموذجي للبرنامج النصي على النحو التالي:
python script.py start_date end_date keyword
الوصول إلى واجهة برمجة تطبيقات تويتر (Twitter API)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import oauth2 req_count = 0 def oauth_req(url, http_method="GET", post_body=b"", http_headers=None): global req_count,consumerKey,consumerSecret,accessToken,accessTokenSecret req_count += 1 consumer = oauth2.Consumer(key=consumerKey, secret=consumerSecret) token = oauth2.Token(key=accessToken, secret=accessTokenSecret) client = oauth2.Client(consumer, token) resp, content = client.request( url, method=http_method, body=post_body , headers=http_headers ) return content |
إن المتغير req_count هو عدد المرات التي استخدمت فيها واجهة برمجة التطبيقات في تنفيذ برنامجي. أواجه الخطأ التالي مع الكود البرمجي المقدم:
TypeError: Unicode-objects must be encoded before hashing
لتجنب ذلك، أقوم بتغيير post_body=”” to post_body=b”” وهذا يحل المشكلة.
استخدام واجهة برمجة تطبيقات تويتر ومراجعها
لقد حان الوقت لتعيين عنوان URL لواجهة برمجة التطبيقات للحصول على بيانات تويتر. أنا أستخدم المعلمة min_faves. إليك شرح عنوان URL وبعض حيل التحسين:
‘min_faves’ يُستخدم لتحديد الحد الأدنى لعدد التفضيلات التي يجب أن تحصل عليها التغريدة في البيانات. إنها ميزة مفيدة للغاية ولكن لم يتم ذكرها في وثائق Twitter API.
‘q’ يمثل الاستعلام أو الكلمات الرئيسية التي تريد إدخالها. هنا من المهم التأكد من إدخال أقل عدد ممكن من الكلمات الرئيسية. على سبيل المثال، دعنا نتخيل أنني أريد تغريدات حول Facebook و Google. إذا قمت بإدخال كليهما ككلمات رئيسية، مثل FACEBOOK و GOOGLE، فلن يعيد لي سوى 100 تغريدة كحد أقصى، لأن هذا قيود مفروضة. ولكن إذا قمت بتشغيل الاستعلام مرتين – مرة مع Facebook ومرة مع Google، فيمكنني الحصول على إجمالي 200 تغريدة. باختصار، من الأفضل استخدام كلمة رئيسية واحدة لكل استعلام.
‘lang’ يمثل لغة التغريدات التي تمت تصفيتها. نظرًا لأنني أريد الحصول على التغريدات باللغة الإنجليزية، فإنني أقوم بضبطه على ‘en’.
‘since’ هو تاريخ بدء الفترة التي تريد البحث عن التغريدات فيها. يجب أن يكون تاريخ البدء هذا من الأيام السبعة الماضية. هذه ميزة أخرى غير موثقة في وثائق Twitter API.
‘until’ يمثل تاريخ انتهاء الفترة المطلوبة. منطقيًا، يجب أن يكون أيضًا من الأيام السبعة الماضية. وهو أيضًا غير موثق في وثائق Twitter API.
‘result_type’ يمثل نوع التغريدات التي تريدها. وله 3 قيم:
‘recent’ يعطي أحدث التغريدات، أي التغريدات في نهاية الفترة المحددة.
‘popular’ يعطي التغريدات الأكثر شعبية وبالتالي فإنه يفوت الكثير من التغريدات. ستحصل دائمًا على التغريدات التي تحظى بأكبر عدد من التفضيلات وإعادات التغريد. الـ min_faves لن تكون ذات فائدة هنا.
‘mixed’ يعطي مزيجًا من التغريدات الحديثة والشعبية.
‘count’ يمثل الحد الأقصى لعدد التغريدات في النتيجة. القيمة الافتراضية هي 15 والحد الأقصى هو 100.
مع الـ result_type المختلط واستخدام min_faves، يمكننا الحصول على الحد الأقصى من التغريدات عن طريق تشغيل الاستعلام عدة مرات.
|
1 2 3 |
def get_tweets(min_faves): global keyword, start_date, end_date, lang return oauth_req( 'https://api.twitter.com/1.1/search/tweets.json?' + '&q=' + keyword + '&lang=' + lang + '%20since%3A' + start_date + '%20until%3A' + end_date + '%20min_faves%3A' + str(min_faves) +'&result_type=mixed&count=100') |
لمزيد من الميزات الموثقة، يمكنك أيضًا الاطلاع على وثائق Twitter’s API.
حفظ/حفظ تلقائي لبيانات التغريدات المستردة
كخطوة تالية، تحتاج إلى تحديد طريقة حفظ تلقائي/حفظ تحتوي على المعلمة ‘saveOverride’. هذه الخطوة مطلوبة ببساطة لإزالة قيود وقت الحفظ التلقائي وحفظ الملف. للقيام بذلك، أقوم بإنشاء t_last لحفظ وقت بدء البرنامج. ثم أقوم بالوصول إلى نفس المتغير في البرنامج والتحقق مما إذا كان قد مر 5 دقائق منذ t_last (آخر وقت حفظ). إذا مر أكثر من 5 دقائق، أقوم بتعيين ‘saveStatus’ كـ True.
بعد ذلك، أتحقق من ‘saveOverride’، مما يعني ببساطة أنني بحاجة إلى إعطاء تعليمات لبرنامجي بأنه بغض النظر عن أي شيء، يجب حفظ الملف الآن. لهذا، قمت بتعيين saveStatus ليكون True.
ثم إذا كان ‘saveStatus’ هو True، فسيقوم السكربت بتغيير t_last إلى الوقت الحالي. بعد ذلك، يقوم الكود بإنشاء كائن قاموس ويطبع “حفظ تلقائي في [time]” حتى تعرف أنه يتم حفظ البيانات تلقائيًا.
بعد ذلك، أتحقق مما إذا كان ملف المخرجات موجودًا بالفعل. إذا كان موجودًا، أقوم بدمج البيانات والبيانات من ملف تم حفظه بالفعل. بعد الدمج، أقوم بكتابتها في نفس الملف. إذا لم يكن موجودًا، أقوم بإنشاء ملف جديد ثم كتابة البيانات في هذا الملف.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import os import json import time import datetime t_last = time.time() def autosave(saveOverride = False): global t_last saveStatus = (time.time() > t_last + 300) if(saveOverride == True):en" saveStatus = True if(saveStatus): t_last=time.time() tmp = {} print("Autosave at " + str(datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S"))) fnamea = keyword + "-st-" + start_date + "-ed-"+ end_date + '.json' if os.path.exists(fnamea) == True: with open(fnamea,'r+') as f: tmp = json.load(f) for i in data.keys(): tmp[i] = data[i] with open(fnamea,'w+') as f: json.dump(tmp,f) |
نتيجة لذلك، قمت ببرمجة كامل الوظائف التي أردتها تقريبًا.
مزيد من التحسين
أخيرًا، حان الوقت للاستفادة من هذه الدوال. أنا أكتب حلقة while(1) والتي تعني while(True). هذا يجعل التعليمات البرمجية تعمل إلى الأبد بشكل أساسي حتى يتم استدعاء عبارة ‘break’ أو حدوث استثناء.
أولاً، أقوم بجمع بيانات التغريدات في القاموس ‘d’ باستخدام json.loads والذي يحول البيانات إلى تنسيق قاموس. ثم أقوم بتشغيل try-catch/except على كتلة البرمجة التي تستخرج الحالات من البيانات. أستخدم try-catch لأن واجهة برمجة تطبيقات Twitter لا تعيد أحيانًا بيانات بل ملف JSON يذكر الخطأ. لا أريد أن يتوقف برنامجي في مثل هذه الحالات. أيضًا، أريده أن يسترجع رقم الطلب الذي يحدث عنده ذلك وحفظ بيانات Twitter الخاصة بي باستخدام أمر الحفظ التلقائي (autosave). يتيح لنا Twitter تقديم 180 طلبًا كل 15 دقيقة. هذا يعادل 12 طلبًا في الدقيقة أو طلبًا واحدًا كل خمس ثوانٍ. ولأكون آمنًا، أضيف أمر sleep لجعل برنامجي ينام لمدة 5 ثوانٍ بعد تنفيذ تكرار واحد.
بعد ذلك، سيعرض الكود عدد التغريدات التي جمعها السكربت حتى الآن.
أخيرًا، حان الوقت لحيلة التحسين الرئيسية. كنت أختبر هذا السكربت لمدة أسبوع تقريبًا وحصلت على عدد التغريدات التالي لكل قيمة min_faves . يمكنني الحصول على 100 تغريدة كحد أقصى لكل طلب وأريد الحصول على أكبر عدد ممكن. حاليًا، لا توجد العديد من التغريدات ذات القيم الأعلى لـ min_faves ولكننا نريد مراعاة الأوقات التي قد تكون فيها الشركة أو الكلمة المفتاحية شائعة (trending). القيمة القصوى لـ min_faves يمكن أن تكون 999999.
| قيمة min_faves | عدد التغريدات |
| 100,000 | 1 |
| 90,000 | 1 |
| 80,000 | 1 |
| 70,000 | 2 |
| 60,000 | 3 |
| 50,000 | 6 |
| 40,000 | 6 |
| 30,000 | 12 |
| 25,000 | 12 |
لذلك، أنا أستخدم منطقًا يجلب التغريدات من قيمة min_faves البالغة 60000 ثم يقللها بمقدار 10000 في كل مرة حتى تصل إلى 10000. ولكن إذا افترضنا أن الكلمة المفتاحية شائعة وحصلت على 100 تغريدة عندما أعمل بقيمة min_faves لتكون 30000، فسيؤدي ذلك إلى زيادة min_faves إلى 35000 ثم الحصول على النتائج مرة أخرى. لذا فإن المنطق الجديد الآن هو 5000 بدلاً من 10000. ومع ذلك، إذا انخفض التغيير إلى أقل من 1000، فإنني أطلب منه التجاهل والمضي قدماً في طرح 1000.
أقوم بتحديد فاصل زمني ثابت قدره 1000 والذي min_faves يجب أن ينخفض بمقداره إذا كان min_faves أقل من أو يساوي 10000.
في نهاية البرنامج، سيخبرك البرنامج أن العمل قد تم من خلال عرض ‘End’.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
min_faves=60000 change=10000 #تقليل كبير في min_faves لاستخراج البيانات interval = 500 #تقليل عادي في min_faves لاستخراج البيانات while(1): d = json.loads(get_tweets(min_faves)) try: for i in d['statuses']: data[i['id']] = i c = len(d['statuses']) except Exception as e: print("خطأ عند الطلب: " + str(req_count)) autosave(True) print("عند الطلب: " + str(req_count) + " إجمالي التغريدات التي تم جمعها: " + str(len(data)) + " مع الحد الأدنى للمفضلة: " + str(min_faves) ) if c==100 and min_faves>10000: if (change>1000): change /= 2 min_faves += change else: min_faves -= change elif min_faves>10000: min_faves -= change else: min_faves -= interval if(min_faves < 0): fnamea = keyword + '.json' autosave(True) break autosave() time.sleep(5) print("End") |
يمكنك العثور على الكود بالكامل على GitHub.
هذا كل شيء. في الدرس التعليمي القادم لبيانات تويتر، سأعلمك كيفية استرداد التغريدات في الوقت الفعلي باستخدام أداة البيانات الضخمة ‘Flume’. تابعنا!
التعليقات
لا توجد تعليقات بعد. كن أول من يعلق.