Мнозина смятат туитовете на Доналд Тръмп за непрезидентски. Но мнозина не са съгласни. Има ли някакъв начин да разрешите въпроса с малко помощ от Python? Сигурен!

В тази поредица от публикации ще споделя бележките си от Python семинар, който проведох за IEEE по-рано тази година. Целта на семинара беше да се завърши проект от нулата. Идеята, която ни хрумна, беше да създадем инструмент, който може да чете и анализира туитовете на Доналд Тръмп. След това можем да решим дали конкретен туит е президентски или не. Така че нека да видим какво има да каже Python за това.

Кой трябва да чете това?

Този урок е за вас, ако:

  • имате основни познания за програмиране, но не се справяте добре с Python, или
  • познавате Python, но не знаете как да го използвате, за да четете и анализирате текстови данни от мрежата.

Това е урок за начинаещи, предназначен за хора с много основни познания по програмиране.

Как да използвам този урок?

В този урок ще започнем с прост код и ще се опитаме да го подобрим, докато напредваме. Можете да копирате и поставите (или дори по-добре да го напишете сами) кода във вашия текстов редактор, да го запишете и да го стартирате в терминала или командния ред. Уверете се, че сте създали директория някъде на вашето устройство и запишете файловете там.

Когато обяснявам кода, въвеждам някои нови концепции. Трябва да прегледате официалната документация, за да разберете по-задълбочено тези концепции.

Тъй като този урок служи като странични бележки към семинара, той е доста бърз. Така че обясненията не са толкова изчерпателни, колкото можете да намерите в други уроци. Затова се уверете, че се консултирате с други ресурси или пишете коментар тук, когато се чувствате изгубени. И помнете: Google, StackOverflow и официалните документи на Python са вашите най-добри приятели.

Предпоставки

Уверете се, че имате инсталиран Python3.6 (или по-нов).

Ако сте на Mac, въведете python3.6 --version във вашия терминал. Ако сте на Windows, въведете py --version в командния ред. И в двата случая трябва да видите вашата версия на Python. Ако вместо това видите грешка или ако версията, която виждате, е по-стара от 3.6, това означава, че трябва да изтеглите и инсталирате по-новата версия.

Освен това трябва да имате добър текстов редактор. Всеки текстов редактор би свършил работа. Но препоръчвам нещо като Atom, тъй като е безплатно, с отворен код и поддържа Python веднага.

Първият подход

За да опростим нещата, нашият първи подход е да разбием един туит на думи.

Както можете да видите, копирахме ръчно един от туитовете на Тръмп, присвоихме го на променлива и използвахме метода split(), за да го разделим на думи. split() връща списък, който наричаме tweet_words. Можем да изчислим броя на елементите в списък с помощта на функцията len. В редове 4 и 5 отпечатваме резултатите от предишните стъпки. Обърнете внимание на функцията str в ред 5. Защо е там?

И накрая, в ред 9, преобръщаме tweet_words: тоест преминаваме през tweet_words елементи един по един, съхраняваме ги в w и след това работете с w в редове 10 и 11. И така, редове 10 и 11 се изпълняват много пъти, всеки с различна стойност за w. Трябва да можете да разберете какво правят редове 10 и 11.

Запазете този код в first.py. Ако сте на Mac или Linux, отидете на терминала. В папката, в която сте записали файла, въведете python3.6 first.pyи натиснете Enter. В Windows трябва да въведете py first.py в командния ред.

Вторият подход

Тук се опитваме да подобрим нашия код, така че да можем да разберем дали един туит е „лош“ или „добър“.

Идеята тук е да създадете два списъка с добри и лоши думи и да увеличите или намалите стойността на един туит въз основа на броя на думите, които съдържа от тези списъци.

И така, в редове 16 и 17 инициализираме две стойности, всяка от които представлява броя на добрите и лошите думи в един туит. В редове 19 и 20 създаваме нашите списъци с добри и лоши думи. Това, разбира се, са силно субективни списъци, така че не се колебайте да промените тези списъци въз основа на вашето лично мнение.

В ред 21 преминаваме през всяка дума в туита една по една. След като го отпечатаме на ред 22, проверяваме дали думата съществува в good_wordsили bad_wordsи увеличаваме number_of_good_wordsили number_of_bad_words съответно. Както можете да видите, за да проверим дали даден елемент съществува в списък, можем да използваме ключовата дума in.

Освен това обърнете внимание на синтаксиса на ако: трябва да въведете двоеточие (:)след условието. Освен това целият код, който трябва да се изпълни вътре в if, трябва да бъде с отстъп.

Можете ли да кажете какво правят редове 31–34?

Третият подход

Нашето предположение досега беше, че думите са или добри, или лоши. Но в реалния свят думите имат различна тежест: страхотно е по-добро от добре,илошоепо-добреотужасно . Засега нашият код не отчита това.

За да се справим с това, ние използваме структура от данни на Python, наречена речник. Речникът е списък от елементи, като всеки елемент има ключ и стойност. Ние наричаме такива елементи двойки ключ-стойност. И така, речникът е списък от двойки ключ-стойност(понякога наричан хранилище за ключ-стойност).

Можем да дефинираме речник, като поставим списък с ключ:стойноствъв фигурни скоби. Обърнете внимание на ред 16 в кода по-долу.

Както можете да видите, ние използваме само един речник. Придаваме на лошите думи отрицателна стойност, а на добрите – положителна. Уверете се, че стойностите са между -1,0 и +1,0. По-късно използваме нашия word_weightsречник в ред 23, за да проверим дали дума съществува в него, а в ред 24, за да разберем стойността, присвоена на думата. Това е много подобно на това, което направихме в предишния код.

Друго подобрение в този код е, че е по-добре структуриран: опитахме се да разделим различни логически части на кода в различни функции. Както можете да видите в редове 12 и 19, функциите са дефиниранис дефиниранаключова дума, последвана от име на функция, последвано от нула или повече аргументи в скоби. След като дефинираме тези функции, ние ги използваме в редове 29 и 30.

Четвъртият подход

Дотук добре. Но все пак има някои ясни недостатъци в нашия код. Например, можем да приемем, че едно съществително, независимо дали е единствено или множествено число, има една и съща стойност. Тук не е така. Например думите данък и данъцисе тълкуват като две отделни думи, което означава, че трябва да имаме два различни записа в нашия речник, по един за всеки. За да избегнем този вид излишък, можем да се опитаме да защитимдумите в туит, което означава да се опитаме да преобразуваме всяка дума в нейния корен. Например както данък, така и данъци ще бъдат включени в данък.

Това е много сложна задача: естествените езици са изключително сложни и изграждането на стемър отнема много време и усилия. Освен това тези задачи са изпълнявани и преди. И така, защо да изобретяваме колелото, особено толкова сложно? Вместо това ще използваме код, написан от други програмисти и пакетиран вPython модулнаречен NLTK.

Инсталиране на NLTK

Можем да стартираме pip install nltk в нашия команден ред, за да инсталираме NLTK. Това обаче ще се опита да инсталира модула в нашата система глобално. Това не е добре: може да има програми в нашата система, използващи същия модул, и инсталирането на по-нова версия на същия модул може да създаде проблеми. Освен това, ако можем да инсталираме всички модули в същата директория, където се намира нашият код, можем просто да копираме тази директория и да я стартираме на различни машини.

Затова вместо това започваме със създаването на виртуална среда.

Първо се уверете, че сте в същата папка, където се намира вашият код. След това въведете следното в терминала:

python3.6 -m venv env

и ако сте в Windows, въведете следното в командния ред:

py -m venv env

Това създава локално копие на Python и всички необходими инструменти в текущата папка.

Сега трябва да кажете на вашата система да използва това локално копие на Python. На Mac или Linux използвайте следната команда:

source env/bin/activate

И в Windows:

env\Scripts\activate

Ако сте направили всичко правилно, трябва да видите командния ред променен. Най-вероятно трябва да видите (env) в началото на вашия команден ред.

Ние използваме командата pipза инсталиране на пакети на Python. Но първо нека се уверим, че използваме най-новата версия на pipкато изпълним следната команда:

pip install --upgrade pip

И само ако сте на Mac, не забравяйте да изпълните и следната команда:

sudo "/Applications/Python 3.6/Install Certificates.command"

Сега можете безопасно да инсталирате NLTK с помощта на командата pip:

pip install nltk

И накрая, стартирайте своя интерпретатор на Python, като стартирате python (или py, ако сте на Windows) и въведете следните команди в интерпретатора:

import nltk
nltk.download()

Трябва да изскочи прозорец. Изберете елемента с популярен идентификатор и щракнете върху изтегляне. Това ще изтегли всички необходими данни, използвани от популярни NLTK модули.

Сега, след като приключихме с инсталирането на NLTK, нека го използваме в кода.

Използване на NLTK

За да използваме модул в Python, първо трябва да го импортираме. Това се прави в ред 11, където казваме на Python, че искаме да използваме функцията word_tokenize, и в ред 12, където казваме, че искаме да използваме всичко, което има в модула nltk.stem.porter.

В ред 14 създаваме stemmer обект, използвайки PorterStemmer (познайте къде е дефиниран?), а в ред 18 използваме word_tokenize вместо split, за да разбием нашия туит на думи по по-интелигентен начин.

И накрая, в ред 31 използваме stemmer.stem, за да намерим основата на думата и да я съхраним в stemmed_word. Останалата част от кода е много подобен на нашия предишен код.

Както трябва да запомните, ние използваме речник от дума към стойност в редове 20 до 24. Да имаме толкова дълъг списък от думи в нашата програма е лоша практика. Помислете за това: трябва да отваряме и редактираме нашия код всеки път, когато решим да променим речника дума към стойност (като добавяне на дума или промяна на теглото на дума). Това е проблематично, защото:

  1. Може по погрешка да променим други части от нашия код.
  2. Колкото повече думи добавяме, толкова по-малко четлив става нашият код.
  3. Различни хора, използващи един и същи код, може да искат да дефинират различни речници (напр. различен език, различни тегла, ...) и не могат да го направят, без да променят кода.

Поради тези причини (и много други) трябва да отделим данните от кода (като цяло това е добра практика). С други думи, трябва да запазим нашия речник в отделен файл и след това да го заредим в нашата програма.

Сега, както може би знаете, файловете имат различни формати, което показва как данните се съхраняват във файл. Например JPEG, GIF, PNG и BMP са различни формати на изображения, които казват как да съхраните изображение във файл. XLS и CSV също са два формата за съхраняване на таблични данни във файл.

В нашия случай искаме да съхраним структура от данни ключ-стойност. Форматът на данни JSON е най-често използваният формат на данни за съхраняване на тези видове данни. Освен това JSON е популярен формат за комуникация на данни в световната мрежа (по-късно ще видим примери за това). Ето пример за JSON файл:

{ 
  "firstName": "John",
  "lastName": "Smith",
  "age" : 25 
}

Както можете да видите, изглежда точно като речник на Python. Така че, продължете и създайте нов файл и го наречете „word_weights.json“. Ето я моята:

Сега всичко, което трябва да направим, е да кажем на Python да зареди този файл в word_weights.

Отваряне на файл

За да отворим файл, използваме функцията open. Той отваря файл и връща „файлов обект“, който ни позволява да извършваме операции с файла. Всеки път, когато отворим файл, трябва да го close. Това гарантира, че всички операции върху файловия обект се изчистват (прилагат) към файла.

Тук искаме да заредим съдържанието на файла и да го присвоим на променлива. Знаем, че съдържанието на нашия файл е във формат JSON. Така че всичко, което трябва да направим, е да импортираме модула json на Python и да приложим неговата функция load към нашия файлов обект:

Но изричното използване на close може да бъде проблематично: в голяма програма е лесно да забравите да затворите файла и може да се случи close да е в блок, който не се изпълнява през цялото време (например if).

За да избегнем подобни проблеми, можем да използваме ключовата дума with. with се грижи за затварянето на файла.

Така че, когато кодът излезе от блока with, файлът, отворен с помощта на with, се затваря автоматично. Уверете се, че винаги използвате шаблона за кодиране with, когато работите с файлове. Лесно е да забравите да затворите файл и това може да създаде много проблеми.

Обърнете внимание на редове от 22 до 24:

Можем допълнително да подобрим този код, като превърнем зареждането на JSON файлове и анализирането на туитове в две функции. Вижте редове 20–23 и 41–49:

Сега всичко, което нашата програма прави, е, че присвоява низ за туит (ред 51), зарежда речник с тежести на думите (ред 52) и анализира този низ за туит, използвайки заредения речник.

Четене на туитове от Twitter

За да четем данни от Twitter, трябва да имаме достъп до неговия API (интерфейс за програмиране на приложения). API е интерфейс към приложение, който разработчиците могат да използват за достъп до функционалността и данните на приложението.

Обикновено компании като Twitter, Facebook и други позволяват на разработчиците да имат достъп до своите потребителски данни чрез своите API. Но както може би знаете, потребителските данни са изключително ценни за тези компании. Освен това, много опасения за сигурността и поверителността влизат в действие, когато са включени потребителски данни. По този начин тези компании искат да проследяват, удостоверяват и ограничават достъпа на разработчиците и техните приложения до техния API.

Така че, ако искате да получите достъп до данни в Twitter, първо трябва да влезете в Twitter (и да се регистрирате, ако нямате акаунт в Twitter) и след това да отидете на https://apps.twitter.com/ . Щракнете върху бутона Създаване на ново приложение, попълнете формуляра и щракнете върху бутона Създайте своето приложение за Twitter.

В новата страница изберете разделаAPI ключове и щракнете върху бутона Създаване на моя маркер за достъп. Ще бъде генерирана нова двойка Маркер за достъп, Тайен маркер за достъп. Копирайте някъде тези стойности заедно с API ключаи API тайната.

Сега стартирайте терминала или командния ред, отидете в работната си директория и активирайте вашата виртуална среда (напомняне: ако сте на Mac/Linux, изпълнете . env/bin/activate и ако сте на Windows, изпълнете env/Scripts/activate). Сега инсталирайте пакета python-twitter с помощта на pip:

pip install --upgrade pip
pip install python-twitter

Това инсталира популярен пакет за работа с Twitter API в Python.

Сега, нека бързо тестваме нашата настройка.

Стартирайте своя интерпретатор на Python, като напишете python (или py, ако сте на Windows). Въведете следното и заменете YOUR_CONSUMER_KEY, YOUR_CONSUMER_SECRET, YOUR_ACCESS_TOKEN и YOUR_ACCESS_TOKEN_SECRETсъс стойностите, които сте копирали в предишната стъпка:

import twitter
twitter_api = twitter.Api(consumer_key="YOUR_CONSUMER_KEY",
                  consumer_secret="YOUR_CONSUMER_SECRET",
                  access_token_key="YOUR_ACCESS_TOKEN",
                  access_token_secret="YOUR_ACCESS_TOKEN_SECRET",
                  tweet_mode='extended')
twitter_api.VerifyCredentials()

Можем също да получим туитове на потребител, използвайки GetUserTimeline метода Twitter API. Например, за да получите последния туит от Доналд Тръмп, просто използвайте следното:

last_tweet = twitter_api.GetUserTimeline(screen_name="realDonaldTrump", count=10)

Това ще ни даде списък с един елемент, съдържащ информация за последния туит на Тръмп. Можем да получим различна информация за туита. Например last_tweet.full_text ще ни даде пълния текст на последния си туит.

Използвайки знанията, които придобихме за API на Twitter, сега можем да променим кода си, за да зареди низа за туит от Twitter. Обърнете внимание на редове от 54 до 72:

Разбира се, както беше обсъдено преди, съхраняването на данни в кода е лоша практика. Особено лошо е, когато тези данни включват някаква тайна. Но знаем как да го направим правилно, нали? И така, в ред 56 зареждаме нашите идентификационни данни за Twitter от файла .cred.json. Просто създайте нов JSON файл, съхранете вашите ключове и тайни в речник и го запазете като .cred.json:

Трябва да можете да разберете новия код, с изключение може би на ред 70. Както знаете, много туитове съдържат неазбучни знаци. Например един туит може да съдържа &, > или<. Такива символи се екранират от високочестотния високоговорител. Това означава, че Twitter преобразува тези знаци в безопасни за HTML знаци.

Например туит като Me & my best friend <3 се преобразува в Me &amp; my best friend &lt;3. За да преобразуваме това обратно в първоначалното му представяне, трябва да отменим екраниранетонашите туитове, като използваме функцията unescape от модула html. Това се случва на ред 70.

Опитайте да стартирате този код. Трябва да можете да решите дали последните туитове на Тръмп са президентски или не.

Споделете мислите си и покажете малко ❤ на тази публикация, ако желаете.

Забележка: целият код е наличен в GitHub.