<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Twitter API Archives - relataly.com</title>
	<atom:link href="https://www.relataly.com/category/rest-apis/twitter-api/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.relataly.com/category/rest-apis/twitter-api/</link>
	<description>The Business AI Blog</description>
	<lastBuildDate>Sun, 13 Aug 2023 10:53:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://www.relataly.com/wp-content/uploads/2023/04/cropped-AI-cat-Icon-White.png</url>
	<title>Twitter API Archives - relataly.com</title>
	<link>https://www.relataly.com/category/rest-apis/twitter-api/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">175977316</site>	<item>
		<title>How to Automatize your Twitter News Account with OpenAI ChatGPT and NewsAPI in Python</title>
		<link>https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/</link>
					<comments>https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/#comments</comments>
		
		<dc:creator><![CDATA[Florian Follonier]]></dc:creator>
		<pubDate>Fri, 05 May 2023 22:15:20 +0000</pubDate>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Generative AI]]></category>
		<category><![CDATA[Language Generation]]></category>
		<category><![CDATA[NewsAPI]]></category>
		<category><![CDATA[OpenAI]]></category>
		<category><![CDATA[Twitter API]]></category>
		<category><![CDATA[Use Cases]]></category>
		<category><![CDATA[AI in E-Commerce]]></category>
		<category><![CDATA[Intermediate Tutorials]]></category>
		<guid isPermaLink="false">https://www.relataly.com/?p=13581</guid>

					<description><![CDATA[<p>It&#8217;s no secret that Large Language Models (LLMs) are a powerful tool for automating social media tasks. Not only can they be used to curate relevant content that matches your audience&#8217;s interests, but also can they create the content and tailor them to the interests of your customers. This article describes how to create a ... <a title="How to Automatize your Twitter News Account with OpenAI ChatGPT and NewsAPI in Python" class="read-more" href="https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/" aria-label="Read more about How to Automatize your Twitter News Account with OpenAI ChatGPT and NewsAPI in Python">Read more</a></p>
<p>The post <a href="https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/">How to Automatize your Twitter News Account with OpenAI ChatGPT and NewsAPI in Python</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">It&#8217;s no secret that Large Language Models (LLMs) are a powerful tool for automating social media tasks. Not only can they be used to curate relevant content that matches your audience&#8217;s interests, but also can they create the content and tailor them to the interests of your customers. This article describes how to create a Twitter News Bot such as the one that now automates sharing news updates on the <a href="https://twitter.com/relataly" target="_blank" rel="noreferrer noopener">relataly Twitter channel</a>. The bot uses the NewsAPI and OpenAI&#8217;s chatGPT 3.5 model to retrieve and share relevant news updates. This tutorial will equip you with the skills to build a similar Twitter News Bot in Python that provides news on your own Twitter account.</p>



<p class="wp-block-paragraph">We&#8217;ll start by exploring NewsAPI and show you how to use it to fetch news articles from various sources. Then we&#8217;ll use OpenAI to enhance the bot&#8217;s capabilities. By refining the news selection process and generating engaging tweets using ChatGPT, you can ensure your updates are unique, informative, and captivating. We&#8217;ll provide clear explanations and code samples to help you succeed. By the end, you&#8217;ll have a powerful News Bot that can deliver curated news updates fully automated. But the best thing is that it is so efficient that you can run it in the cloud almost for free. So, let&#8217;s dive in and get started on creating an impressive NewsBot using OpenAI and NewsAPI in Python!</p>



<p class="wp-block-paragraph">This is what the posts from the bot look like: </p>



<figure class="wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter"><div class="wp-block-embed__wrapper">
<a class="twitter-timeline" data-width="1200" data-height="1000" data-dnt="true" href="https://twitter.com/relataly?ref_src=twsrc%5Etfw">Tweets by relataly</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div><figcaption class="wp-element-caption">The <a href="https://twitter.com/relataly" target="_blank" rel="noreferrer noopener">Relataly Twitter Account</a> runs the Same News Bot described in this tutorial. It leverages a serverless cloud architecture based on <a href="https://azure.microsoft.com/en-us/products/functions/?ef_id=_k_Cj0KCQjw9deiBhC1ARIsAHLjR2A0tS1xzElZhulEEeVKkLO8dxOiEFDJTsiiYvoZCCz3rLJU_LzOfQoaAuGGEALw_wcB_k_&amp;OCID=AIDcmmtg9dwtad_SEM__k_Cj0KCQjw9deiBhC1ARIsAHLjR2A0tS1xzElZhulEEeVKkLO8dxOiEFDJTsiiYvoZCCz3rLJU_LzOfQoaAuGGEALw_wcB_k_&amp;gclid=Cj0KCQjw9deiBhC1ARIsAHLjR2A0tS1xzElZhulEEeVKkLO8dxOiEFDJTsiiYvoZCCz3rLJU_LzOfQoaAuGGEALw_wcB" target="_blank" rel="noreferrer noopener">Azure Functions</a>.</figcaption></figure>



<p class="wp-block-paragraph">Also relevant: </p>



<ul class="wp-block-list">
<li><a href="https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/" target="_blank" rel="noreferrer noopener">Posting Tweets On Twitter using Python and Tweepy</a></li>



<li><a href="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/" target="_blank" rel="noreferrer noopener">Automate Crypto Trading with a Python-Powered Twitter Bot and Gate.io Signals</a></li>
</ul>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h2 class="wp-block-heading">The Architecture of the Twitter NewsBot</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">Let&#8217;s begin with an overview of what the NewsBot looks like. The illustration below shows the architecture.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="1385" height="921" data-attachment-id="13616" data-permalink="https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/image-2-15/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2023/05/image-2.png" data-orig-size="1385,921" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-2" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2023/05/image-2.png" src="https://www.relataly.com/wp-content/uploads/2023/05/image-2.png" alt="" class="wp-image-13616" srcset="https://www.relataly.com/wp-content/uploads/2023/05/image-2.png 1385w, https://www.relataly.com/wp-content/uploads/2023/05/image-2.png 300w, https://www.relataly.com/wp-content/uploads/2023/05/image-2.png 512w, https://www.relataly.com/wp-content/uploads/2023/05/image-2.png 768w" sizes="(max-width: 1237px) 100vw, 1237px" /><figcaption class="wp-element-caption">The architecture of the Relataly News Bot. </figcaption></figure>



<p class="wp-block-paragraph">The modular architecture of the bot makes it easy to deploy as microservices to the cloud, just like relataly does with Azure functions. This approach also makes it simple to customize the bot by changing topics or defining a different style for the tweet creation process.</p>



<h3 class="wp-block-heading">Fetching News</h3>



<p class="wp-block-paragraph">The bot is scheduled to run regularly, typically every hour. During each call, it retrieves the latest news articles from the NewsAPI. The NewsAPI allows filtering for specific categories: </p>



<ul class="wp-block-list">
<li>business entertainment</li>



<li>general</li>



<li>health</li>



<li>science</li>



<li>sports</li>



<li>technology</li>
</ul>



<p class="wp-block-paragraph">The news bot only news related to &#8220;technology.&#8221; However, this is not specific enough, as we only want to retrieve news related to AI, data science, and Machine Learning. To address this, we rely on OpenAI to determine which news is relevant. ChatGPT provides us with a list that identifies the relevant news with True and irrelevant news with False. In addition, the bot tracks which news articles have already been shared in a CSV file. This ensures that the same news is not shared multiple times.</p>



<h3 class="wp-block-heading">Creating News Tweets</h3>



<p class="wp-block-paragraph">Once we have the relevant news, the bot hands over the information to the second component responsible for creating the tweets. For each post, the bot makes an API call to OpenAI GPT, which generates a tweet based on a prompt that combines the article title, description, and URL. The resulting tweet is then sent to the Twitter API, which adds it to the account&#8217;s feed.</p>



<p class="wp-block-paragraph">By automating the process of sharing news updates on Twitter, you can save time and focus on more important tasks. Additionally, using OpenAI to generate engaging tweets can help increase social media engagement and attract more followers.</p>



<p class="wp-block-paragraph">Also: </p>



<ul class="wp-block-list">
<li><a href="https://www.relataly.com/eliminating-friction-how-openais-gpt-streamlines-online-experiences-and-reduces-the-need-for-google-searches/13171/">Using LLMs (OpenAI’s ChatGPT) to Streamline Digital Experiences</a></li>



<li><a href="https://www.relataly.com/building-a-digital-ai-assistant-for-your-software-application/14056/">Building a Virtual AI Assistant (aka Copilot) for Your Software Application: Harnessing the Power of LLMs like ChatGPT</a></li>
</ul>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<h2 class="wp-block-heading">Customization Options</h2>



<p class="wp-block-paragraph">You can easily customize the bot by changing the relevant topics or by defining another style in which OpenAI creates the tweets. By automating the process of sharing news updates on Twitter, you can save time and focus on more essential tasks. Additionally, using OpenAI to generate engaging tweets can help increase your social media engagement and attract more followers. In the next section, let&#8217;s look at the APIs used in this architecture and how you gain access. </p>



<p class="wp-block-paragraph">Also: <a href="https://www.relataly.com/chatgpt-style-guide-understanding-voice-and-tone-options-for-engaging-conversations/13065/" target="_blank" rel="noreferrer noopener">ChatGPT Style Guide: Understanding Voice and Tone Prompt Options for Engaging Conversations</a></p>



<h2 class="wp-block-heading">APIs used in this Tutorial</h2>



<p class="wp-block-paragraph">To use the functionalities of our application, you will need to obtain the following API keys: NewsAPI, OpenAI API, and Twitter API. Without an API key, the API calls will lead to an error, so there is no way around signing up.</p>



<h3 class="wp-block-heading">NewsAPI.org API</h3>



<p class="wp-block-paragraph">The <a href="http://www.newsapi.org" target="_blank" rel="noreferrer noopener">NewsAPI </a>provides access to over 30,000 news sources from around the world, including major news organizations such as CNN, BBC, and Reuters. We will walk you through how to specify criteria such as sources, keywords, and categories to retrieve relevant news articles. The free tier allows you to retrieve a certain number of news for free. </p>



<p class="wp-block-paragraph">The NewsAPI key provides access to news articles and headlines from various sources. To obtain the API key, you can sign up for a NewsAPI account on their website at <a href="https://newsapi.org/">NewsAPI Registration</a> and generate a unique key specifically for your application.</p>



<h3 class="wp-block-heading">OpenAI API</h3>



<p class="wp-block-paragraph">The OpenAI API key is required to leverage the power of artificial intelligence and natural language processing provided by OpenAI. You can obtain an API key by signing up for an OpenAI account at <a href="https://openai.com/" target="_blank" rel="noreferrer noopener">OpenAI Registration</a> and following their documentation to generate the key associated with your account. </p>



<p class="wp-block-paragraph">While OpenAI provides powerful language models through its API, it is important to note that there is a cost associated with using the GPT model that depends on the amount of text and the model type you are using. In this tutorial, we will be using the chatGPT turbo model, which is highly cost-efficient. Because we only process tiny bits of text, each inference typically costs a fraction of a cent. However, the amount might increase if you adjust the code and process more text. Check the <a href="https://openai.com/pricing" target="_blank" rel="noreferrer noopener">OpenAI pricing site</a> for the latest price information. </p>



<p class="wp-block-paragraph">To give you an idea, my monthly openai costs for running the bot are between less than 2 $: </p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" data-attachment-id="13684" data-permalink="https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/image-4-7/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2023/05/image-4.png" data-orig-size="1019,872" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-4" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2023/05/image-4.png" src="https://www.relataly.com/wp-content/uploads/2023/05/image-4-512x438.png" alt="To give you an idea, my monthly openai costs for running the bot are between less than 2 $" class="wp-image-13684" style="width:734px;height:628px" width="734" height="628" srcset="https://www.relataly.com/wp-content/uploads/2023/05/image-4.png 512w, https://www.relataly.com/wp-content/uploads/2023/05/image-4.png 300w, https://www.relataly.com/wp-content/uploads/2023/05/image-4.png 768w, https://www.relataly.com/wp-content/uploads/2023/05/image-4.png 1019w" sizes="(max-width: 734px) 100vw, 734px" /></figure>



<h3 class="wp-block-heading">Twitter Developer API</h3>



<p class="wp-block-paragraph">Finally, you will need to obtain Twitter API keys to interact with the Twitter API and perform actions such as posting tweets. These include the API key, API secret key, access token, and access token secret. You can obtain these keys by creating a Twitter Developer account at <a href="https://developer.twitter.com/" target="_blank" rel="noreferrer noopener">Twitter Developer Portal</a>, setting up a new application, and generating the required keys within the Twitter Developer dashboard. It can take some days until your application gets approved, but the good thing is that a basic tier allows you to create up to 1500 tweets for free.</p>



<p class="wp-block-paragraph">Once you have obtained these API keys, you can securely store them in a secure storage solution like Azure Key Vault, as shown in the code example. This ensures that your keys remain confidential and allows your application to access the necessary services seamlessly.</p>



<p class="wp-block-paragraph">Also: <a href="https://www.relataly.com/access-remote-data-sources-using-rest-apis-in-python/278/" target="_blank" rel="noreferrer noopener">Accessing Remote Data Sources via REST APIs in Python</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-large is-resized"><img decoding="async" data-attachment-id="13618" data-permalink="https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/flo7up_several_post_envelopes_that_have_the_twitter_bird_on_the_e048c6dc-a940-4045-a0c0-a54d0298232b-min/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_several_post_envelopes_that_have_the_twitter_bird_on_the_e048c6dc-a940-4045-a0c0-a54d0298232b-min.png" data-orig-size="1028,1016" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Flo7up_several_post_envelopes_that_have_the_twitter_bird_on_the_e048c6dc-a940-4045-a0c0-a54d0298232b-min" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_several_post_envelopes_that_have_the_twitter_bird_on_the_e048c6dc-a940-4045-a0c0-a54d0298232b-min.png" src="https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_several_post_envelopes_that_have_the_twitter_bird_on_the_e048c6dc-a940-4045-a0c0-a54d0298232b-min-512x506.png" alt="The relataly Twitter news bot leverages and integrates the following APIs: NewsAPI, OpenAI, and Twitter. " class="wp-image-13618" style="width:383px;height:378px" width="383" height="378" srcset="https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_several_post_envelopes_that_have_the_twitter_bird_on_the_e048c6dc-a940-4045-a0c0-a54d0298232b-min.png 512w, https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_several_post_envelopes_that_have_the_twitter_bird_on_the_e048c6dc-a940-4045-a0c0-a54d0298232b-min.png 300w, https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_several_post_envelopes_that_have_the_twitter_bird_on_the_e048c6dc-a940-4045-a0c0-a54d0298232b-min.png 768w, https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_several_post_envelopes_that_have_the_twitter_bird_on_the_e048c6dc-a940-4045-a0c0-a54d0298232b-min.png 1028w" sizes="(max-width: 383px) 100vw, 383px" /><figcaption class="wp-element-caption">The relataly Twitter news bot leverages and integrates the following APIs: NewsAPI, OpenAI, and Twitter.</figcaption></figure>
</div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<h2 class="wp-block-heading">Creating an OpenAI NewsBot for Twitter using NewsAPI in Python</h2>



<p class="wp-block-paragraph">Now that you are familiar with the architecture of the news bot, it&#8217;s time to roll up your sleeves and get into the coding. We will guide you through the necessary steps to create an OpenAI News Bot for Twitter using Python. By leveraging the advanced language model of OpenAI and the vast resources available through NewsAPI, we will develop a sophisticated bot that automatically fetches and tweets the latest news updates on Twitter. Our bot will go beyond basic news retrieval and have the ability to curate relevant news articles within a specific scope and generate compelling tweets that stand out in the noise of social media. Let&#8217;s get started!</p>



<p class="wp-block-paragraph">The code is available on the GitHub repository.</p>



<div class="wp-block-kadence-advancedbtn kb-buttons-wrap kb-btns13581_a6106e-2d"><a class="kb-button kt-button button kb-btn13581_4957ce-2f kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-tutorials/blob/master/07%20OpenAI/604%20Custom%20ChatGPT%20with%20Azure%20Cosmos%20DB%20Vector%20Database%20and%20Embeddings.ipynb" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fe_eye kt-btn-icon-side-left"><svg viewBox="0 0 24 24"  fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></span><span class="kt-btn-inner-text">View on GitHub </span></a>

<a class="kb-button kt-button button kb-btn13581_41c5d8-a3 kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-API-tutorials" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fa_github kt-btn-icon-side-left"><svg viewBox="0 0 496 512"  fill="currentColor" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg></span><span class="kt-btn-inner-text">Relataly GitHub Repo </span></a></div>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Update August 2023: If you are wondering what the exact code is for the automation of the <a href="https://twitter.com/relataly">relataly twitter account</a> in <a href="https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-python">Azure functions</a>, I have published it in a separate <a href="https://github.com/flo7up/relataly-functions/tree/master">GitHub repository</a>. In the meantime, i have slightly adjusted the code and added functionalities for retrieveing articles from <a href="https://news.ycombinator.com/">hackernews</a> and posting fact tweets.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-large"><img decoding="async" width="512" height="510" data-attachment-id="13592" data-permalink="https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min.png" data-orig-size="1018,1014" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min.png" src="https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min-512x510.png" alt="" class="wp-image-13592" srcset="https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min.png 512w, https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min.png 300w, https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min.png 140w, https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min.png 768w, https://www.relataly.com/wp-content/uploads/2023/05/Flo7up_automatising_social_media_facebook_twitter_instagram_lin_dd924ad4-c54d-4614-aa39-34f93aa3a8ba-min.png 1018w" sizes="(max-width: 512px) 100vw, 512px" /><figcaption class="wp-element-caption">OpenAI, with its language models and natural language processing capabilities, can be a valuable tool in automating Social media tasks. </figcaption></figure>
</div>
</div>



<h2 class="wp-block-heading">Setup and APIs</h2>



<p class="wp-block-paragraph">Before diving into the code, it’s essential to ensure that you have the proper setup for your Python 3 environment and have installed all the necessary packages. If you do not have a Python environment, follow the instructions in&nbsp;<a href="https://www.relataly.com/anaconda-python-environment-machine-learning/1663/" target="_blank" rel="noreferrer noopener">this tutorial</a>&nbsp;to set up the&nbsp;<a href="https://www.anaconda.com/products/individual" target="_blank" rel="noreferrer noopener">Anaconda Python environment</a>. This will provide you with a robust and versatile environment well-suited for machine learning and data science tasks.</p>



<p class="wp-block-paragraph">In this tutorial, we will be working with the OpenAI library. You can install the OpenAI Python library using console commands:</p>



<ul class="wp-block-list">
<li><em>pip install&nbsp;</em>openai</li>



<li><em>conda install&nbsp;</em>openai&nbsp;(if you are using the Anaconda packet manager)</li>
</ul>



<h3 class="wp-block-heading" id="h-step-1-imports-and-authentication">Step #1 Imports and Authentication</h3>



<p class="wp-block-paragraph">We begin by making the necessary imports and setting up the API keys required to authenticate against the different APIs. In the example, below I have used the Azure key vault to store the API keys in a secure manner in the cloud. You can also load the API keys from a yaml file or store the API keys in the code (not advised for security reasons).</p>



<p class="wp-block-paragraph">We retrieve and set API keys and authentication credentials for services like NewsAPI, OpenAI, and Twitter. These keys and credentials are essential for authenticating our application and ensuring secure access to the respective APIs. Additionally, we implement logging functionality to record important information about our program&#8217;s execution, enabling us to monitor and troubleshoot as needed.</p>



<p class="wp-block-paragraph">In addition, we assign a variable for the CSV file name we&#8217;ll use to store our news log data.</p>



<p class="wp-block-paragraph">By executing these steps, we lay the foundation for seamless integration with external APIs and services, enabling our application to perform a wide range of functionalities in subsequent parts of our code.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># A tutorial for this file is available at www.relataly.com
# Tested with Python 3.9.13, 1.2.0, Pandas 1.3.4, OpenAI 0.27.3, Tweepy 4.13.0, Requests 2.26.0, 

import logging
import pandas as pd
import openai
import tweepy
import csv
import requests

# Set API Keys and Authentification
logging.info('Setting NewsAPI API Key')
NEWSAPI_API_KEY = &lt;your API key&gt; # replace with own API key

logging.info('Setting OpenAI API Key')
openai.api_key = &lt;your API key&gt; # replace with own API key

logging.info('Setting Twitter API Key')
auth=tweepy.OAuthHandler(&lt;your API key&gt;,
                         &lt;your API secret&gt;)
auth.set_access_token(&lt;your access token&gt;,
                      &lt;your access secret&gt;)
twitter_api=tweepy.API(auth)

CSV_NAME = 'news_log.csv'</pre></div>



<h3 class="wp-block-heading">Step #2 Collecting the News from the NewsAPI</h3>



<p class="wp-block-paragraph">Next, we define a function to retrieve technology news from the NewsAPI. </p>



<p class="wp-block-paragraph">The function below takes an optional parameter number to specify the desired number of news items. Inside the function, we construct a URL using the NewsAPI endpoint and our API key. We send a request to the URL and receive a JSON response containing the news data. Then, we extract the relevant information, such as the title, description, and URL, from the response.</p>



<p class="wp-block-paragraph">Using the Pandas library, we create a DataFrame to organize the news items neatly. We filter out any rows with missing values, ensuring we have clean and complete data. Finally, we return the top number news items as a DataFrame.</p>



<p class="wp-block-paragraph">By utilizing the fetch_news function, we can effortlessly access a collection of up-to-date technology news articles. This allows us to stay informed and integrate the latest news seamlessly into our application.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">#### NewsAPI
def fetch_news(number=10):
    # Fetch tech news from NewsAPI
    url = f&quot;https://newsapi.org/v2/top-headlines?country=us&amp;category=technology&amp;apiKey={NEWSAPI_API_KEY}&quot;
    response = requests.get(url).json()
    news_items = response[&quot;articles&quot;]
    df = pd.DataFrame(news_items)
    df = df[[&quot;title&quot;, &quot;description&quot;, &quot;url&quot;]].dropna()
    return df.head(number)</pre></div>



<h3 class="wp-block-heading">Step #3 OpenAI Functions for News Relevance and Tweet Generation</h3>



<p class="wp-block-paragraph"><br>We proceed with the OpenAI integration, which allows us to perform important tasks in our application. Firstly, we utilize the OpenAI GPT-3.5 engine to identify the relevance of news articles based on a specific scope of topics. By constructing prompts and leveraging the GPT-3.5 Turbo model, we can effectively determine the relevance of news articles to enhance the accuracy of our information. If you are interested in retrieving other news, you can easily adjust the prompt and include other topics that you deem relevant for your application. </p>



<p class="wp-block-paragraph">In addition, we define a clause for the case that the bot does not identify any news as relevant. In this case, the bot will create a fact tweet that describes common terms from the domain of machine learning and data science. </p>



<p class="wp-block-paragraph">Furthermore, we harness the power of OpenAI to create tweets uniquely and engagingly. By generating prompts that provide a title, description, and a tiny URL, we can generate informative tweets within the 280-character limit. This enables us to share compelling news content while utilizing hashtags to expand the reach of our tweets. As you can see in the function &#8220;select_relevant_news_prompt&#8221; code, we provide a single sample response to OpenAI ChatGPT. This approach is known as 1-shot learning, and it typically significantly improves the results compared to a prompt without any samples (zero-shot learning).  </p>



<p class="wp-block-paragraph">In the second function, &#8220;create_tweet_prompt,&#8221; we do not provide any sample response to minimize the number of tokens processed and lower our cost for calling the model. This approach is known as zero-shot learning because the model is not given any sample. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">#### OpenAI Engine
def openai_request(instructions, task, sample = [], model_engine='gpt-3.5-turbo'):
    prompt = [{&quot;role&quot;: &quot;system&quot;, &quot;content&quot;: instructions }, 
              {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: task }]
    prompt = sample + prompt
    completion = openai.ChatCompletion.create(model=model_engine, messages=prompt, temperature=0.2, max_tokens=400)
    return completion.choices[0].message.content


#### Define OpenAI Prompt for news Relevance
def select_relevant_news_prompt(news_articles, topics, n):    
    instructions = f'Your task is to examine a list of News and return a list of boolean values that indicate which of the News are in scope of a list of topics. \
    Return a list of True or False values that indicate the relevance of the News.'
    task =  f&quot;{news_articles} /n {topics}?&quot; 
    sample = [
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: f&quot;[new AI model available from Nvidia, We Exploded the AMD Ryzen 7, Release of b2 Game, XGBoost 3.0 improvices Decision Forest Algorithms, New Zelda Game Now Available, Ukraine Uses a New Weapon] /n {topics}?&quot;},
        {&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: &quot;[True, False, False, True, False, False]&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: f&quot;[Giga Giraff found in Sounth Africa, We Exploded the AMD Ryzen 7, Release of b2 Game, Donald Trump to make a come back, New Zelda Game Now Available, Ukraine Uses a New Weapon] /n {topics}?&quot;}, 
        {&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: &quot;[False, False, False, False, False, False]&quot;}]
    return instructions, task, sample


#### Define OpenAI Prompt for news Relevance
def check_previous_posts_prompt(title, old_posts):    
    instructions = f'Your objective is to compare a news title with a list of previous news and determine whether it covers a similar topic that was already covered by a previous title. \
        Rate the overlap on a scale between 1 and 10 with 1 beeing a full overlap and 10 representing an unrelated topic. &quot;'
    task =  f&quot;'{title}.' Previous News: {old_posts}.&quot;
    sample = [
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;'Nvidia launches new AI model.' Previous News: [new AI model available from Nvidia, We Exploded the AMD Ryzen 7 7800X3D, The Lara Croft Collection For Switch Has Been Rated By The ESRB].&quot;},
        {&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: &quot;1&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;'Big Explosion of an AMD Ryzen 7.' Previous News: [Improving Mental Wellbeing Through Physical Activity, The Lara Croft Collection For Switch Has Been Rated By The ESRB].&quot;},
        {&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: &quot;10&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;'new AI model available from Google.' Previous News : [new AI model available from Nvidia, The Lara Croft Collection For Switch Has Been Rated By The ESRB].&quot;},
        {&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: &quot;9&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;'What Really Made Geoffrey Hinton Into an AI Doomer - WIRED.' Previous News : [Why AI's 'godfather' Geoffrey Hinton quit Google, new AI model available from Nvidia, The Lara Croft Collection For Switch Has Been Rated By The ESRB].&quot;},
        {&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: &quot;4&quot;}]
    return instructions, task, sample


#### Define OpenAI Prompt for News Tweet
def create_tweet_prompt(title, description, tiny_url):
    instructions = f'You are a twitter user that creates tweets with a maximum length of 280 characters.'
    task = f&quot;Create an informative tweet on twitter based on the following news title and description. \
        The tweet must use a maximum of 280 characters. \
        Include the {tiny_url}. But do not include any other urls.\
        Title: {title}. \
        Description: {description}. \
        Use hashtags to reach a wider audience. \
        Do not include any emojis in the tweet&quot;
    return instructions, task


#### Define OpenAI Prompt for news Relevance
def previous_post_check(title, old_posts):
    instructions, task, sample = check_previous_posts_prompt(title, old_posts)
    response = openai_request(instructions, task, sample)
    return eval(response)


#### Define OpenAI Prompt for News Tweet
def create_fact_tweet_prompt(old_terms):
    instructions = f'You are a twitter user that creates tweets with a length below 280 characters.'
    task = f&quot;Choose a technical term from the field of AI, machine learning or data science. Then create a twitter tweet that describes the term. Just return a python dictionary with the term and the tweet. &quot;
    # if old terms not empty
    if old_terms != []:
        avoid_terms =f'Avoid the following terms, because you have previously tweetet about them: {old_terms}'
        task = task + avoid_terms
    sample = [
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: f&quot;Choose a technical term from the field of AI, machine learning or data science. Then create a twitter tweet that describes the term. Just return a python dictionary with the term and the tweet.&quot;},
        {&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: &quot;{'GradientDescent': '#GradientDescent is a popular optimization algorithm used to minimize the error of a model by adjusting its parameters. \
         It works by iteratively calculating the gradient of the error with respect to the parameters and updating them accordingly. #ML'}&quot;}]
    return instructions, task, sample

# Load previous information from a csv file
def get_history_from_csv(csv_name):
    try:
        # try loading the csv file
        df = pd.read_csv(csv_name)
    except:
        # create the csv file
        df = pd.DataFrame(columns=['title'])
        df.to_csv(csv_name, index=False)
    return df

</pre></div>



<h3 class="wp-block-heading">Step #4 Functions for Publishing Twitter Tweets</h3>



<p class="wp-block-paragraph"><br>Next, we will create a series of functions that enable us to create and post tweets based on specific news articles. The first function, check_tweet_length, checks the length of a tweet and ensures it does not exceed the 280-character limit. If the tweet is too long, it returns False; otherwise, it returns True.</p>



<p class="wp-block-paragraph">Given the character limit of Twitter tweets at only 280 characters, including a URL can often take up a significant amount of that limit. To avoid wasting precious characters on lengthy URLs, we can use an URL-shortening service called <a href="http://www.tinyurl.com" target="_blank" rel="noreferrer noopener">TinyURL</a>. This service provides a shortened version of any input URL, allowing us to fit more text within the character limit. The good news is that TinyURL offers an API that we can use without the need for an API key.</p>



<p class="wp-block-paragraph">The create_tweet function takes the title, description, and URL of a news article as inputs. It generates a tiny URL using the create_tiny_url function and constructs a prompt for tweet creation using the create_tweet_prompt function. The prompt is then sent to the OpenAI engine to generate the tweet content. The generated tweet is checked for length using the check_tweet_length function, and if it passes the length check, it is posted using the Twitter API.</p>



<p class="wp-block-paragraph">By utilizing these functions together, we can effectively create and post tweets based on news articles while ensuring they meet the length requirements and include relevant information for our audience. This streamlines the process of sharing news updates and engaging with our followers in a concise and informative manner.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">def check_tweet_length(tweet):
    return False if len(tweet) &gt; 280 else True


# Create the fact tweet
def create_fact_tweet(chance_for_tweet = 0.5):
    df_old_facts = get_history_from_csv(CSV_FACTS_NAME)

    if random.random() &lt; chance_for_tweet:
        # create a fact tweet
        instructions, tasks, sample = create_fact_tweet_prompt(list(df_old_facts.tail(10)['title']))
        tweet = openai_request(instructions, tasks, sample)
        tweet_text = list(eval(tweet).values())[0]

        # tweet creation
        print(f'Creating fact tweet: {tweet_text}')
        
        # check tweet length and post tweet
        if check_tweet_length(tweet):
            twitter_auth().update_status(tweet_text)
            term = list(eval(tweet).keys())[0]
            # save the fact in the csv file
            with open(f'{CSV_FACTS_NAME}', 'a', newline='') as file:
                            writer = csv.writer(file)
                            writer.writerow([term])
        else: 
            print('error tweet too long')
    else:
        print('No fact tweet created')
    

def create_news_tweet(title, description, url):
    # create tiny url
    tiny_url = create_tiny_url(url)

    # define prompt for tweet creation
    instructions, task = create_tweet_prompt(title, description, tiny_url)
    tweet_text = openai_request(instructions, task)

    print(f'Creating new tweet: {tweet_text}')
    # check tweet length and post tweet
    if check_tweet_length(tweet_text):
            status = twitter_auth().update_status(tweet_text)
            print(f&quot;Tweeted: {title}&quot;)
            with open(f'{CSV_NEWS_NAME}', 'a', newline='') as file:
                writer = csv.writer(file)
                writer.writerow([title])
    else: 
        status = 'error tweet too long'
    return status


def create_tiny_url(url):
    response = requests.get(f'http://tinyurl.com/api-create.php?url={url}')
    return response.text</pre></div>



<h3 class="wp-block-heading">Step #5 Bringing it All Together &#8211; Running the Bot</h3>



<p class="wp-block-paragraph"><br>Finally, we reach the exciting part where we can run our Twitter news bot. The code below utilizes the functions we&#8217;ve created earlier to compose a tweet and post it on Twitter. </p>



<p class="wp-block-paragraph">First, we call the create_tweet(title, description, url) function, which takes the title, description, and URL of a news article. This function generates a shorter URL and prepares a prompt for the tweet. Next, we generate the actual content of the tweet by using the prompt with the help of the openai_request(instructions, task) function.</p>



<p class="wp-block-paragraph">Once the tweet is generated and assigned to a variable called tweet, we check its length using the check_tweet_length(tweet) function. This step ensures that the tweet does not exceed the maximum character limit allowed by Twitter. If the tweet is within the allowed limit, we post it on Twitter using the twitter_api.update_status(tweet) function. We also log the ID of the posted tweet for reference.</p>



<p class="wp-block-paragraph">If the tweet exceeds the character limit, we assign an error message to the status variable.</p>



<p class="wp-block-paragraph">Finally, the function returns the status variable, which can be used to analyze any potential issues or handle errors.</p>



<p class="wp-block-paragraph">This code segment brings everything together, allowing our Twitter news bot to automatically create and publish tweets based on news articles. You can wrap this function with a timer function to run the code on a regular interval.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">#### Main Bot
def main_bot():
    # Read the old CSV data
    # try opening the csv file and creeate it if it does not exist
    df_old_news = get_history_from_csv(CSV_NEWS_NAME)
    df_old_news = df_old_news.tail(16)
    # Fetch news data
    df = fetch_news(12)
    
    # Check the Relevance of the News and Filter those not relevant
    relevant_topics =&quot;[AI, Machine Learning, Data Science, OpenAI, Artificial Intelligence, Data Mining, Data Analytics]&quot;
    instructions, task, sample = select_relevant_news_prompt(list(df['title']), relevant_topics, len(list(df['title'])))
    relevance = openai_request(instructions, task, sample)
    relevance_list = eval(relevance)

    s = 0
    df = df[relevance_list]
    if len(df) &gt; 0:
        for index, row in df.iterrows():
            if s == 1:
                break
            logging.info('info:' + row['title'])
            title = row['title']
            title = title.replace(&quot;'&quot;, &quot;&quot;)
            description = row['description']
            url = row['url']            
                                             
            if (title not in df_old_news.title.values):
                doublicate_check = previous_post_check(title, list(df_old_news.tail(10)['title']))
                if doublicate_check &gt; 3:
                    # Create a tweet
                    response = create_news_tweet(title, description, url)
            
                else: 
                    print(f&quot;Already tweeted: {title}&quot;)
            else: 
                print(&quot;No news articles found&quot;)
                create_fact_tweet(chance_for_tweet=0.5)

main_bot()</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">No news articles found
No fact tweet created
No news articles found
Creating fact tweet: Looking for a way to cluster your data? Try #KMeans! It is an unsupervised learning algorithm that groups similar data points together based on their distance to a centroid. #MachineLearning #DataScience
Creating tweet: {'KMeans': 'Looking for a way to cluster your data? Try #KMeans! It is an unsupervised learning algorithm that groups similar data points together based on their distance to a centroid. #MachineLearning #DataScience'}</pre></div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<h2 class="wp-block-heading">Hosting the Bot Serverless on Azure Functions</h2>



<p class="wp-block-paragraph">If you want to run the bot fully automated, you will probably want to host it somewhere in the cloud. To host the OpenAI newsbot on Azure, you can follow these steps:</p>



<ol class="wp-block-list">
<li>Create an Azure Key Vault to store the credentials securely.</li>



<li>Create an Azure Blob Storage account to keep track of past posts.</li>



<li>Create two Azure Functions. The first function fetches news on a regular interval and checks that only relevant news is posted. This function also ensures that there are no duplicates with the help of OpenAI and a CSV file that keeps track of previous posts. The second function is an HTTP trigger and is used to create the post. It reaches out to OpenAI to generate the post and then makes the call to the Twitter API.</li>



<li>Once the functions are created, deploy the code to Azure Functions.</li>



<li>Configure the Azure Functions to use the credentials from the Key Vault and the Blob Storage account to store the CSV file.</li>
</ol>



<p class="wp-block-paragraph">The code for the newsbot is only slightly different from what was presented in the blog post. If you&#8217;re interested in the Azure-ready code, feel free to message me.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1385" height="946" data-attachment-id="13638" data-permalink="https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/image-3-6/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2023/05/image-3.png" data-orig-size="1385,946" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-3" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2023/05/image-3.png" src="https://www.relataly.com/wp-content/uploads/2023/05/image-3.png" alt="The Relataly OpenAI News Bot runs on a Serverless Infrastructure based on Azure Functions." class="wp-image-13638" srcset="https://www.relataly.com/wp-content/uploads/2023/05/image-3.png 1385w, https://www.relataly.com/wp-content/uploads/2023/05/image-3.png 300w, https://www.relataly.com/wp-content/uploads/2023/05/image-3.png 512w, https://www.relataly.com/wp-content/uploads/2023/05/image-3.png 768w" sizes="(max-width: 1237px) 100vw, 1237px" /><figcaption class="wp-element-caption">The Relataly News Bot runs on a Serverless Infrastructure based on Azure Functions</figcaption></figure>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">In this article, we have developed a Twitter news bot that automates news updates on the platform. Our focus was on leveraging OpenAI&#8217;s advanced language model to create a powerful bot capable of generating and posting engaging tweets based on news articles. Throughout the discussion, we covered essential aspects such as tweet length validation, concise URL generation, crafting captivating tweet prompts, and seamless integration with the Twitter API for efficient posting.</p>



<p class="wp-block-paragraph">By following the step-by-step guide presented in this blog, readers were able to harness the capabilities of OpenAI technology and successfully build their own Twitter news bots. This enabled them to effortlessly deliver timely updates to their audience, expanding their reach and fostering meaningful engagement within the Twitter community.</p>



<p class="wp-block-paragraph">Whether you have questions, suggestions, or insights, let us know in the comments below. Your feedback is invaluable to us as we strive to continuously improve. </p>



<h2 class="wp-block-heading">Sources</h2>



<ul class="wp-block-list">
<li><a href="https://developer.twitter.com/" target="_blank" rel="noreferrer noopener">Twitter Developer Portal</a></li>



<li><a href="https://openai.com/" target="_blank" rel="noreferrer noopener">OpenAI Portal</a></li>



<li><a href="https://newsapi.org/" target="_blank" rel="noreferrer noopener">NewsAPI Portal</a></li>



<li><a href="https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-python">Overview Azure Functions</a></li>



<li><a href="http://www.tinyurl.com" target="_blank" rel="noreferrer noopener">Tinyurl.com</a></li>



<li>ChatGPT helped to revise this article. </li>



<li>Images created with <a href="http://www.midjourney.com" target="_blank" rel="noreferrer noopener">Midjourney AI</a></li>
</ul>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>
<p>The post <a href="https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/">How to Automatize your Twitter News Account with OpenAI ChatGPT and NewsAPI in Python</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.relataly.com/how-to-build-a-twitter-news-bot-with-openai-and-newsapi/13581/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">13581</post-id>	</item>
		<item>
		<title>Automate Crypto Trading with a Python-Powered Twitter Bot and Gate.io Signals</title>
		<link>https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/</link>
					<comments>https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/#comments</comments>
		
		<dc:creator><![CDATA[Florian Follonier]]></dc:creator>
		<pubDate>Wed, 19 May 2021 04:57:00 +0000</pubDate>
				<category><![CDATA[Algorithmic Trading]]></category>
		<category><![CDATA[Finance]]></category>
		<category><![CDATA[Gate.io API]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Stock Market Forecasting]]></category>
		<category><![CDATA[Time Series Forecasting]]></category>
		<category><![CDATA[Twitter API]]></category>
		<category><![CDATA[AI in E-Commerce]]></category>
		<category><![CDATA[API Tutorials]]></category>
		<category><![CDATA[Automated Twitter Posts]]></category>
		<category><![CDATA[Intermediate Tutorials]]></category>
		<category><![CDATA[Social Media Data]]></category>
		<category><![CDATA[Trading Signals]]></category>
		<category><![CDATA[Twitter Bots]]></category>
		<guid isPermaLink="false">https://www.relataly.com/?p=3974</guid>

					<description><![CDATA[<p>This tutorial develops a Twitter bot in Python that will generate automated trading signals. The bot will pull real-time price data on various cryptocurrencies (Bitcoin, Ethereum, Doge, etc.) from the crypto exchange Gate.io and analyze it using predefined rules. Whenever the bot detects a relevant price change, it automatically posts a tweet via Twitter. Simple ... <a title="Automate Crypto Trading with a Python-Powered Twitter Bot and Gate.io Signals" class="read-more" href="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/" aria-label="Read more about Automate Crypto Trading with a Python-Powered Twitter Bot and Gate.io Signals">Read more</a></p>
<p>The post <a href="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/">Automate Crypto Trading with a Python-Powered Twitter Bot and Gate.io Signals</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">This tutorial develops a Twitter bot in Python that will generate automated trading signals. The bot will pull real-time price data on various cryptocurrencies (Bitcoin, Ethereum, Doge, etc.) from the <a href="http://www.gate.io/" target="_blank" rel="noreferrer noopener">crypto exchange</a> <em>Gate.io</em> and analyze it using predefined rules. Whenever the bot detects a relevant price change, it automatically posts a tweet via Twitter. Simple Twitter bots can proactively inform their audiences about relevant events in the market. Such an event can be a sharp rise or fall in price or a sudden spike in the trading volume. If we examine data for specific price movements, we can also store these events and use them later to train a predictive model.</p>



<p class="wp-block-paragraph">More advanced signal bots use predictive models to signal when it is appropriate to enter or exit the market. Or the bot executes the buy- and sell-orders directly itself. A well-defined signaling logic can therefore constitute the first step toward algorithmic trading. But one thing at a time. So in this article, we will begin by developing a simple signal bot.</p>



<p class="wp-block-paragraph">The rest of this article is structured as follows. First, we take a look at the different code modules of the Twitter bot. After that, we&#8217;ll implement the other code modules in Python. Finally, we will integrate the modules and run some tests. We will also quickly introduce the APIs used to build the bot.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-full"><img decoding="async" width="748" height="506" data-attachment-id="12463" data-permalink="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/trading-bot-machine-learning-tutorial-gateio-trading-signals-python-min/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2023/02/trading-bot-machine-learning-tutorial-gateio-trading-signals-python-min.png" data-orig-size="748,506" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="trading-bot-machine-learning-tutorial-gateio-trading-signals-python-min" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2023/02/trading-bot-machine-learning-tutorial-gateio-trading-signals-python-min.png" src="https://www.relataly.com/wp-content/uploads/2023/02/trading-bot-machine-learning-tutorial-gateio-trading-signals-python-min.png" alt="trading bot machine learning tutorial gateio trading signals python. Midjourney. relataly.com" class="wp-image-12463" srcset="https://www.relataly.com/wp-content/uploads/2023/02/trading-bot-machine-learning-tutorial-gateio-trading-signals-python-min.png 748w, https://www.relataly.com/wp-content/uploads/2023/02/trading-bot-machine-learning-tutorial-gateio-trading-signals-python-min.png 300w" sizes="(max-width: 748px) 100vw, 748px" /><figcaption class="wp-element-caption">Bots can do a lot of cool things but should be used with caution. Image created with <a href="http://www.midjourney.com" target="_blank" rel="noreferrer noopener">Midjourney</a></figcaption></figure>
</div>
</div>
</div>
</div>



<h2 class="wp-block-heading" id="h-different-modules-of-the-signal-bot">Different Modules of the Signal Bot </h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">This section briefly describes the conceptual architecture of the Crypto Twitter bot. Its architecture adheres to a modular design pattern and separates into four loosely coupled modules. Each module has a clear function.</p>



<ol class="wp-block-list">
<li>The <strong>Data Collection Module retrieves price data from the crypto exchange Gate.io. The module sends requests at </strong>regular intervals against the gate.io API. The module adds the data to separate data stores &#8211; one for each cryptocurrency. It then forwards the data to the preprocessing module.</li>



<li>The<strong> Data Preprocessing Module</strong> calculates the statistical indicators, such as moving averages or means, which become the basis for the signaling logic.</li>



<li>The <strong>Signaling Module </strong>searches for relevant events based on the indicator values provided. If a relevant event is detected, it is reported to the communication module.</li>



<li>The <strong>Communication Module</strong> connects to the Twitter API. As soon as it is informed about a new event, it tweets about this event on Twitter.</li>
</ol>



<p class="wp-block-paragraph">Now that you are familiar with the modules of our Crypto Twitter Bot, we can take a look at its underlying APIs.</p>



<figure class="wp-block-image size-large is-resized is-style-default"><img decoding="async" data-attachment-id="6092" data-permalink="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/image-124/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2022/03/image.png" data-orig-size="1342,865" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2022/03/image.png" src="https://www.relataly.com/wp-content/uploads/2022/03/image-1024x660.png" alt="" class="wp-image-6092" width="611" height="394" srcset="https://www.relataly.com/wp-content/uploads/2022/03/image.png 1024w, https://www.relataly.com/wp-content/uploads/2022/03/image.png 300w, https://www.relataly.com/wp-content/uploads/2022/03/image.png 768w, https://www.relataly.com/wp-content/uploads/2022/03/image.png 1342w" sizes="(max-width: 611px) 100vw, 611px" /><figcaption class="wp-element-caption">Components of the Relataly Crypto Signal Bot</figcaption></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h2 class="wp-block-heading" id="h-about-the-apis-used-in-this-tutorial">About the APIs Used in this Tutorial</h2>



<p class="wp-block-paragraph">In this tutorial, we will be using two APIs: </p>



<ul class="wp-block-list">
<li>The Gate.io API to fetch price data.</li>



<li>Twitter to post Tweets about Trading Signals</li>
</ul>



<h3 class="wp-block-heading" id="h-the-gate-io-api">The Gate.io API</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">Firstly, we will be using the Gate.io API to obtain prices for various cryptocurrencies. Gate.io is one of the smaller crypto exchanges in the crypto-verse. However, it offers a wide range of smaller cryptocurrencies, especially those you cannot trade anywhere else. As of now, the gate.io market endpoint does not require authentication to use its essential functions.</p>



<p class="wp-block-paragraph">Check out our <a href="https://www.relataly.com/streaming-crypto-prices-via-the-gate-io-api-with-python/3982/" target="_blank" rel="noreferrer noopener">recent relataly gate.io tutorial</a> to learn how to pull data via the gate.io API in Python.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h3 class="wp-block-heading" id="h-the-twitter-api">The Twitter API</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">The second API that our bot will use is the Twitter API. We will use this API via the Python package Tweepy to post crypto price signals. Check out this article if you are looking for a simple code example of submitting tweets via the Twitter API. If you don&#8217;t want to use Twitter, you can disable its use in the code.</p>



<p class="wp-block-paragraph">Posting tweets via the API requires authentication with a valid developer account. You can apply for a developer account for free on the Twitter <a href="https://developer.twitter.com/en/apply-for-access" target="_blank" rel="noreferrer noopener">developer website</a>. Just be aware that the confirmation can sometimes take several days. </p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h3 class="wp-block-heading" id="storing-the-api-key">Storing the Twitter API Key</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">Storing API keys in your code can compromise the security of your application. If the code is made public, for example, by publishing it on a code-sharing website like GitHub, anyone who has access to the code can use the API key to make requests to the API and potentially access sensitive information or cause harm to your account or application. A better practice is to import and access the API key from a separate YAML file, from where you can import it into your project. To store the Twitter API Key, create a YAML file with the name “api_config_twitter.yml” and insert your API key into this file as follows:</p>



<p class="wp-block-paragraph">api_<em>key: “your api key”</em></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h2 class="wp-block-heading" id="h-implementing-a-twitter-signal-bot-using-python">Implementing a Twitter Signal Bot using Python</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">In this article, we will walk through the process of creating a Twitter bot that automatically tweets updates about cryptocurrency prices. The bot will be designed to pull real-time data on cryptocurrency prices from an external API, and then automatically generate and post tweets on a regular basis. By the end of the article, you will have a fully functional Twitter bot that can keep your followers informed about the latest cryptocurrency prices.</p>



<p class="wp-block-paragraph">Note: You require a Twitter developer account if you want to use the Twitter functionality. Without an account, you can still print out trading signals to yourself, but you will not be able to post them via the Twitter API. </p>



<p class="wp-block-paragraph">The code is available on the GitHub repository.</p>



<div class="wp-block-kadence-advancedbtn kb-buttons-wrap kb-btns_41cd8e-1f"><a class="kb-button kt-button button kb-btn_290c88-96 kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-tutorials/blob/master/08%20Natural%20Language%20Processing/025%20Bots%20-%20Building%20a%20Twitter%20Bot%20with%20Python.ipynb" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fe_eye kt-btn-icon-side-left"><svg viewBox="0 0 24 24"  fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></span><span class="kt-btn-inner-text">View on GitHub </span></a>

<a class="kb-button kt-button button kb-btn_de3f80-09 kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-API-tutorials" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fa_github kt-btn-icon-side-left"><svg viewBox="0 0 496 512"  fill="currentColor" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg></span><span class="kt-btn-inner-text">Relataly GitHub Repo </span></a></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<p class="has-accent-color has-blush-light-purple-gradient-background has-text-color has-background wp-block-paragraph"><strong>Disclaimer</strong>: This article does not constitute financial advice. Stock markets can be very volatile and are generally difficult to predict. Predictive models and other forms of analytics applied in this article only illustrate machine learning use cases.</p>
</div>
</div>



<h3 class="wp-block-heading" id="h-python-prerequisites">Python Prerequisites</h3>



<p class="wp-block-paragraph">Before starting the coding part, make sure that you have set up your Python 3 environment and required packages. If you don&#8217;t have an environment set up yet, you can follow&nbsp;this tutorial&nbsp;to set up the&nbsp;<a href="https://www.anaconda.com/products/individual" target="_blank" rel="noreferrer noopener">Anaconda environment</a>.</p>



<p class="wp-block-paragraph">Also, make sure you install all required packages. In this tutorial, we will be working with the following standard packages:&nbsp;</p>



<ul class="wp-block-list">
<li><em><a href="https://pandas.pydata.org/" target="_blank" rel="noreferrer noopener">pandas</a></em></li>



<li><em><a href="https://numpy.org/" target="_blank" rel="noreferrer noopener">NumPy</a></em></li>
</ul>



<p class="wp-block-paragraph">In addition, we will use the following two packages:</p>



<ul class="wp-block-list">
<li>Firstly, the gate.io package (<a href="https://github.com/gateio/gateapi-python" target="_blank" rel="noreferrer noopener">package name gate-API</a>) pulls crypto price data from gate.io.</li>



<li>Secondly, we will use the Twitter API library <a href="https://www.tweepy.org/" target="_blank" rel="noreferrer noopener">Tweepy</a> to post trading signals via the <a href="https://developer.twitter.com/en/docs/twitter-api" target="_blank" rel="noreferrer noopener">Twitter API</a>.</li>
</ul>



<p class="wp-block-paragraph">You can install packages using console commands:</p>



<ul class="wp-block-list">
<li><em>pip install &lt;package name&gt;</em></li>



<li><em>conda install &lt;package name&gt;</em>&nbsp;(if you are using the anaconda packet manager)</li>
</ul>



<h3 class="wp-block-heading" id="h-step-1-regular-retrieval-of-price-data">Step #1: Regular Retrieval of Price Data </h3>



<p class="wp-block-paragraph">First, we will define a &#8220;prices&#8221; class to handle the incoming data flow. The prices class contains a &#8220;get_latest_prices&#8221; attribute that retrieves price information from gate.io. The function regularly calls the gate.io list_ticker market endpoint.</p>



<p class="wp-block-paragraph">The list_ticker endpoint returns a list of data fields for cryptocurrency pairs. Examples of price pairs are BTC_USD, BTC_ETH, BTC_ADA, etc. We can limit the response to a single price pair by passing a single pair as a variable in the API call. However, it is not possible to restrict the response to multiple pairs. We either get data for a single pair or all pairs. The response contains a list of the following data fields:</p>



<figure class="wp-block-image is-resized"><img decoding="async" src="https://www.relataly.com/wp-content/uploads/2021/05/image-5-1024x581.png" alt="Response returned by the Gate.io API list_tickers operation" width="493" height="280"/><figcaption class="wp-element-caption">Overview of the data fields in the response</figcaption></figure>



<p class="wp-block-paragraph">The following code maintains a separate dictionary for each cryptocurrency pair. The dictionary contains the name of the cryptocurrency pair and a data frame that includes the price data history. Each time the crypto bot receives a new response from the API, it goes through the response, extracts the price data(Price, Volume, etc.), and appends this data to the Data Frame of the respective cryptocurrency pair. Then the information is passed to the preprocessing module.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">import pandas as pd
import numpy as np
import json
import requests
import datetime as dt
import logging
import threading
import time
from __future__ import print_function

import tweepy 
import gate_api
from gate_api.exceptions import ApiException, GateApiException
from twitter_secrets import twitter_secrets as ts # place the twitter_secrets file under &lt;User&gt;/anaconda3/Lib

class Prices:
    &quot;&quot;&quot;Class that uses the gate api to retrieve currency data.&quot;&quot;&quot;

    def __init__(self, config):
        self._config = config
        self._logger = logging.getLogger(__name__)
        configuration = gate_api.Configuration(host=&quot;https://api.gateio.ws/api/v4&quot;)
        api_client = gate_api.ApiClient(configuration)
        self._api_instance = gate_api.SpotApi(api_client)
        self._price_history = {}
        self._cont_update_thread = None
        self._stop_cont_update_thread = None
        self._price_history_lock = threading.Lock()

    def get_price_history(self):
        &quot;&quot;&quot;Returns a dictionary with the price histories for the currencies.&quot;&quot;&quot;
        return self._price_history, self._price_history_lock

    def get_latest_prices(self):
        &quot;&quot;&quot;Gets new price data and adds the values to a DataFrame.

        Returns the DataFrame in a dictionary with the currencies as keys.&quot;&quot;&quot;
        timestamp = dt.datetime.now()
        try:
            api_response = self._api_instance.list_tickers()
        except GateApiException as e:
            logging.warning(
                &quot;Gate api exception, label: %s, message: %s\n&quot; % (e.label, e.message)
            )
            return {}
        except ApiException as e:
            logging.warning(&quot;Exception when calling SpotApi-&gt;list_tickers: %s\n&quot; % e)
            return {}
        latest_prices = {}
        for response in api_response:
            currency = response.currency_pair
            if &quot;USDT&quot; not in currency or &quot;BEAR&quot; in currency:
                continue
            value_dict = {
                &quot;base_volume&quot;: pd.to_numeric(response.base_volume),
                &quot;change_percentage&quot;: pd.to_numeric(response.change_percentage),
                &quot;etf_leverage&quot;: pd.to_numeric(response.etf_leverage),
                &quot;etf_net_value&quot;: pd.to_numeric(response.etf_net_value),
                &quot;etf_pre_net_value&quot;: pd.to_numeric(response.etf_pre_net_value),
                &quot;etf_pre_timestamp&quot;: response.etf_pre_timestamp,
                &quot;high_24h&quot;: pd.to_numeric(response.high_24h),
                &quot;highest_bid&quot;: pd.to_numeric(response.highest_bid),
                &quot;high_bid&quot;: pd.to_numeric(response.highest_bid),
                &quot;last&quot;: pd.to_numeric(response.last),
                &quot;low_24h&quot;: pd.to_numeric(response.low_24h),
                &quot;lowest_ask&quot;: pd.to_numeric(response.lowest_ask),
                &quot;quote_volume&quot;: pd.to_numeric(response.quote_volume),
                &quot;timestamp&quot;: timestamp,
            }
            latest_prices[currency] = pd.DataFrame(value_dict, index=[1])
        return latest_prices

    def start_cont_update(self):
        self._stop_cont_update_thread = threading.Event()
        self._stop_cont_update_thread.clear()
        self._cont_update_thread = threading.Thread(
            target=self._cont_update,
            args=(
                self._stop_cont_update_thread,
                self._price_history_lock,
            ),
        )
        self._cont_update_thread.start()
        self._logger.info(&quot;Started continuous price logging&quot;)

    def _cont_update(self, stop_event, lock):
        &quot;&quot;&quot;Continuously adds new prices to the price history.&quot;&quot;&quot;
        while not stop_event.is_set():
            start_time = time.time()
            lock.acquire()
            for currency, df in self.get_latest_prices().items():
                if currency in self._price_history.keys():
                    self._price_history[currency] = self._price_history[
                        currency
                    ].append(df, ignore_index=True)
                else:
                    self._price_history[currency] = df
            lock.release()
            self._logger.debug(&quot;Currency_dfs updated&quot;)
            self._wait_before_update(start_time)

    def _wait_before_update(self, start_time):
        elapsed_time = time.time() - start_time
        self._logger.debug(f&quot;Elapsed time: {elapsed_time}&quot;)
        if elapsed_time &gt; self._config[&quot;price_update_delay&quot;]:
            delay = 0
            self._logger.warning(
                #&quot;It took longer to retrieve the price data than the update_delay!&quot;
            )
        else:
            delay = self._config[&quot;price_update_delay&quot;] - elapsed_time
        self._logger.debug(f&quot;Waiting {delay}s until next update&quot;)
        time.sleep(delay)
</pre></div>



<h3 class="wp-block-heading" id="h-step-2-calculate-indicator-values">Step #2: Calculate Indicator Values</h3>



<p class="wp-block-paragraph">Next, we will define a few functions that process the regular data inflow from gate.io and calculate indicator values for the different cryptocurrencies. </p>



<p class="wp-block-paragraph">Absolute price values signal the bot that the price moves up or down. However, our signaling logic will primarily work with thresholds on percentage values. These indicators have a p at the end of the name in the code below.</p>



<p class="wp-block-paragraph">In addition, we will avoid misleading signals by incorporating moving averages into the signaling logic. Moving averages work on historical data, so we have to hand over the price history when we call the &#8220;calc_indicators&#8221; function. Furthermore, we take over other indicators from the data frame, including the 24h_low and the 24h_high. These indicators give us additional information about the indicators of the preceding price points. We can use them to build more robust trading signals.</p>



<p class="wp-block-paragraph">All indicators are calculated separately for each crypto pair, passed to a dictionary, and then passed to the signaling logic. In the next step, we can use these indicator values in our signaling rules.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">def calc_indicators(price_history):
    indicators = {}
    indicators_over_all = calc_indicators_over_all(price_history)
    for currency, df in price_history.items():
        if len(df) &lt;= 2:
            logging.getLogger().debug(
                f&quot;Skipped '{currency} when calculating indicators due to a lack of information&quot;
            )
            continue
        volume = df[&quot;base_volume&quot;].iloc[-1]
        last_price = df[&quot;last&quot;].iloc[-1]
        moving_avg_price = df[&quot;last&quot;].mean()
        moving_average_volume = df[&quot;base_volume&quot;].mean()
        moving_average_deviation_percent = np.round(
            div(last_price, moving_avg_price) - 1, 2
        )

        price_before = df[&quot;last&quot;].iloc[-2]
        price_delta = last_price - price_before
        price_delta_p = div(price_delta, last_price)
        price_delta_before = price_before - df[&quot;last&quot;].iloc[-3]
        price_delta_p_before = div((price_before - df[&quot;last&quot;].iloc[-3]), price_before)
        low_24h = df[&quot;low_24h&quot;].iloc[-1]
        high_24h = df[&quot;high_24h&quot;].iloc[-1]
        low_high_diff_p = div(high_24h - low_24h, low_24h)
        change_percentage = df[&quot;change_percentage&quot;].iloc[-1]

        indicator_values = {
            &quot;last_price&quot;: last_price,
            &quot;price_before&quot;: price_before,
            &quot;volume&quot;: volume,
            &quot;moving_avg_price&quot;: moving_avg_price,
            &quot;moving_average_volume&quot;: moving_average_volume,
            &quot;moving_average_deviation_percent&quot;: moving_average_deviation_percent,
            &quot;price_delta_p&quot;: price_delta_p,
            &quot;price_delta&quot;: price_delta,
            &quot;price_delta_before&quot;: price_delta_before,
            &quot;price_delta_p_before&quot;: price_delta_p_before,
            &quot;high_24h&quot;: high_24h,
            &quot;low_24h&quot;: low_24h,
            &quot;low_high_diff_p&quot;: low_high_diff_p,
            &quot;change_percentage&quot;: change_percentage,
        }
        indicator_values.update(indicators_over_all)
        indicators[currency] = indicator_values
    return indicators


def calc_indicators_over_all(price_history):
    avg_change_p = 0
    for currency, df in price_history.items():
        avg_change_p += df[&quot;change_percentage&quot;].iloc[-1]
    nr_of_currencies = len(price_history)
    avg_change_p = div(avg_change_p, nr_of_currencies)
    values = {
        &quot;avg_change_p&quot;: avg_change_p,
    }
    return values


def div(dividend, divisor, alt_value=0.0):
    return dividend / divisor if divisor != 0 else alt_value</pre></div>



<h3 class="wp-block-heading" id="h-step-3-define-the-signaling-logic-of-the-twitter-bot">Step #3: Define the Signaling Logic of the Twitter Bot</h3>



<p class="wp-block-paragraph">Our bot will use a signaling logic that differentiates between the following price signals:</p>



<ul class="wp-block-list">
<li>A simple uptick: Price_delta_p must be higher than the threshold (10%) to trigger.</li>



<li>A simple downtick: Price_delta_p must be lower than the threshold (10%) to trigger.</li>



<li>The bot does also report on new 24-hour lows and highs</li>



<li>Another event on which the bot reports is when an up or down price trend begins to accelerate or slows down.</li>



<li>The bot reports that when a price performs a trend reversal (pullback and recovery)</li>
</ul>



<p class="wp-block-paragraph"></p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" data-attachment-id="5034" data-permalink="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/image-71-2/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/06/image-71.png" data-orig-size="1168,639" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-71" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/06/image-71.png" src="https://www.relataly.com/wp-content/uploads/2021/06/image-71-1024x560.png" alt="Overview of the different trading signals generated by the signaling logic, twitter bot, algorithmic trading" class="wp-image-5034" width="755" height="413" srcset="https://www.relataly.com/wp-content/uploads/2021/06/image-71.png 1024w, https://www.relataly.com/wp-content/uploads/2021/06/image-71.png 300w, https://www.relataly.com/wp-content/uploads/2021/06/image-71.png 768w, https://www.relataly.com/wp-content/uploads/2021/06/image-71.png 1168w" sizes="(max-width: 755px) 100vw, 755px" /><figcaption class="wp-element-caption">Overview of the different trading signals generated by the signaling logic</figcaption></figure>



<p class="wp-block-paragraph">Be aware that the price_delta_p measures the percentage deviation from the previous price point. Thus, the signaling logic that our bot has in place is very dependent on the interval in which the bots request new price data. Shorter time intervals will have a lower chance of triggering because more considerable changes typically occur over a longer time. For more details regarding the signaling logic, please view the code below.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">def check_signal(currency, indicators, cs_config):
    ind = indicators[currency]
    signal = ''
    if (ind['moving_avg_price'] &gt; 0
            and ind['last_price'] &gt; 0.0
            and abs(ind['price_delta']) &gt; 0.0
            and abs(ind['price_delta_p']) &gt;= cs_config[&quot;delta_threshold_p&quot;]
            and ind['volume'] &gt; 0
    ):
        # up
        if ind['price_delta'] &gt; 0:
            movement_type = 'up +'
            if abs(ind['price_delta_p_before']) &gt; cs_config[&quot;delta_threshold_p&quot;]:
                if ind['price_delta_before'] &lt;= 0:
                    movement_type = 'recovery from ' + str(ind['price_before']) + ' to ' + str(ind['last_price'])
                else:
                    if ind['price_delta_p'] * (1-cs_config[&quot;delta_threshold_p&quot;]) &gt; ind['price_delta_p_before']:
                        movement_type = 'upward trend accelerates +'
                    elif ind['price_delta_p'] &lt; ind['price_delta_p_before'] * (1-cs_config[&quot;delta_threshold_p&quot;]):
                        movement_type = 'upward trend slows down +'
                    elif ind['price_delta_p'] * (1+cs_config[&quot;delta_threshold_p&quot;]) &gt;= ind['price_delta_p_before'] &gt;= ind['price_delta_p'] * (1-cs_config[&quot;delta_threshold_p&quot;]):
                        movement_type = 'upward trend continues +'
        # down
        elif ind['price_delta'] &lt; 0:
            movement_type = 'down '
            if abs(ind['price_delta_p_before']) &gt; cs_config[&quot;delta_threshold_p&quot;]:
                if ind['price_delta_before'] &gt; 0:
                    movement_type = 'pullback from ' + str(ind['price_before']) + ' to ' + str(ind['last_price'])
                else:
                    if ind['price_delta_p'] * (1-cs_config[&quot;delta_threshold_p&quot;]) &gt; ind['price_delta_p_before']:
                        movement_type = 'down trend accelerates '
                    elif ind['price_delta_p'] * (1+cs_config[&quot;delta_threshold_p&quot;]) &gt;= ind['price_delta_p_before'] &gt;= ind['price_delta_p'] * (1-cs_config[&quot;delta_threshold_p&quot;]):
                        movement_type = 'down trend continues '
                    elif ind['price_delta_p'] &lt; ind['price_delta_p_before'] * (1+cs_config[&quot;delta_threshold_p&quot;]):
                        movement_type = 'downward trend slows down '

        signal = get_signal_log(movement_type, currency, ind['price_delta_p'], ind['last_price'],
                                ind['moving_avg_price'], ind['volume'], ind['price_delta'], ind['change_percentage'],
                                ind['high_24h'], ind['low_24h'], ind['low_high_diff_p'])

        check_24h_peak(currency, ind['last_price'], ind['low_24h'], ind['high_24h'])

    return signal
    # trade_signal


def check_24h_peak(currency, last_price, low_24h, high_24h):
    if last_price &lt; low_24h:
        print(currency + ' new 24h low $' + str(last_price))
    elif last_price &gt; high_24h:
        print(currency + ' new 24h high $' + str(last_price))


def get_signal_log(movement_type, currency, price_delta_p, last_price, moving_avg_price, volume, price_delta,
                   daily_up_p, high_24h, low_24h, low_high_diff_p):
    signal = f'{currency} {movement_type} ' \
             f'{np.round(price_delta_p * 100, 5)}% ' \
             f'MA:${np.round(moving_avg_price, 6)} ' \
             f'last_price:${np.round(last_price, 6)} ' \
             f'price delta:{np.round(price_delta, 6)} ' \
             f'volume:${np.round(volume, 1)} ' \
             f'daily_change:{np.round(daily_up_p, 2)}% ' \
             f'high_24h:${high_24h} ' \
             f'low_24h:${low_24h} ' \
             f'low_high_diff_p:{np.round(low_high_diff_p * 100, 2)}%'
    return signal</pre></div>



<h3 class="wp-block-heading" id="h-step-4-send-tweets-via-twitter">Step #4: Send Tweets via Twitter</h3>



<p class="wp-block-paragraph">Next, we define a simple function that calls the Twitter API and tweets our price signal. Because the Twitter API requires authentication, you must provide the API authentication credentials from a valid Twitter developer account. </p>



<p class="wp-block-paragraph">It&#8217;s best not to store the API credentials directly in code. Still not perfect, but slightly better is to keep the data in a separate python file (for example, called &#8220;twitter_secrets&#8221;) that you put into your package folder (for example, under /anaconda3/Lib), from where you can import it directly into your code. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># Twitter Consumer API keys
CONSUMER_KEY    = &quot;api123&quot;
CONSUMER_SECRET = &quot;api123&quot;

# Twitter Access token &amp; access token secret
ACCESS_TOKEN    = &quot;api123&quot;
ACCESS_SECRET   = &quot;api123&quot;

BEARER_TOKEN = &quot;api123&quot;

class TwitterSecrets:
    &quot;&quot;&quot;Class that holds Twitter Secrets&quot;&quot;&quot;

    def __init__(self):
        self.CONSUMER_KEY    = CONSUMER_KEY
        self.CONSUMER_SECRET = CONSUMER_SECRET
        self.ACCESS_TOKEN    = ACCESS_TOKEN
        self.ACCESS_SECRET   = ACCESS_SECRET
        self.BEARER_TOKEN   = BEARER_TOKEN
        
        # Tests if keys are present
        for key, secret in self.__dict__.items():
            assert secret != &quot;&quot;, f&quot;Please provide a valid secret for: {key}&quot;

twitter_secrets = TwitterSecrets()</pre></div>



<p class="wp-block-paragraph">Once you have imported the file, you can then load the API credentials from the file in the following way: </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">consumer_key = ts.CONSUMER_KEY
consumer_secret = ts.CONSUMER_SECRET
access_token = ts.ACCESS_TOKEN
access_secret = ts.ACCESS_SECRET

### Print API Auth Data (leave disabled for security reasons)
# print(f'consumer_key: {consumer_key}')
# print(f'consumer_secret: {consumer_secret}')
# print(f'access_token: {access_token}')
# print(f'access_secret: {access_token}')

#authenticating to access the twitter API
auth=tweepy.OAuthHandler(consumer_key,consumer_secret)
auth.set_access_token(access_token,access_secret)
api=tweepy.API(auth)

def send_pricechange_tweet(signal):
    api.update_status(f&quot;{signal} \n {relataly_url}&quot;)</pre></div>



<h3 class="wp-block-heading" id="h-step-5-starting-the-crypto-signal-bot">Step #5 Starting the Crypto Signal Bot</h3>



<p class="wp-block-paragraph">Finally, we can hit the start button of our crypto signal bot. But before we do this, take a look at some configuration options of the bot.</p>



<ul class="wp-block-list">
<li>CYCLE_DELAY is the standard interval in seconds in which the bot will call the gate.io API. </li>



<li>CURRENCY_PAIR is another API parameter limiting the cryptocurrency pairs to specific currency pairs. The bot will scan the entire market with all currency pairs in the standard setting, including all USDT pairs.</li>



<li>TWITTER_ACTIVE defines whether the bot posts signals on Twitter. Be aware that your bot may instantly report any signal on your Twitter account if you enable it. </li>



<li>RUNS defines the max number of prices that the bot will retrieve before the bot stops. </li>
</ul>



<p class="wp-block-paragraph">Now, let&#8217;s test the bot:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">RUNS = 50 # the bot will stop after 50 price points
CYCLE_DELAY = 20 # the interval for checking the data and retrieving another price point
EVAL_PRICES_DELAY = 10
CURRENCY_PAIR = &quot;&quot; # the bot will retrieve data for all currency pairs listed on gate.io
PRICES_CONFIG = {&quot;price_update_delay&quot;: 20}
TWITTER_ACTIVE = False

CHECK_SIGNAL_CONFIG = {
    &quot;moving_avg_threshold_down_p&quot;: 0.10,
    &quot;moving_avg_threshold_up_p&quot;: 0.10,
    &quot;delta_threshold_p&quot;: 0.07,
    'enable_twitter': TWITTER_ACTIVE,
}

if __name__ == &quot;__main__&quot;:
    logging.basicConfig(
        level=logging.INFO, format=&quot;\033[02m%(asctime)s %(levelname)s: %(message)s&quot;
    )
    logger = logging.getLogger(__name__)
    prices = Prices(PRICES_CONFIG)
    prices.start_cont_update()
    currency_dfs = {}
    logging.info(f&quot;Crypto bot is starting - please wait&quot;)
    logger.info(f&quot;Collecting crypto data from gate.io for {EVAL_PRICES_DELAY}s&quot;)
    time.sleep(EVAL_PRICES_DELAY)
    logger.info(f&quot;\n&lt;&lt; Crypto signal bot started :-) &gt;&gt;&quot;)
    logger.info(f&quot;&lt;&lt; Checking prices every {CYCLE_DELAY} seconds &gt;&gt;&quot;)
    logger.info(f&quot;Now checking for signals - please wait\n&quot;)
    for i in range(RUNS):
        price_history, lock = prices.get_price_history()
        lock.acquire()
        indicators = calc_indicators(price_history)
        lock.release()
        for currency in indicators.keys():
            if not indicators[currency]:
                continue
            signal = check_signal(
                currency,
                indicators,
                CHECK_SIGNAL_CONFIG,
            )
            if signal:
                logger.info(signal)
                if CHECK_SIGNAL_CONFIG['enable_twitter']:
                    send_pricechange_tweet(signal)
                    print('send via twitter')
        time.sleep(CYCLE_DELAY)</pre></div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">2022-03-09 11:40:38,939 INFO: Started continuous price logging
2022-03-09 11:40:38,940 INFO: Crypto bot is starting - please wait
2022-03-09 11:40:38,940 INFO: Collecting crypto data from gate.io for 10s
2022-03-09 11:40:48,941 INFO: 
&lt;&lt; Crypto signal bot started :-) &gt;&gt;
2022-03-09 11:40:48,942 INFO: &lt;&lt; Checking prices every 20 seconds &gt;&gt;
2022-03-09 11:40:48,942 INFO: Now checking for signals - please wait

2022-03-09 11:52:06,800 INFO: EOSBULL_USDT up + 19.42446% MA:$1.1e-05 last_price:$1.4e-05 price delta:3e-06 volume:$1272326905.1 daily_change:33.65% high_24h:$1.16e-05 low_24h:$9.8e-06low_high_diff_p:18.37%
EOSBULL_USDT new 24h high $1.39e-05
send via twitter</pre></div>



<p class="wp-block-paragraph"> And this is what the tweets will look like on Twitter:</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" data-attachment-id="4060" data-permalink="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/image-11-10/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/05/image-11.png" data-orig-size="788,724" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-11" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/05/image-11.png" src="https://www.relataly.com/wp-content/uploads/2021/05/image-11.png" alt="output of our twitter bot, signalling logic, algorithmic trading, crypto price bot, gateio" class="wp-image-4060" width="512" height="470" srcset="https://www.relataly.com/wp-content/uploads/2021/05/image-11.png 788w, https://www.relataly.com/wp-content/uploads/2021/05/image-11.png 300w, https://www.relataly.com/wp-content/uploads/2021/05/image-11.png 768w" sizes="(max-width: 512px) 100vw, 512px" /></figure>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p class="wp-block-paragraph">Congratulations on completing this tutorial! In this article, you learned how to build a Python-based Twitter crypto signal bot. When run, the bot will regularly retrieve cryptocurrency quotes from the Gate.io exchange and tweet about any price movements based on a simple signaling logic.</p>



<p class="wp-block-paragraph">While the signaling logic in this tutorial is kept simple, this basic framework provides a foundation for you to further develop and enhance the signaling rules. For example, you could consider using volume or price volatility changes as the basis for defining signals. Have fun experimenting and expanding upon this project!</p>



<p class="wp-block-paragraph">If you found this article helpful, please show your appreciation by leaving a comment. Cheers</p>



<h2 class="wp-block-heading" id="h-sources-and-further-reading">Sources and Further Reading</h2>



<ol class="wp-block-list"><li><a href="https://amzn.to/3MyU6Tj" target="_blank" rel="noreferrer noopener">Charu C. Aggarwal (2018) Neural Networks and Deep Learning</a></li><li><a href="https://amzn.to/3yIQdWi" target="_blank" rel="noreferrer noopener">Jansen (2020) Machine Learning for Algorithmic Trading: Predictive models to extract signals from market and alternative data for systematic trading strategies with Python</a></li><li><a href="https://amzn.to/3S9Nfkl" target="_blank" rel="noreferrer noopener">Aurélien Géron (2019) Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow: Concepts, Tools, and Techniques to Build Intelligent Systems </a></li><li><a href="https://amzn.to/3EKidwE" target="_blank" rel="noreferrer noopener">David Forsyth (2019) Applied Machine Learning Springer</a></li><li><a href="https://amzn.to/3MAy8j5" target="_blank" rel="noreferrer noopener">Andriy Burkov (2020) Machine Learning Engineering</a></li></ol>



<p class="has-contrast-2-color has-base-3-background-color has-text-color has-background wp-block-paragraph"><em>The links above to Amazon are affiliate links. By buying through these links, you support the Relataly.com blog and help to cover the hosting costs. Using the links does not affect the price.</em></p>
<p>The post <a href="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/">Automate Crypto Trading with a Python-Powered Twitter Bot and Gate.io Signals</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3974</post-id>	</item>
		<item>
		<title>Posting Tweets On Twitter using Python and Tweepy</title>
		<link>https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/</link>
					<comments>https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/#respond</comments>
		
		<dc:creator><![CDATA[Florian Follonier]]></dc:creator>
		<pubDate>Sun, 09 May 2021 15:14:45 +0000</pubDate>
				<category><![CDATA[REST APIs]]></category>
		<category><![CDATA[Twitter API]]></category>
		<category><![CDATA[AI in E-Commerce]]></category>
		<category><![CDATA[API Tutorials]]></category>
		<category><![CDATA[Automated Twitter Posts]]></category>
		<category><![CDATA[Beginner Tutorials]]></category>
		<category><![CDATA[Social Media Data]]></category>
		<category><![CDATA[Tweepy]]></category>
		<guid isPermaLink="false">https://www.relataly.com/?p=3925</guid>

					<description><![CDATA[<p>In a previous article, we have shown how to retrieve social media data via the Twitter API in Python. However, we can do many more cool things with the Twitter API. Another cool thing is interacting with the Twitter user account and posting automated tweets. This article shows how this works. We will use the ... <a title="Posting Tweets On Twitter using Python and Tweepy" class="read-more" href="https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/" aria-label="Read more about Posting Tweets On Twitter using Python and Tweepy">Read more</a></p>
<p>The post <a href="https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/">Posting Tweets On Twitter using Python and Tweepy</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">In a previous article, we have shown how to <a href="https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/" target="_blank" rel="noreferrer noopener">retrieve social media data via the Twitter API in Python</a>. However, we can do many more cool things with the Twitter API. Another cool thing is interacting with the Twitter user account and posting automated tweets. This article shows how this works. We will use the Twitter API and the Tweepy library to submit tweets to our Twitter account. </p>



<p class="wp-block-paragraph">A common use case for submitting tweets via the Twitter API is a <a href="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/" target="_blank" rel="noreferrer noopener">Twitter bot</a>. Today, many bots on Twitter send automated tweets, for example, about unusual movements in the stock market or other types of events. However, it is worth mentioning that bots are also used for evil purposes, for example, to lure people into scams or influence political opinions.</p>



<p class="wp-block-paragraph">This tutorial lays the foundation for building a simple Twitter bot with Python and Tweepy. The remainder of this article is structured as follows: We&#8217;ll begin by briefly looking at the tweet object on Twitter. Then, we will write some code that requests authentication via the Twitter API and submit some test tweets to the API.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow"></div>
</div>



<h2 class="wp-block-heading" id="h-the-tweet-object-of-the-twitter-api">The Tweet Object of the Twitter API</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">Tweets are the basic building blocks of Twitter. They have several customization options, such as media, hashtags, and emojis. We can use all of these options by specifying respective parameters in our requests to the Twitter API.</p>



<p class="wp-block-paragraph">First of all, a tweet contains up to 280 characters of text. The text can include hashtags or emojis, which also occupy space in terms of characters.</p>



<p class="wp-block-paragraph">While hashtags are indicated via the #-sign, emojis are displayed via standard Unicode. Most emojis occupy two characters of the maximum text length, but some may require more. Here you can find an overview of the emoji Unicode. </p>



<p class="wp-block-paragraph">Optionally, tweets can contain media objects such as images, GIFs, or Polls. We can attach these elements via a separate API function.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="294" data-attachment-id="3949" data-permalink="https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/image-2-14/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/05/image-2.png" data-orig-size="1493,428" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-2" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/05/image-2.png" src="https://www.relataly.com/wp-content/uploads/2021/05/image-2-1024x294.png" alt="Submitting a Twitter Tweet" class="wp-image-3949" srcset="https://www.relataly.com/wp-content/uploads/2021/05/image-2.png 1024w, https://www.relataly.com/wp-content/uploads/2021/05/image-2.png 300w, https://www.relataly.com/wp-content/uploads/2021/05/image-2.png 768w, https://www.relataly.com/wp-content/uploads/2021/05/image-2.png 1493w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Submitting a Twitter Tweet</figcaption></figure>
</div>
</div>



<h2 class="wp-block-heading" id="h-implementation-posting-tweets-via-the-twitter-api-in-python">Implementation: Posting Tweets via the Twitter API in Python </h2>



<p class="wp-block-paragraph">This tutorial shows how to write a short Python script that authenticates against Twitter. Then we will submit some test Tweets using your Twitter account. We will look at two different cases:</p>



<ul class="wp-block-list">
<li>Submitting a simple text-only tweet </li>



<li>Submitting a tweet that contains text and a media file</li>
</ul>



<p class="wp-block-paragraph">The code is available on the GitHub repository.</p>



<div class="wp-block-kadence-advancedbtn kb-buttons-wrap kb-btns_c22607-1b"><a class="kb-button kt-button button kb-btn_c436b2-88 kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-API-tutorials/blob/main/111%20Posting%20Tweets%20via%20the%20Twitter%20API%20v2.0.ipynb" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fe_eye kt-btn-icon-side-left"><svg viewBox="0 0 24 24"  fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></span><span class="kt-btn-inner-text">View on GitHub </span></a>

<a class="kb-button kt-button button kb-btn_c55bfd-d7 kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-API-tutorials" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fa_github kt-btn-icon-side-left"><svg viewBox="0 0 496 512"  fill="currentColor" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg></span><span class="kt-btn-inner-text">Relataly GitHub Repo </span></a></div>



<h3 class="wp-block-heading" id="h-prerequisites">Prerequisites</h3>



<p class="wp-block-paragraph">Using the Twitter API requires a Twitter <a href="https://developer.twitter.com/en" target="_blank" rel="noreferrer noopener">developer account</a>. If you don&#8217;t have one yet, you can follow the steps described in <a href="https://www.relataly.com/wp-admin/post.php?post=1976&amp;action=edit" target="_blank" rel="noreferrer noopener">this tutorial</a> to create an account for free.</p>



<p class="wp-block-paragraph">Before starting the coding part, make sure that you have set up your Python 3 environment and required packages. If you don&#8217;t have an environment set up yet, you can follow&nbsp;this tutorial&nbsp;to set up the&nbsp;<a href="https://www.anaconda.com/products/individual" target="_blank" rel="noreferrer noopener">Anaconda environment</a>.</p>



<p class="wp-block-paragraph">Also, make sure you install all required packages. In this article, we will be working with the following standard packages:&nbsp;</p>



<ul class="wp-block-list">
<li><em><a href="https://pandas.pydata.org/" target="_blank" rel="noreferrer noopener">pandas</a></em></li>
</ul>



<p class="wp-block-paragraph">In addition, we will be using <a href="https://www.tweepy.org/" target="_blank" rel="noreferrer noopener">Tweepy</a>. Tweepy is an easy-to-use Python library for accessing the Twitter API.</p>



<p class="wp-block-paragraph">You can install packages using console commands:</p>



<ul class="wp-block-list">
<li><em>pip install &lt;package name&gt;</em></li>
</ul>



<h3 class="wp-block-heading" id="h-step-1-load-twitter-account-credentials-for-authentication">Step #1: Load Twitter Account Credentials for Authentication</h3>



<p class="wp-block-paragraph">Before interacting with the Twitter API, we must authenticate with our developer account credentials. The developer account is linked to the Twitter account specified during registration. So, when you execute an API request, it will use the associated Twitter user.</p>



<h4 class="wp-block-heading" id="h-storing-the-account-credentials-in-a-python-file">Storing the Account Credentials in a Python File</h4>



<p class="wp-block-paragraph">We should not store the user credentials directly in our Python notebooks. Instead, we should use a Python file and import it into our notebook. You can use the following sample file and replace the values with your Twitter API keys, secrets, and tokens.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}"># Twitter Consumer API keys
CONSUMER_KEY    = &quot;api123&quot;
CONSUMER_SECRET = &quot;api123&quot;

# Twitter Access token &amp; access token secret
ACCESS_TOKEN    = &quot;api123&quot;
ACCESS_SECRET   = &quot;api123&quot;

BEARER_TOKEN = &quot;api123&quot;

class TwitterSecrets:
    &quot;&quot;&quot;Class that holds Twitter Secrets&quot;&quot;&quot;

    def __init__(self):
        self.CONSUMER_KEY    = CONSUMER_KEY
        self.CONSUMER_SECRET = CONSUMER_SECRET
        self.ACCESS_TOKEN    = ACCESS_TOKEN
        self.ACCESS_SECRET   = ACCESS_SECRET
        self.BEARER_TOKEN   = BEARER_TOKEN
        
        # Tests if keys are present
        for key, secret in self.__dict__.items():
            assert secret != &quot;&quot;, f&quot;Please provide a valid secret for: {key}&quot;

twitter_secrets = TwitterSecrets()</pre></div>



<p class="wp-block-paragraph">Once you have stored the API keys in the file and the file in the right folder, you can load the API keys into your Python project with the following code.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">import pandas as pd
import tweepy 

# place the twitter_secrets file under &lt;User&gt;/anaconda3/Lib
from twitter_secrets import twitter_secrets as ts

consumer_key = ts.CONSUMER_KEY
consumer_secret = ts.CONSUMER_SECRET
access_token = ts.ACCESS_TOKEN
access_secret = ts.ACCESS_SECRET

### Print API Auth Data (leave disabled for security reasons)
# print(f'consumer_key: {consumer_key}')
# print(f'consumer_secret: {consumer_secret}')
# print(f'access_token: {access_token}')
# print(f'access_secret: {access_token}')</pre></div>



<h4 class="wp-block-heading" id="h-alternative-storing-the-account-credentials-in-a-yaml-file">Alternative: Storing the Account Credentials in a YAML File</h4>



<p class="wp-block-paragraph">Alternatively, you can also put the credentials into a YAML file (called &#8220;api_config_twitter.yml.&#8221; The file should then look as follows, and you can place it in a subfolder &#8220;API Keys&#8221; in your working directory:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:false,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;null&quot;,&quot;mime&quot;:&quot;text/plain&quot;,&quot;theme&quot;:&quot;3024-day&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Plain Text&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;text&quot;}">api_key: api123 
api_secret: api123
access_token: api123
access_secret: api123</pre></div>



<p class="wp-block-paragraph">You can then import the token and access keys with the code below. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">## In case you prefer to load the auth data from a local yaml file, use the following code
import yaml
# load the API keys and further data from your local yaml file
# place the api_config_twitter.yml file under &lt;python notebook&gt;/API_Keys/
yaml_file = open('API Keys/api_config_twitter.yml', 'r')  
p = yaml.load(yaml_file, Loader=yaml.FullLoader)

try:
    consumer_key = p['api_key']
    consumer_secret = p['api_secret']
    access_token = p['access_token']
    access_secret = p['access_secret']
except ValueError: 
        print('error')</pre></div>



<h3 class="wp-block-heading" id="h-step-2-request-user-authentication-via-the-api">Step #2: Request User Authentication via the API</h3>



<p class="wp-block-paragraph">When you have the auth data available in your project, you can authenticate against the Twitter API. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">#authenticating to access the twitter API
auth=tweepy.OAuthHandler(consumer_key,consumer_secret)
auth.set_access_token(access_token,access_secret)
api=tweepy.API(auth)</pre></div>



<h3 class="wp-block-heading" id="h-step-3-post-a-text-only-tweet-on-twitter">Step #3: Post a Text-only Tweet on Twitter</h3>



<p class="wp-block-paragraph">Once we successfully authenticate at the Twitter API, we can interact with our Twitter user account. The code below will submit a test tweet via Twitter API. As you can see, we also indicated two hashtags.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># Define the tweet text
tweet='this is an automated test tweet using #Python $BTC $ETH'

# Generate text tweet
api.update_status(tweet)</pre></div>



<p class="wp-block-paragraph">Once you run the code, the tweet will immediately appear in the feed of our Twitter account:</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" data-attachment-id="3956" data-permalink="https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/image-4-13/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/05/image-4.png" data-orig-size="746,146" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-4" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/05/image-4.png" src="https://www.relataly.com/wp-content/uploads/2021/05/image-4.png" alt="A simple test tweet sent via the Twitter API" class="wp-image-3956" width="588" height="115" srcset="https://www.relataly.com/wp-content/uploads/2021/05/image-4.png 746w, https://www.relataly.com/wp-content/uploads/2021/05/image-4.png 300w" sizes="(max-width: 588px) 100vw, 588px" /><figcaption class="wp-element-caption">A simple test tweet sent via the Twitter API</figcaption></figure>



<h3 class="wp-block-heading" id="h-step-4-include-mediafiles-in-tweets-via-the-api">Step #4: Include Mediafiles in Tweets via the API</h3>



<p class="wp-block-paragraph">We can also include media files such as photos and videos in our tweets. For this case, Tweety provides a separate function called &#8220;update_with_media.&#8221; This function takes two arguments: the image path and tweet_text. </p>



<p class="wp-block-paragraph">Before running the code below, you need to change the image_path to reference an image file on your computer.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># Define the tweet text
tweet_text='This is another automated test tweet using #Python'
image_path ='Test Images/ETH_price.png'

# Generate text tweet with media (image)
status = api.update_with_media(image_path, tweet_text)</pre></div>



<p class="wp-block-paragraph">Et voilà: Another Tweet has appeared on our Twitter Account. This time, the post includes the sample text and a media file.</p>



<figure class="wp-block-image size-large is-resized"><img decoding="async" data-attachment-id="3955" data-permalink="https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/image-3-13/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/05/image-3.png" data-orig-size="757,431" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-3" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/05/image-3.png" src="https://www.relataly.com/wp-content/uploads/2021/05/image-3.png" alt="Twitter tweet with an image attached" class="wp-image-3955" width="646" height="367" srcset="https://www.relataly.com/wp-content/uploads/2021/05/image-3.png 757w, https://www.relataly.com/wp-content/uploads/2021/05/image-3.png 300w" sizes="(max-width: 646px) 100vw, 646px" /><figcaption class="wp-element-caption">Twitter tweet with an image attached</figcaption></figure>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p class="wp-block-paragraph">This article has shown how you can use Tweepy and Python to submit tweets via the Twitter API. You have learned to authenticate against the Twitter API and submit tweets containing text and media files.</p>



<p class="wp-block-paragraph">Understanding how to interact with Twitter via the API is essential when creating a Twitter bot. I have written another article about creating a Twitter signaling bot that analyzes financial data and tweets about relevant price movements. If you want to learn more about this topic, check out this article on<a href="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/" target="_blank" rel="noreferrer noopener"> Generating crypto trading signals in Python</a></p>



<h2 class="wp-block-heading">Sources and Further Reading</h2>



<div style="display: inline-block;">
  <iframe sandbox="allow-popups allow-scripts allow-modals allow-forms allow-same-origin" style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//ws-eu.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&amp;OneJS=1&amp;Operation=GetAdHtml&amp;MarketPlace=DE&amp;source=ss&amp;ref=as_ss_li_til&amp;ad_type=product_link&amp;tracking_id=flo7up-21&amp;language=de_DE&amp;marketplace=amazon&amp;region=DE&amp;placement=3030181162&amp;asins=3030181162&amp;linkId=669e46025028259138fbb5ccec12dfbe&amp;show_border=true&amp;link_opens_in_new_window=true"></iframe>
<iframe sandbox="allow-popups allow-scripts allow-modals allow-forms allow-same-origin" style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//ws-eu.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&amp;OneJS=1&amp;Operation=GetAdHtml&amp;MarketPlace=DE&amp;source=ss&amp;ref=as_ss_li_til&amp;ad_type=product_link&amp;tracking_id=flo7up-21&amp;language=de_DE&amp;marketplace=amazon&amp;region=DE&amp;placement=1999579577&amp;asins=1999579577&amp;linkId=91d862698bf9010ff4c09539e4c49bf4&amp;show_border=true&amp;link_opens_in_new_window=true"></iframe>
<iframe sandbox="allow-popups allow-scripts allow-modals allow-forms allow-same-origin" style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//ws-eu.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&amp;OneJS=1&amp;Operation=GetAdHtml&amp;MarketPlace=DE&amp;source=ss&amp;ref=as_ss_li_til&amp;ad_type=product_link&amp;tracking_id=flo7up-21&amp;language=de_DE&amp;marketplace=amazon&amp;region=DE&amp;placement=1839217715&amp;asins=1839217715&amp;linkId=356ba074068849ff54393f527190825d&amp;show_border=true&amp;link_opens_in_new_window=true"></iframe>
<iframe sandbox="allow-popups allow-scripts allow-modals allow-forms allow-same-origin" style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//ws-eu.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&amp;OneJS=1&amp;Operation=GetAdHtml&amp;MarketPlace=DE&amp;source=ss&amp;ref=as_ss_li_til&amp;ad_type=product_link&amp;tracking_id=flo7up-21&amp;language=de_DE&amp;marketplace=amazon&amp;region=DE&amp;placement=1492032646&amp;asins=1492032646&amp;linkId=2214804dd039e7103577abd08722abac&amp;show_border=true&amp;link_opens_in_new_window=true"></iframe>
</div>



<p class="has-contrast-2-color has-base-3-background-color has-text-color has-background wp-block-paragraph"><em>The links above to Amazon are affiliate links. By buying through these links, you support the Relataly.com blog and help to cover the hosting costs. Using the links does not affect the price.</em></p>
<p>The post <a href="https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/">Posting Tweets On Twitter using Python and Tweepy</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3925</post-id>	</item>
		<item>
		<title>Streaming Tweets and Images via the Twitter API in Python</title>
		<link>https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/</link>
					<comments>https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/#comments</comments>
		
		<dc:creator><![CDATA[Florian Follonier]]></dc:creator>
		<pubDate>Sun, 03 Jan 2021 21:46:47 +0000</pubDate>
				<category><![CDATA[Data Science]]></category>
		<category><![CDATA[Data Sources]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Twitter API]]></category>
		<category><![CDATA[API Tutorials]]></category>
		<category><![CDATA[Beginner Tutorials]]></category>
		<category><![CDATA[Requesting Data via REST APIs]]></category>
		<category><![CDATA[Social Media Data]]></category>
		<guid isPermaLink="false">https://www.relataly.com/?p=1976</guid>

					<description><![CDATA[<p>Twitter is a rich source of data that can be used to understand current and future trends. Because tweets often include hashtags, they can be easily linked to specific contexts such as political discussions or financial instruments. This makes Twitter a valuable tool for collecting and analyzing data. In this article, we&#8217;ll demonstrate how to ... <a title="Streaming Tweets and Images via the Twitter API in Python" class="read-more" href="https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/" aria-label="Read more about Streaming Tweets and Images via the Twitter API in Python">Read more</a></p>
<p>The post <a href="https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/">Streaming Tweets and Images via the Twitter API in Python</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">Twitter is a rich source of data that can be used to understand current and future trends. Because tweets often include hashtags, they can be easily linked to specific contexts such as political discussions or financial instruments. This makes Twitter a valuable tool for collecting and analyzing data. In this article, we&#8217;ll demonstrate how to use Python to access Twitter data via the <a href="https://developer.twitter.com/en/docs/twitter-api" target="_blank" rel="noreferrer noopener">Twitter API v2</a>. We&#8217;ll show how to extract tweets, process them, and use them to gain insights and make predictions. Whether you&#8217;re a data scientist, a business analyst, or a social media enthusiast, this tutorial will provide you with the tools you need to work with Twitter data in Python.</p>



<p class="wp-block-paragraph">This article shows two specific cases:</p>



<ul class="wp-block-list">
<li>Example A: Streaming Tweets and Storing the Data in a DataFrame</li>



<li>Example B: Streaming Images for a specific channel and storing them in a local directory</li>
</ul>



<p class="wp-block-paragraph"><a>If you are new to APIs, consider first familiarizing yourself with the </a><a href="https://www.relataly.com/access-data-sources-using-apis/278/" target="_blank" rel="noreferrer noopener">basics of REST APIs</a>.</p>



<p class="wp-block-paragraph">The rest of this article is structured as follows: First, we&#8217;ll look at how to sign up to use the Twitter API and obtain an authentication token. We will then look at the object model of Twitter and use the security token in our requests to the Twitter API. Then we will turn to the two examples, A &amp; B.</p>



<p class="wp-block-paragraph">Also: <a href="https://www.relataly.com/access-remote-data-sources-using-rest-apis-in-python/278/" target="_blank" rel="noreferrer noopener">Accessing Remote Data Sources via REST APIs in Python</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<figure class="wp-block-image size-large is-resized"><img decoding="async" data-attachment-id="3831" data-permalink="https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/image-119/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/05/image.png" data-orig-size="1576,1132" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/05/image.png" src="https://www.relataly.com/wp-content/uploads/2021/05/image-1024x736.png" alt="twitter api python" class="wp-image-3831" width="353" height="254" srcset="https://www.relataly.com/wp-content/uploads/2021/05/image.png 1024w, https://www.relataly.com/wp-content/uploads/2021/05/image.png 300w, https://www.relataly.com/wp-content/uploads/2021/05/image.png 768w, https://www.relataly.com/wp-content/uploads/2021/05/image.png 1536w, https://www.relataly.com/wp-content/uploads/2021/05/image.png 1576w" sizes="(max-width: 353px) 100vw, 353px" /><figcaption class="wp-element-caption">Twitter data is a playground for data scientists.</figcaption></figure>
</div>
</div>



<div style="height:33px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading" id="h-basics-of-the-twitter-api">Basics of the Twitter API</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">Twitter data has a variety of applications. For example, we can analyze tweets to discover trends or evaluate sentiment on a topic. Furthermore, images embedded in tweets and hashtags can train image recognition models or validate them. Thus, knowing how to obtain data via the Twitter API can be helpful if you are doing data science.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h3 class="wp-block-heading" id="h-api-versions">API Versions</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">Twitter provides two different API versions: The two versions have their documentation and are incompatible. While the API v1.1 is still more established, Twitter API v2 offers more options for fetching data from Twitter. For example, it allows tailoring the fields given back with the response, which can be helpful if the goal is to minimize traffic. The Twitter API v2 is currently in early access mode, but it will sooner or later become the new standard API in the market. Therefore, I decided to base this tutorial on the newer v2-version.</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img decoding="async" data-attachment-id="2803" data-permalink="https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/image-2-10/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/01/image-2.png" data-orig-size="1131,821" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-2" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/01/image-2.png" src="https://www.relataly.com/wp-content/uploads/2021/01/image-2-1024x743.png" alt="Twitter API specification" class="wp-image-2803" width="662" height="478"/><figcaption class="wp-element-caption">Overview of Twitter APIs (Source: Twitter)</figcaption></figure>
</div></div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h3 class="wp-block-heading" id="h-twitter-api-documentation">Twitter API Documentation</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">When working with the Twitter <strong><a href="https://developer.twitter.com/en/docs/twitter-api/early-access" target="_blank" rel="noreferrer noopener">API v2</a></strong>, it is vital to understand the Twitter object model. The tweet object acts as the parent of four subobjects: according to the API documentation, the basic building block of Twitter is the Tweet object. It has various fields attached, such as the tweet text, created_at, and tweet id. The Twitter API documentation provides a complete list of these root-level fields. The standard API response does not include most of the areas. If we want to retrieve additional fields, we need to specify these fields in the request rules. </p>



<ul class="wp-block-list">
<li><a href="https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/user" target="_blank" rel="noreferrer noopener">User object</a></li>



<li><a href="https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/media" target="_blank" rel="noreferrer noopener">Media object</a></li>



<li><a href="https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/poll" target="_blank" rel="noreferrer noopener">Poll object</a></li>



<li><a href="https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/place" target="_blank" rel="noreferrer noopener">Place objects</a></li>
</ul>



<p class="wp-block-paragraph">Each object, in turn, has multiple fields for which we specify which fields to return in the rule, as with the Tweet Object. This article uses the tweet object and the media object, which contains all the media (e.g., images or videos) that tweets can have attached. </p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h4 class="wp-block-heading" id="h-functioning-of-the-recent-search-endpoint">Functioning of the Recent Search Endpoint</h4>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">In this tutorial, we will be working with the <a href="https://developer.twitter.com/en/docs/twitter-api/tweets/search/introduction" target="_blank" rel="noreferrer noopener">Twitter Recent Search Endpoint</a>. There are also other API endpoints, but covering all of them would go beyond the scope of this article. One notable feature of the Recent Search endpoint is that we can&#8217;t retrieve the data directly using GET requests but first have to send a POST request to the API specifying which information we want to fetch. To change these rules, we first have to delete them with a POST request and then pass the new ruleset to the API with another POST request. This procedure may sound complicated, but it gives the user more control over the API.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<p class="wp-block-paragraph"></p>



<h4 class="wp-block-heading" id="h-different-api-models">Different API Models</h4>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">We can use the &#8220;Recent Search Endpoint&#8221; in batch and streaming modes. In batch mode, the endpoint returns a list of tweets once. If the stream option is enabled, the API returns a continuous flow of individual tweets, plus any new tweets as they are published to Twitter. In this way, we can stream and process tweets in (almost) real-time. In this tutorial, we will work with the streaming option enabled.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"><div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img decoding="async" data-attachment-id="2812" data-permalink="https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/image-5-8/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/01/image-5.png" data-orig-size="434,445" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-5" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/01/image-5.png" src="https://www.relataly.com/wp-content/uploads/2021/01/image-5.png" alt="" class="wp-image-2812" width="266" height="272" srcset="https://www.relataly.com/wp-content/uploads/2021/01/image-5.png 434w, https://www.relataly.com/wp-content/uploads/2021/01/image-5.png 293w" sizes="(max-width: 266px) 100vw, 266px" /><figcaption class="wp-element-caption">Stream Mode vs. Batch Mode</figcaption></figure>
</div></div>
</div>



<h4 class="wp-block-heading">Filters</h4>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">We can limit the tweets and fields that the API includes in the response by specifying parameters. For example, we can let the API know that we want to retrieve tweets with specific keywords or in a certain period or only those tweets with images attached. The <a href="https://developer.twitter.com/en/docs/twitter-api/tweets/filtered-stream/integrate/build-a-rule" target="_blank" rel="noreferrer noopener">API documentation</a> provides a list of all filter parameters.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h2 class="wp-block-heading" id="h-twitter-search-api-python-examples">Twitter Search-API Python Examples</h2>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">To stream tweets from Twitter, you will need to use the Twitter API. The API allows developers to access Twitter&#8217;s data and functionality, including the ability to stream real-time tweets. In order to stream tweets, you will need to sign up for a Twitter developer account and obtain the necessary credentials, such as a consumer key and access token. Once you have these credentials, you can use them to authenticate your API requests and access the streaming endpoint for tweets.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h3 class="wp-block-heading" id="h-setup-a-twitter-developer-account">Setup a Twitter Developer Account</h3>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">Using the Twitter API requires you to have your own Twitter developer account. If you don&#8217;t have an account yet, you need to create it on the Twitter <a href="https://developer.twitter.com/" target="_blank" rel="noreferrer noopener">developer page</a>. As of Jan 2021, the standard developer account is free and comes with a limit of 500.000 tweets that you can fetch per month.</p>



<p class="wp-block-paragraph">After logging into your developer account, go to the <a href="https://developer.twitter.com/en/portal/dashboard" target="_blank" rel="noreferrer noopener">developer dashboard page</a> and create a new project with a name of your choice. Once you have created a project, it will be shown in the &#8220;projects dashboard,&#8221; along with an overview of your monthly tweet usage. In the next section, you will retrieve your API key from the project.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"></div>
</div>



<h4 class="wp-block-heading" id="h-obtaining-your-twitter-api-security-key">Obtaining your Twitter API Security Key</h4>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<p class="wp-block-paragraph">The Twitter API accepts our requests only if we provide a personal Bearer token for authentication. Each project has its Bearer token. You can find the bearer token in the Developer Portal under the Authentication Token section. Store the token somewhere in between. In the next step, we will store it in a secure location.</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%"><div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img decoding="async" data-attachment-id="2768" data-permalink="https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/image-1-10/#main" data-orig-file="https://www.relataly.com/wp-content/uploads/2021/01/image-1.png" data-orig-size="1752,919" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image-1" data-image-description="" data-image-caption="" data-large-file="https://www.relataly.com/wp-content/uploads/2021/01/image-1.png" src="https://www.relataly.com/wp-content/uploads/2021/01/image-1-1024x537.png" alt="Twitter API Authentication Tokens" class="wp-image-2768" width="308" height="161" srcset="https://www.relataly.com/wp-content/uploads/2021/01/image-1.png 1024w, https://www.relataly.com/wp-content/uploads/2021/01/image-1.png 300w, https://www.relataly.com/wp-content/uploads/2021/01/image-1.png 768w, https://www.relataly.com/wp-content/uploads/2021/01/image-1.png 1536w, https://www.relataly.com/wp-content/uploads/2021/01/image-1.png 1752w" sizes="(max-width: 308px) 100vw, 308px" /><figcaption class="wp-element-caption">Twitter API Authentication Tokens</figcaption></figure>
</div></div>
</div>



<h4 class="wp-block-heading" id="h-storing-and-loading-api-tokens">Storing and Loading API Tokens</h4>



<p class="wp-block-paragraph">The Twitter API requires the user to authenticate during use by providing a secret token. It is best not to store these keys in your project but to put them separately in a safe place. In a production environment, you would, of course, want to decrypt the keys. However, it should be sufficient to store the key in a separate python file for our test case.</p>



<p class="wp-block-paragraph">Create a new Python file called &#8220;twitter_secrets.py&#8221; and fill in the following code. Then replace the Bearer_Key with the key you retrieved from the Twitter Developer portal in the previous step.</p>



<p class="wp-block-paragraph">In the following, create a Python file called &#8220;twitter_secrets.py&#8221; and fill in the code below:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">&quot;&quot;&quot;Replace the values below with your own Twitter API Tokens&quot;&quot;&quot;

# Twitter Bearer Token
BEARER_KEY = &quot;your own BEARER KEY&quot;


class TwitterSecrets:
    &quot;&quot;&quot;Class that holds Twitter Secrets&quot;&quot;&quot;

    def __init__(self):
        self.BEARER_KEY = BEARER_KEY
        
        # Tests if keys are present
        for key, secret in self.__dict__.items():
            assert secret != &quot;&quot;, f&quot;Please provide a valid secret for: {key}&quot;

twitter_secrets = TwitterSecrets()</pre></div>



<p class="wp-block-paragraph">Then replace the Bearer_Key with the key you retrieved from the Twitter Developer portal in the previous step.</p>



<p class="wp-block-paragraph">The twitter_screts.py has to go to the package library of your python environment. If you use anaconda under Windows, the path is typically: &lt;user&gt;\anaconda3\Lib. Once you have placed the file in your python library, you can import it into your python project and use the bearer token from the import, as shown below:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># imports the twitter_secrets python file in which we store the twitter API keys
from twitter_secrets import twitter_secrets as ts

bearer_token = ts.BEARER_TOKEN</pre></div>



<h3 class="wp-block-heading" id="h-prerequisites">Prerequisites</h3>



<p class="wp-block-paragraph">Before starting the coding part, make sure that you have set up your Python 3 environment and required packages. If you don&#8217;t have an environment set up yet, you can follow&nbsp;this tutorial&nbsp;to set up the&nbsp;<a href="https://www.anaconda.com/products/individual" target="_blank" rel="noreferrer noopener">Anaconda environment</a>.</p>



<p class="wp-block-paragraph">Also, make sure you install all required packages. In this tutorial, we will be working with the following standard packages:&nbsp;</p>



<ul class="wp-block-list">
<li><em><a href="https://pandas.pydata.org/" target="_blank" rel="noreferrer noopener">pandas</a></em></li>
</ul>



<p class="wp-block-paragraph">You can install packages using console commands:</p>



<ul class="wp-block-list">
<li><em>pip install &lt;package name&gt;</em></li>



<li><em>conda install &lt;package name&gt;</em>&nbsp;(if you are using the anaconda packet manager)</li>
</ul>



<h3 class="wp-block-heading" id="h-example-a-streaming-tweets-via-the-twitter-recent-search-endpoint">Example A: Streaming Tweets via the Twitter Recent Search Endpoint</h3>



<p class="wp-block-paragraph">In the first use case, we will first define some simple filter rules and then request tweets from the API based on these rules. As a response, the API returns a stream of tweets which we will process further. We store the text from the tweets in a DataFrame and further tweet information.</p>



<p class="wp-block-paragraph">We won&#8217;t detail all the code components, but we will go through the most important functions with inline code. The code is available on the GitHub repository.</p>



<div class="wp-block-kadence-advancedbtn kb-buttons-wrap kb-btns_ea7ba1-49"><a class="kb-button kt-button button kb-btn_37eb41-5b kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-API-tutorials/blob/main/126%20Getting%20Real-Time%20Price%20Data%20via%20the%20Gate.io%20API.ipynb" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fe_eye kt-btn-icon-side-left"><svg viewBox="0 0 24 24"  fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></span><span class="kt-btn-inner-text">View on GitHub </span></a>

<a class="kb-button kt-button button kb-btn_c92de6-61 kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-API-tutorials" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fa_github kt-btn-icon-side-left"><svg viewBox="0 0 496 512"  fill="currentColor" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg></span><span class="kt-btn-inner-text">Relataly GitHub Repo </span></a></div>



<h4 class="wp-block-heading" id="h-step-1-define-functions-to-interact-with-the-twitter-api">Step #1: Define Functions to Interact with the Twitter API</h4>



<p class="wp-block-paragraph">We begin by defining functions to interact with the Twitter API. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">import requests 
import json 
import pandas as pd

# imports the twitter_secrets python file in which we store the twitter API keys
from twitter_secrets import twitter_secrets as ts

# a function that provides a bearer token to the API
def create_headers(bearer_token):
    headers = {&quot;Authorization&quot;: &quot;Bearer {}&quot;.format(bearer_token)}
    return headers

# this function defines the rules on what tweets to pull    
def set_rules(headers, delete, bearer_token, rules):
    payload = {&quot;add&quot;: rules}
    response = requests.post(
        &quot;https://api.twitter.com/2/tweets/search/stream/rules&quot;,
        headers=headers,
        json=payload,
    )
    if response.status_code != 201:
        raise Exception(
            &quot;Cannot add rules (HTTP {}): {}&quot;.format(response.status_code, response.text)
        )
    print(json.dumps(response.json()))
    
# this function requests the current rules in place
def get_rules(headers, bearer_token):
    response = requests.get(
        &quot;https://api.twitter.com/2/tweets/search/stream/rules&quot;, headers=headers
    )
    if response.status_code != 200:
        raise Exception(
            &quot;Cannot get rules (HTTP {}): {}&quot;.format(response.status_code, response.text)
        )
    print(json.dumps(response.json()))
    return response.json()

# this function resets all rules
def delete_all_rules(headers, bearer_token, rules):
    if rules is None or &quot;data&quot; not in rules:
        return None

    ids = list(map(lambda rule: rule[&quot;id&quot;], rules[&quot;data&quot;]))
    payload = {&quot;delete&quot;: {&quot;ids&quot;: ids}}
    response = requests.post(
        &quot;https://api.twitter.com/2/tweets/search/stream/rules&quot;,
        headers=headers,
        json=payload
    )
    if response.status_code != 200:
        raise Exception(
            &quot;Cannot delete rules (HTTP {}): {}&quot;.format(
                response.status_code, response.text
            )
        )
    print(json.dumps(response.json()))

# this function starts the stream
def get_stream(headers, set, bearer_token, expansions, fields, save_to_disk, save_path):
    data = []
    response = requests.get(
        &quot;https://api.twitter.com/2/tweets/search/stream&quot; + expansions + fields, headers=headers, stream=True,
    )
    print(response.status_code)
    if response.status_code != 200:
        raise Exception(
            &quot;Cannot get stream (HTTP {}): {}&quot;.format(
                response.status_code, response.text
            )
        )
    i = 0
    for response_line in response.iter_lines():
        i += 1
        if i == max_results:
            break
        else:
            json_response = json.loads(response_line)
            #print(json.dumps(json_response, indent=4, sort_keys=True))
            try:
                save_tweets(json_response)
                if save_to_disk == True:
                    save_media_to_disk(json_response, save_path)
            except (json.JSONDecodeError, KeyError) as err:
                # In case the JSON fails to decode, we skip this tweet
                print(f&quot;{i}/{max_results}: ERROR: encountered a problem with a line of data... \n&quot;)
                continue

# this function saves a tweet to the SQLite DB                
def save_tweets(tweet):
    print(json.dumps(tweet, indent=4, sort_keys=True))
    data = tweet['data']
    public_metrics = data['public_metrics']
    tweet_list.append([data['id'], data['author_id'], data['created_at'], data['text'], public_metrics['like_count']])
</pre></div>



<h4 class="wp-block-heading" id="h-step-2-subscribe-to-the-tweet-streaming-service">Step #2: Subscribe to the Tweet Streaming Service</h4>



<p class="wp-block-paragraph">Next, we subscribe to a stream of tweets. Once you have subscribed to the stream, you can process the received tweets as needed, such as by filtering or storing them for further analysis.</p>



<p class="wp-block-paragraph">In this example, we will simply save the data to disk and append it to a text file. Tweets may have media files attached. If you also like to save these images to disk, you can set the save_media_to_disk variable to &#8220;True.&#8221;</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># the max number of tweets that will be returned
max_results = 20

# save to disk
save_media_to_disk = False
save_path = &quot;&quot;

# You can adjust the rules if needed
search_rules = [
    {&quot;value&quot;: &quot;dog has:images&quot;, &quot;tag&quot;: &quot;dog pictures&quot;, &quot;lang&quot;: &quot;en&quot;},
    {&quot;value&quot;: &quot;cat has:images -grumpy&quot;, &quot;tag&quot;: &quot;cat pictures&quot;, &quot;lang&quot;: &quot;en&quot;},
]
tweet_fields = &quot;?tweet.fields=attachments,author_id,created_at,public_metrics&quot;
expansions = &quot;&quot;
tweet_list = []


bearer_token = ts.BEARER_TOKEN
headers = create_headers(bearer_token)
rules = get_rules(headers, bearer_token)
delete = delete_all_rules(headers, bearer_token, rules)
set = set_rules(headers, delete, bearer_token, search_rules)
get_stream(headers, set, bearer_token, expansions, tweet_fields, save_media_to_disk, save_path)

df = pd.DataFrame (tweet_list, columns = ['tweetid', 'author_id' , 'created_at', 'text', 'like_count'])
df</pre></div>



<p class="wp-block-paragraph"></p>



<h3 class="wp-block-heading" id="h-example-b-streaming-images-from-twitter-to-disk">Example B: Streaming Images from Twitter to Disk</h3>



<p class="wp-block-paragraph">The second use case is streaming image data from Twitter. Twitter images are useful in various machine learning use cases, e.g., training models for image recognition and classification. </p>



<p class="wp-block-paragraph">To be able to use the images later, we save them directly to our local drive. To do this, we reuse several functions from the first use case. We add some functions for creating the folder structure in which we then store the images. You can also find the code for this example on Github. The code is available on the GitHub repository.</p>



<div class="wp-block-kadence-advancedbtn kb-buttons-wrap kb-btns_1c9a6f-ad"><a class="kb-button kt-button button kb-btn_668636-e5 kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-API-tutorials/blob/main/111B%20Pulling%20Images%20via%20the%20Twitter%20API%20v2.0.ipynb" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fe_eye kt-btn-icon-side-left"><svg viewBox="0 0 24 24"  fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg></span><span class="kt-btn-inner-text">View on GitHub </span></a>

<a class="kb-button kt-button button kb-btn_e5363e-2d kt-btn-size-standard kt-btn-width-type-full kb-btn-global-inherit kt-btn-has-text-true kt-btn-has-svg-true wp-block-button__link wp-block-kadence-singlebtn" href="https://github.com/flo7up/relataly-public-python-API-tutorials" target="_blank" rel="noreferrer noopener"><span class="kb-svg-icon-wrap kb-svg-icon-fa_github kt-btn-icon-side-left"><svg viewBox="0 0 496 512"  fill="currentColor" xmlns="http://www.w3.org/2000/svg"  aria-hidden="true"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg></span><span class="kt-btn-inner-text">Relataly GitHub Repo </span></a></div>



<h4 class="wp-block-heading" id="h-step-1-define-functions-to-interact-with-the-twitter-api-1">Step #1: Define Functions to Interact with the Twitter API</h4>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}">import requests 
import json 
import pandas as pd
import urllib
import os
from os import path
from datetime import datetime as dt

# imports the twitter_secrets python file in which we store the twitter API keys
from twitter_secrets import twitter_secrets as ts

def create_headers(bearer_token):
    headers = {&quot;Authorization&quot;: &quot;Bearer {}&quot;.format(bearer_token)}
    return headers
        
def set_rules(headers, delete, bearer_token, rules):
    payload = {&quot;add&quot;: rules}
    response = requests.post(
        &quot;https://api.twitter.com/2/tweets/search/stream/rules&quot;,
        headers=headers,
        json=payload,
    )
    if response.status_code != 201:
        raise Exception(
            &quot;Cannot add rules (HTTP {}): {}&quot;.format(response.status_code, response.text)
        )
    print(json.dumps(response.json()))
    
def get_rules(headers, bearer_token):
    response = requests.get(
        &quot;https://api.twitter.com/2/tweets/search/stream/rules&quot;, headers=headers
    )
    if response.status_code != 200:
        raise Exception(
            &quot;Cannot get rules (HTTP {}): {}&quot;.format(response.status_code, response.text)
        )
    print(json.dumps(response.json()))
    return response.json()

def delete_all_rules(headers, bearer_token, rules):
    if rules is None or &quot;data&quot; not in rules:
        return None

    ids = list(map(lambda rule: rule[&quot;id&quot;], rules[&quot;data&quot;]))
    payload = {&quot;delete&quot;: {&quot;ids&quot;: ids}}
    response = requests.post(
        &quot;https://api.twitter.com/2/tweets/search/stream/rules&quot;,
        headers=headers,
        json=payload
    )
    if response.status_code != 200:
        raise Exception(
            &quot;Cannot delete rules (HTTP {}): {}&quot;.format(
                response.status_code, response.text
            )
        )
    print(json.dumps(response.json()))

def get_stream(headers, set, bearer_token, expansions, fields, save_to_disk, save_path):
    data = []
    response = requests.get(
        &quot;https://api.twitter.com/2/tweets/search/stream&quot; + expansions + fields, headers=headers, stream=True,
    )
    print(response.status_code)
    if response.status_code != 200:
        raise Exception(
            &quot;Cannot get stream (HTTP {}): {}&quot;.format(
                response.status_code, response.text
            )
        )
    i = 0
    for response_line in response.iter_lines():
        i += 1
        if i == max_results:
            break
        else:
            json_response = json.loads(response_line)
            #print(json.dumps(json_response, indent=4, sort_keys=True))
            try:
                save_tweets(json_response)
                if save_to_disk == True:
                    save_media_to_disk(json_response, save_path)
            except (json.JSONDecodeError, KeyError) as err:
                # In case the JSON fails to decode, we skip this tweet
                print(f&quot;{i}/{max_results}: ERROR: encountered a problem with a line of data... \n&quot;)
                continue
                
def save_tweets(tweet):
    #print(json.dumps(tweet, indent=4, sort_keys=True))
    data = tweet['data']
    includes = tweet['includes']
    media = includes['media']
    for line in media:
        tweet_list.append([data['id'], line['url']])  
        
def save_media_to_disk(tweet, save_path):
    data = tweet['data']
    #print(json.dumps(data, indent=4, sort_keys=True))
    includes = tweet['includes']
    media = includes['media']
    for line in media:
        media_url = line['url']
        media_key = line['media_key']
        pic = urllib.request.urlopen(media_url)
        file_path = save_path + &quot;/&quot; + media_key + &quot;.jpg&quot;
        try:
            with open(file_path, 'wb') as localFile:
                localFile.write(pic.read())
            tweet_list.append(media_key, media_url)
        except Exception as e:
            print('exception when saving media url ' + media_url + ' to path: ' + file_path)
            if path.exists(file_path):
                print(&quot;path exists&quot;)
    
def createDir(save_path):
    try:
        os.makedirs(save_path)
    except OSError:
        print (&quot;Creation of the directory %s failed&quot; % save_path)
        if path.exists(savepath):
            print(&quot;file already exists&quot;)
    else:
        print (&quot;Successfully created the directory %s &quot; % save_path)</pre></div>



<h4 class="wp-block-heading" id="h-step-2-define-the-folder-structure-to-store-the-images">Step #2: Define the Folder Structure to Store the Images</h4>



<p class="wp-block-paragraph">We want to store images contained in tweets on disk. To find these images again afterward, we create a new directory for each run. </p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># save to disk
save_to_disk = True
 
if save_to_disk == True: 
    # detect the current working directory and print it
    base_path = os.getcwd()
    print (&quot;The current working directory is %s&quot; % base_path)
    img_dir = '/twitter/downloaded_media/'
    # the write path in which the data will be stored. If it does not yet exist, it will be created
    now = dt.now()
    dt_string = now.strftime(&quot;%d%m%Y-%H%M%S&quot;)# ddmmYY-HMS
    save_path = base_path + img_dir + dt_string
    createDir(save_path)</pre></div>



<h4 class="wp-block-heading" id="h-step-3-subscribe-to-the-tweet-streaming-service">Step #3: Subscribe to the Tweet Streaming Service</h4>



<p class="wp-block-paragraph">Finally, we call the Twitter API and subscribe to the Streaming Service. We store the tweet id and the preview image URL in a DataFrame (df).</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:false,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text/x-python&quot;,&quot;theme&quot;:&quot;monokai&quot;,&quot;lineNumbers&quot;:true,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}"># the max number of tweets that will be returned
max_results = 10

# You can adjust the rules if needed
search_rules = [
    {&quot;value&quot;: &quot;dog has:images&quot;, &quot;tag&quot;: &quot;dog pictures&quot;, &quot;lang&quot;: &quot;en&quot;},
]

media_fields = &quot;&amp;media.fields=duration_ms,height,media_key,preview_image_url,public_metrics,type,url,width&quot;
expansions = &quot;?expansions=attachments.media_keys&quot;
tweet_list = []

bearer_token = ts.BEARER_TOKEN
headers = create_headers(bearer_token)
rules = get_rules(headers, bearer_token)
delete = delete_all_rules(headers, bearer_token, rules)
set = set_rules(headers, delete, bearer_token, search_rules)
get_stream(headers, set, bearer_token, expansions, media_fields, save_to_disk, save_path)

df = pd.DataFrame (tweet_list, columns = ['tweetid', 'preview_image_url'])
df</pre></div>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p class="wp-block-paragraph">In this tutorial, you learned how to stream and process Twitter data in near real-time using the Twitter API v2 with two use cases. The first use case has shown requesting tweet text and how to store it in a DataFrame. In the second case, we have streamed images and saved them to a local directory. There are many more ways to interact with the Twitter API, but it&#8217;s already possible to implement some exciting projects based on these two cases. </p>



<p class="wp-block-paragraph">If you liked this post, leave a comment. And if you want to learn more about using the Twitter API with Python, consider checking out my other articles:</p>



<ul class="wp-block-list">
<li><a href="https://www.relataly.com/posting-tweets-on-twitter-using-python-and-tweepy/3925/" target="_blank" rel="noreferrer noopener">Posting Tweets on Twitter via Tweepy in Python</a></li>



<li><a href="https://www.relataly.com/building-a-twitter-bot-for-trading-signals-using-python/3974/" target="_blank" rel="noreferrer noopener">Building a Twitter Bot for Trading Signals in Python</a></li>
</ul>



<h2 class="wp-block-heading" id="h-sources-and-further-reading">Sources and Further Reading</h2>



<ul class="wp-block-list">
<li><a href="https://developer.twitter.com/en/docs/twitter-api" target="_blank" rel="noreferrer noopener">https://developer.twitter.com/en/docs/twitter-api </a>A part of the presented Python code stems from the Twitter API documentation and has been modified to fit the purpose of this article.</li>
</ul>
<p>The post <a href="https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/">Streaming Tweets and Images via the Twitter API in Python</a> appeared first on <a href="https://www.relataly.com">relataly.com</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.relataly.com/accessing-twitter-data-via-the-twitter-rest-api/1976/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1976</post-id>	</item>
	</channel>
</rss>
