<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE article  PUBLIC "-//NLM//DTD Journal Publishing DTD v3.0 20080202//EN" "http://dtd.nlm.nih.gov/publishing/3.0/journalpublishing3.dtd"><article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="3.0" xml:lang="en" article-type="research article"><front><journal-meta><journal-id journal-id-type="publisher-id">JCC</journal-id><journal-title-group><journal-title>Journal of Computer and Communications</journal-title></journal-title-group><issn pub-type="epub">2327-5219</issn><publisher><publisher-name>Scientific Research Publishing</publisher-name></publisher></journal-meta><article-meta><article-id pub-id-type="doi">10.4236/jcc.2023.112012</article-id><article-id pub-id-type="publisher-id">JCC-123470</article-id><article-categories><subj-group subj-group-type="heading"><subject>Articles</subject></subj-group><subj-group subj-group-type="Discipline-v2"><subject>Computer Science&amp;Communications</subject></subj-group></article-categories><title-group><article-title>
 
 
  GatherTweet: A Python Package for Collecting Social Media Data on Online Events
 
</article-title></title-group><contrib-group><contrib contrib-type="author" xlink:type="simple"><name name-style="western"><surname>Claudia</surname><given-names>Kann</given-names></name><xref ref-type="aff" rid="aff1"><sup>1</sup></xref></contrib><contrib contrib-type="author" xlink:type="simple"><name name-style="western"><surname>Sarah</surname><given-names>Hashash</given-names></name><xref ref-type="aff" rid="aff1"><sup>1</sup></xref></contrib><contrib contrib-type="author" xlink:type="simple"><name name-style="western"><surname>Zachary</surname><given-names>Steinert-Threlkeld</given-names></name><xref ref-type="aff" rid="aff2"><sup>2</sup></xref></contrib><contrib contrib-type="author" xlink:type="simple"><name name-style="western"><surname>R.</surname><given-names>Michael Alvarez</given-names></name><xref ref-type="aff" rid="aff1"><sup>1</sup></xref><xref ref-type="corresp" rid="cor1"><sup>*</sup></xref></contrib></contrib-group><aff id="aff1"><addr-line>Department of Humanities and Social Sciences, California Institute of Technology, Pasadena, USA</addr-line></aff><aff id="aff2"><addr-line>Luskin School of Public Affairs, University of California Los Angeles, Los Angeles, USA</addr-line></aff><pub-date pub-type="epub"><day>15</day><month>02</month><year>2023</year></pub-date><volume>11</volume><issue>02</issue><fpage>172</fpage><lpage>193</lpage><history><date date-type="received"><day>7,</day>	<month>December</month>	<year>2022</year></date><date date-type="rev-recd"><day>25,</day>	<month>February</month>	<year>2023</year>	</date><date date-type="accepted"><day>28,</day>	<month>February</month>	<year>2023</year></date></history><permissions><copyright-statement>&#169; Copyright  2014 by authors and Scientific Research Publishing Inc. </copyright-statement><copyright-year>2014</copyright-year><license><license-p>This work is licensed under the Creative Commons Attribution International License (CC BY). http://creativecommons.org/licenses/by/4.0/</license-p></license></permissions><abstract><p>
 
 
  Social media plays a crucial role in the organization of massive social movements. However, the sheer quantity of data generated by the events as well as the data collection restrictions that researchers encounter, leads to a series of challenges for researchers who want to analyze dynamic public discourse and opinion in response to and in the creation of world events. In this paper we present gatherTweet, a Python package that helps researchers efficiently collect social media data for events that are composed of many decentralized actions (across both space and time). The package is useful for studies that require analysis of the organizational or baseline messaging before an action, the action itself, and the effects of the action on subsequent public discourse. By capturing these aspects of world events gatherTweet enables the study of events and actions like protests, natural disasters, and elections.
 
</p></abstract><kwd-group><kwd>Data Science</kwd><kwd> Movements</kwd><kwd> Social Media Data</kwd><kwd> Twitter</kwd><kwd> Network Science</kwd><kwd> Data Mining</kwd><kwd> Python</kwd></kwd-group></article-meta></front><body><sec id="s1"><title>1. Introduction</title><p>The spread of social media has transformed the world in recent years. Individuals are now able to easily connect to others who are thousands of miles away, creating online enclaves separated from their physical location. While this interconnectedness creates online communities based on shared discourse, many events such as protests, natural disasters, and elections maintain clear geographic foci. Moreover, these geographic foci are dynamic: a protest movement spreads, a hurricane travels, and presidential primaries occur across the country. This paper introduces the package gatherTweet to follow the temporal and geographic progression of offline events made up of discrete activities (a particular protest march, cities the hurricane hits, or election days). Many individuals still use their social media to report on, publicize and organize the offline events they participate in. Thus gatherTweet provides efficient data collection to determine individuals’ broader event-related online community as well as the subset of those in their geographic vicinity. These data enable researchers to gain insight into the evolution of both the discourse network structure and content as an event progresses.</p><p>The package gatherTweet addresses a series of challenges facing researchers collecting social media data. Every collection effort must heed rate limits, manage storage space, and make choices about how to identify relevant users and conversations. The implementation of these choices is time consuming and requires advanced programming knowledge. This package circumvents many of these challenges, by enabling the user to:</p><p>1) Create data structures that represent events that are geographically and temporally dispersed. Specifically, gatherTweet creates codex “TwitterEvent” and codex “TwitterActivity” objects which can be populated manually, through importing a specialized .csv, or by reading existing directory structures.</p><p>2) Identify individuals<sup>1</sup> on Twitter who participated physically in event activities.</p><p>3) Identify individuals who echoed the sentiments of and influenced individuals around the event.</p><p>4) Analyze the Twitter presence of these groups of individuals over time.</p><p>The rest of the paper proceeds as follows. First, we present a brief literature, with a focus on how our approach differs from existing packages and approaches. The general use case of gatherTweet is then discussed in conjunction with the methodology it employs. This is followed with an illustrative example using gatherTweet to track the evolution of the Black Lives Matter discourse in three separate cities during the summer of 2020. The use of Twitter as a platform is then discussed, in terms of the limitations it imposes, how gatherTweet circumvents them, and the potential to use similar methods on different social media applications. This is followed by suggestions of ways in which gatherTweet could be deployed and an explanation of the contribution gatherTweet makes to the overall Twitter-related software suite in Python.</p></sec><sec id="s2"><title>2. Literature Review</title><p>Social media data serve as the foundation for many studies of public discourse because they provide researchers with an inexpensive, immediate, and accessible way to gather large swaths of information. They have proved especially fertile for studying the interaction of offline and online activity [<xref ref-type="bibr" rid="scirp.123470-ref1">1</xref>] [<xref ref-type="bibr" rid="scirp.123470-ref2">2</xref>] [<xref ref-type="bibr" rid="scirp.123470-ref3">3</xref>] [<xref ref-type="bibr" rid="scirp.123470-ref4">4</xref>] . Yet, projects’ data collection methods are usually tailored to their precise event, forcing subsequent researchers to spend effort building the same tool instead of analyzing data and writing. Few of these papers present user-friendly packages or tools to enable the replication of their analysis methods for applications other than the particular one in the study. Packages that do exist, mostly Twitter API wrappers, tend to be extremely versatile. This versatility, however, leads to an increased required programming knowledge to take advantage of them. gatherTweet straddles the space between Twitter API wrappers and individual use case code.</p><p>The package develops a general methodology and implements that methodology in the package. Previous work in this area has heavily emphasized methods which can be used to inform data collection from Twitter. These include building keyword or hashtag searching pipelines [<xref ref-type="bibr" rid="scirp.123470-ref5">5</xref>] [<xref ref-type="bibr" rid="scirp.123470-ref6">6</xref>] or approaches using keyword expansion [<xref ref-type="bibr" rid="scirp.123470-ref7">7</xref>] [<xref ref-type="bibr" rid="scirp.123470-ref8">8</xref>] . Other social media data collection efforts prioritize the streamlining the data collection process and storage [<xref ref-type="bibr" rid="scirp.123470-ref9">9</xref>] [<xref ref-type="bibr" rid="scirp.123470-ref10">10</xref>] . In general, these methods have not been implemented in easy-to-use packages and researchers who are not comfortable with complex programming may be unable to take advantage of the knowledge shared. The methodology presented in gatherTweet uses geographic information as a tool to pinpoint relevant actors as well as reduce the quantity of data collected for movements that have prolific online discussions. Thus, gatherTweet implements a generalizable methodology that takes into account geographic information, filters the data to a tractable size, and is easy to use.</p><p>There are numerous Python packages such as tweepy [<xref ref-type="bibr" rid="scirp.123470-ref11">11</xref>] , twitterAPI [<xref ref-type="bibr" rid="scirp.123470-ref12">12</xref>] , and python-twitter [<xref ref-type="bibr" rid="scirp.123470-ref13">13</xref>] , all of which provide helpful wrappers for the Twitter API. These packages are versatile and have been used widely in other studies; in fact, gatherTweet is an implementation using codex TwitterAPI. However, their implementation is difficult for many users because each requires detailed knowledge of Python and the Twitter APIs. We have designed gatherTweet to be easy-to-use for a wider range of researchers, and have implemented it as a data collection method that has broad applicability in social media analysis.</p></sec><sec id="s3"><title>3. Method</title><p>While various steps of this methodology can be done independently, both using gatherTweet as well as replicated for other social media platforms, in this paper we assume that the user will be implementing the package using all of its capabilities. As a broad overview, gatherTweet first identifies the most central and active participants in each activity within the event (users who are part of the core). This is accomplished by identifying individuals who are both discussing the event online and whose geo-location suggests their involvement in the physical activity. A directed one-step crawl is then implemented to find users who retweet the core. These users are labelled echos as they propagate the online content of the core. In addition, the users whom the core retweets are found in a similar manner. These users, influences, create content that the core disperses.</p><p>These three groups of individuals make up the discourse network. In general, the discourse network does not invite the use of typical network analysis tools, as the connections between echos and influences are unknown. However, there are studies that can be done more generally on the discourse network’s structure. For example, structural knowledge can answer research questions like whether individuals participate in multiple activities, if their roles (core, echo, or influence) are consistent over activities, and whether individuals associated with different activities have similar tweeting behaviors. The content of conversation could also change across an event’s activities [<xref ref-type="bibr" rid="scirp.123470-ref14">14</xref>] [<xref ref-type="bibr" rid="scirp.123470-ref15">15</xref>] . Following the initial discourse network collection, gatherTweet can access the full timeline of individuals who are part of the activity. This creates a panel study for each individual, it is similar to each of them filling out multiple surveys over the period, so the researcher can search for individual level patterns. Individuals’ tweet history can help answer questions about how they act over time (previous to, during, and following the activity they are associated with) and whether individuals participate in multiple offline activities, for example if individuals participate in multiple protests, are impacted by weather events at multiple stages or vote in multiple election [<xref ref-type="bibr" rid="scirp.123470-ref16">16</xref>] [<xref ref-type="bibr" rid="scirp.123470-ref17">17</xref>] .</p><p>The full methodology can be seen in <xref ref-type="fig" rid="fig1">Figure 1</xref>. During preliminary event specification, the researcher determines the activities of an event. The next step, individual level identification, has three components, one for each type of individual. First, individuals participating in the event activities both online and offline</p><p>are identified. These individuals are the core for each event activity. An individual could belong to the core of multiple activities within an event, however these core groups are kept separate by activity. Such users are recorded multiple times, with each instance considered a unique user. In the second component of individual level identification, individuals who members of the core retweet are found and labeled as influences, because they likely influence the views and tweets of the core. In the third component, a list of users who retweet the core is created, and these users are labeled echos since they echo the tweets of the core. These three groups make up the discourse network of Twitter users associated with each event. Finally, in timeline tweet collection, the full timeline is collected for all three types of individuals. The researcher must specify a start time and end time for the event as a whole, the period for which the timelines will be collected.</p><p>The start time should precede the start of the actual event and the end time come after the event is over in order to include pre- and post-event information as a baseline. Researchers can also add distinct timeline spans for each activity. This may be useful in the case when the activities cover a large time span. If an individual shows up in multiple activities or plays multiple roles within an activity, each instance is viewed as an independent observation and the timeline is collected for each situation. This duplication ensures that individuals are counted in every role and activity in which they appear. These panel data provide researchers a complete understanding of each individual’s Twitter discourse surrounding an activity or the event.</p><p>In the remainder of this section the details of applying the methodology using gatherTweet will be covered. For each of the functions used, the full specification of them can be found in the supplemental materials as well as in the github repository.</p><sec id="s3_1"><title>3.1. Preliminary Event Specification</title><p>The current version of gatherTweet uses Twitter API v2. To access the API users must have a developer account<sup>2</sup>. The specific limitations referenced in this paper assume that researchers have Academic Researcher level access<sup>3</sup>. The application and acceptance process can take a few days.</p><p>To use gatherTweet, an empty event object must first be created; this object is then filled with the relevant information and activity objects. This event object is instantiated as:</p><p>import gatherTweet as tw</p><p>event = tw.TwitterEvent (name, base_directory = &quot; &quot;, separator = “CityTown”)</p><p>This code creates a codex TwitterEvent object which can then be populated. The object has a name, a path, and a grouping factor which defaults to the “CityTown” in which the activity takes place. The details regarding the inputs of these functions are listed in <xref ref-type="table" rid="table1">Table 1</xref>. Once created, the codex TwitterEvent object is ready to be populated by a series of codex TwitterActivity objects as well as event specific data like the keywords and the event period. Each of the three processes used to populate the event with activities are outlined in the next section: from an Excel sheet, manually in Python, or from an existing data structure. Each of the processes requires the same researcher-defined information. The difference between the processes is how the researcher puts that information in the object—the final result is the same.</p><p>The researcher must compose an event consisting of discrete activities. For each activity, the researcher must specify a time-frame and geographic boundaries for where it occurred. The geographic boundaries are a bounding box consisting of North and South latitudes and East and West longitudes. They must then determine a list of keywords pertinent to the discourse surrounding the event. To construct this list, it is best to look at Twitter itself as well as other studies that analyze the frequency of usage of certain key terms and hashtags. Keywords are not only restricted to hashtags but also include words and phrases used in the tweets. This information is then added to the codex TwitterEvent object in one of the three processes that follows.</p><sec id="s3_1_1"><title>3.1.1. From Excel</title><p>The first process discussed is using an Excel document to populate the event. This approach is the easiest, particularly for those with less experience in Python. A template Excel sheet is provided in the gatherTweet repository on GitHub. The researcher must add the information provided in <xref ref-type="table" rid="table2">Table 2</xref> to the template. The bolded arguments are optional. Alternatively, the researcher can create their own Excel sheet where the italisized values are the sheet names and the Input column represents the columns of the sheet. Once the sheet is completed, it should be saved in the codex base_directory specified in the event. It can then be populated through the function:</p><p>event.upload_from_excel(path = “event_template.xlsx”)</p><p>The details of this function can be found in <xref ref-type="table" rid="table3">Table 3</xref>.</p><p>Once populating the Excel sheet is complete, the user can begin using the codex TwitterEvent object codex event to collect data.</p></sec><sec id="s3_1_2"><title>3.1.2. From Python</title><p>The researcher can also input activity information directly in Python. In order to do this, each individual activity must be created. Each codex TwitterActivity object is created as:</p><p>activity = tw.TwitterActivity(ID, starting_date, ending_date, CityTown,</p><p>StateTerritory, Date, BestGuess)</p><p>If, for a given activity, the timeline time span is different than that for the event in general, this independent timing can be added using:</p><p>activity.add_timing(period_start, period_end). Details for the function can be seen in <xref ref-type="table" rid="table4">Table 4</xref>.</p><p>This activity is then added to the event through the function (<xref ref-type="table" rid="table5">Table 5</xref>).</p><p>event.add_activity(activity)</p><table-wrap id="table1" ><label><xref ref-type="table" rid="table1">Table 1</xref></label><caption><title> TwitterEvent inputs</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Name</th><th align="center" valign="middle" >Name for the event.</th></tr></thead><tr><td align="center" valign="middle" >base_directory</td><td align="center" valign="middle" >Path to where all of the data will be stored.</td></tr><tr><td align="center" valign="middle" >separator</td><td align="center" valign="middle" >Describes how the activities are split in the data saving structure, it can be any of the activity objects. For geographical differences “CityTown” makes the most sense.</td></tr></tbody></table></table-wrap><table-wrap id="table2" ><label><xref ref-type="table" rid="table2">Table 2</xref></label><caption><title> Pages and fields to be filled out in event_template.xlsx to import Event from Excel. Bold arguments are optional</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Input</th><th align="center" valign="middle" >Description</th></tr></thead><tr><td align="center" valign="middle" >Activities</td><td align="center" valign="middle" ></td></tr><tr><td align="center" valign="middle" >ID</td><td align="center" valign="middle" >Unique identification string.</td></tr><tr><td align="center" valign="middle" >starting_date</td><td align="center" valign="middle" >Beginning date of the activity within the event in the format dd mm yyyy hh:mm:ss.</td></tr><tr><td align="center" valign="middle" >ending_date</td><td align="center" valign="middle" >Ending date of the activity within the event in the format. dd mm yyyy hh:mm:ss.</td></tr><tr><td align="center" valign="middle" >CityTown</td><td align="center" valign="middle" >City or town where you want to search for individuals in the core.</td></tr><tr><td align="center" valign="middle" >StateTerritory</td><td align="center" valign="middle" >State or territory where you want to search for individuals in the core.</td></tr><tr><td align="center" valign="middle" >Date</td><td align="center" valign="middle" >Date of the activity in dd mm yyyy format.</td></tr><tr><td align="center" valign="middle" >BestGuess</td><td align="center" valign="middle" >Best guess of the size of the activity, if unknown, write 0.</td></tr><tr><td align="center" valign="middle" >period_start</td><td align="center" valign="middle" >Start of the event (when you want the timeline gathering to start) if different from the rest of the activities in the event. In the format dd mm yyyy hh:mm:ss.</td></tr><tr><td align="center" valign="middle" >period_end</td><td align="center" valign="middle" >End of the event (when you want the timeline gathering to end) if different from the rest of the activities in the event. In the format dd mm yyyy hh:mm:ss.</td></tr><tr><td align="center" valign="middle" >Keywords</td><td align="center" valign="middle" ></td></tr><tr><td align="center" valign="middle" >Keywords</td><td align="center" valign="middle" >List of keywords you want to use to identify the core. Can be written individually or in Twitter accepted format. For example, it is equivalent to have: George Floyd George Floyd vs. (GeorgeFloyd OR (George Floyd)).</td></tr><tr><td align="center" valign="middle" >Time span</td><td align="center" valign="middle" ></td></tr><tr><td align="center" valign="middle" >Start time</td><td align="center" valign="middle" >Beginning of the timeline gathering period in dd mm yyyy hh:mm:ss format.</td></tr><tr><td align="center" valign="middle" >End time</td><td align="center" valign="middle" >End of the timeline gathering period in dd mm yyyy hh:mm:ss format.</td></tr><tr><td align="center" valign="middle" >Keys</td><td align="center" valign="middle" ></td></tr><tr><td align="center" valign="middle" >Key</td><td align="center" valign="middle" >Twitter keys, make sure not to share these with other people.</td></tr><tr><td align="center" valign="middle" >Secret</td><td align="center" valign="middle" >Twitter secret keys, make sure not to share these with other people.</td></tr><tr><td align="center" valign="middle" >Location</td><td align="center" valign="middle" ></td></tr><tr><td align="center" valign="middle" >CityTown</td><td align="center" valign="middle" >The city or town with which the coordinates are associated.</td></tr><tr><td align="center" valign="middle" >StateTerritory</td><td align="center" valign="middle" >The state or territory abbreviation with which the coordinates are associated.</td></tr><tr><td align="center" valign="middle" >Coordinates</td><td align="center" valign="middle" >West longitude, south latitude, east longitude, north latitude to find bounding box for each location, a row needs to be added for each unique CityTown-StateTerritory pair found in the activities table.</td></tr></tbody></table></table-wrap><table-wrap id="table3" ><label><xref ref-type="table" rid="table3">Table 3</xref></label><caption><title> Upload_from_excel inputs</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Path</th><th align="center" valign="middle" >The path to the Excel file. If the path given is not an .xlsx file it will replace it with base_directory + “event_template.xlsx”. If the path is “event_template.xlsx”, it also assumes its in the base_directory.</th></tr></thead></tbody></table></table-wrap><table-wrap id="table4" ><label><xref ref-type="table" rid="table4">Table 4</xref></label><caption><title> TwitterActivity inputs</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >ID</th><th align="center" valign="middle" >Unique identification string.</th></tr></thead><tr><td align="center" valign="middle" >starting_date</td><td align="center" valign="middle" >Beginning date of the activity within the event in the format dd mm yyyy hh:mm:ss.</td></tr><tr><td align="center" valign="middle" >ending_date</td><td align="center" valign="middle" >Ending date of the activity within the event in the format dd mm yyyy hh:mm:ss.</td></tr><tr><td align="center" valign="middle" >CityTown</td><td align="center" valign="middle" >City or town where activity occurs. This value does not correspond to the Twitter API, but is used for the researcher to link with instantiation of the bounding box, and thus simply must be consistent throughout the use.</td></tr><tr><td align="center" valign="middle" >StateTerritory</td><td align="center" valign="middle" >State or territory where activity occurs. This value does not correspond to the Twitter API but serves as a method of grouping activities for the researcher.</td></tr><tr><td align="center" valign="middle" >Date</td><td align="center" valign="middle" >Date of the activity in any format—this is a string for the user.</td></tr><tr><td align="center" valign="middle" >BestGuess</td><td align="center" valign="middle" >Best guess of the size of the activity. If unknown, write 0.</td></tr></tbody></table></table-wrap><table-wrap id="table5" ><label><xref ref-type="table" rid="table5">Table 5</xref></label><caption><title> TwitterActivity.add_timing inputs</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >period_start</th><th align="center" valign="middle" >Start of the event (when the timeline starts) if different from the rest of the activities in the event. In the format dd mm yyyy hh:mm:ss.</th></tr></thead><tr><td align="center" valign="middle" >period_end</td><td align="center" valign="middle" >End of the event (when the timeline ends) if different from the rest of the activities in the event. In the format dd mm yyyy hh:mm:ss.</td></tr></tbody></table></table-wrap><p>To finish creating the event, the researcher’s Twitter keys must be added. In addition the keywords and general location bounding boxes must be included. First, each set of keys must be converted into a codex TwitterKeyPair object.</p><p>key_j = tw.TwitterKeyPair(key, secret). Details for this function can be found in <xref ref-type="table" rid="table6">Table 6</xref>.</p><p>These keys, the keywords, the timing, and the location must then be added to the event object by the researcher through the series of functions listed in <xref ref-type="table" rid="table7">Table 7</xref>. The order in which each of these four items is added does not matter, but all must be provided to create a full codex TwitterEvent object.</p><p>After completing the codex TwitterEvent object, the user must apply a quick check in which gatherTweet both ensures internal consistency and produces an easily readable object that the user can examine. The command is codex protest_ids = event.print_protests() and the output is a dataframe of the activities with the relevant information. The event object is now ready for use.</p></sec><sec id="s3_1_3"><title>3.1.3. From Data Structure</title><p>The TwitterEvent objects populated using the previous two methods are needed to pull the Twitter data associated with each activity. In order to run the checking and analysis functions explained later in the paper a codex TwitterEvent object is still needed. However, a sparser version of the object is sufficient. Once the data are found, the file structure encodes the information necessary to create this sparser version. In this case, building codex TwitterEvent objects from the existing data structure may be simpler. The function codex upload_from_file_structure is used to do this. It loops through the file system, building up the codex TwitterEvent object. Specifically, the application is:</p><p>event.upload_from_file_structure()</p><p>The function has no inputs and assumes that the codex base_directory used in the creation of the event is the same as was originally used and thus is the directory in which the data is stored. Following this command, the codex TwitterEvent object codex event is ready to be used to collect timelines and analyze data.</p></sec></sec><sec id="s3_2"><title>3.2. Individual Level Identification</title><p>Individuals in the event core are identified after the creation of the event object. From there, the echo and influence accounts are found. While on the back end these are similar processes, small differences in the commands sent to the Twitter API result in substantial differences in data collected.</p><table-wrap id="table6" ><label><xref ref-type="table" rid="table6">Table 6</xref></label><caption><title> TwitterKeyPair inputs</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Key</th><th align="center" valign="middle" >Twitter developer key as a string</th></tr></thead><tr><td align="center" valign="middle" >Secret</td><td align="center" valign="middle" >Twitter developer secret key as a string</td></tr></tbody></table></table-wrap><table-wrap id="table7" ><label><xref ref-type="table" rid="table7">Table 7</xref></label><caption><title> Completing event functions and inputs</title></caption><table><tbody><thead><tr><th align="center" valign="middle"  colspan="2"  >event.add_key(key_j)</th></tr></thead><tr><td align="center" valign="middle" >Key</td><td align="center" valign="middle" >Twitter developer key as a string</td></tr><tr><td align="center" valign="middle" >Secret</td><td align="center" valign="middle" >Twitter developer secret key as a string</td></tr><tr><td align="center" valign="middle"  colspan="2"  >event.add_keyWords(words)</td></tr><tr><td align="center" valign="middle" >Words</td><td align="center" valign="middle"  rowspan="5"  >List of keywords to use to identify the core. Can be written individually or in Twitter accepted format. For example, it is equivalent to have: George Floyd GeorgeFloyd vs. (GeorgeFloyd OR (George Floyd))</td></tr><tr><td align="center" valign="middle" ></td></tr><tr><td align="center" valign="middle" ></td></tr><tr><td align="center" valign="middle" ></td></tr><tr><td align="center" valign="middle" ></td></tr><tr><td align="center" valign="middle"  colspan="2"  >event.add_timing(start, end)</td></tr><tr><td align="center" valign="middle" >Start</td><td align="center" valign="middle" >Beginning of the timeline gathering period in dd mm yyyy hh:mm:ss format.</td></tr><tr><td align="center" valign="middle" >End</td><td align="center" valign="middle" >End of the timeline gathering period in dd mm yyyy hh:mm:ss format.</td></tr><tr><td align="center" valign="middle"  colspan="2"  >event.add_location(CityTown, StateTerritory, west, south, east, north)</td></tr><tr><td align="center" valign="middle" >CityTown</td><td align="center" valign="middle" >List of CityTown entries that occur in the activities.</td></tr><tr><td align="center" valign="middle" >StateTerritory</td><td align="center" valign="middle" >List of StateTerritories associate with CityTown list.</td></tr><tr><td align="center" valign="middle" >West</td><td align="center" valign="middle" >List of West longitude for bounding box of CityTowns.</td></tr><tr><td align="center" valign="middle" >South</td><td align="center" valign="middle" >List of South latitude for bounding box of CityTowns.</td></tr><tr><td align="center" valign="middle" >East</td><td align="center" valign="middle" >List of East longitude for bounding box of CityTowns.</td></tr><tr><td align="center" valign="middle" >North</td><td align="center" valign="middle" >List of North latitude for bounding box of CityTowns.</td></tr></tbody></table></table-wrap><p><xref ref-type="fig" rid="fig2">Figure 2</xref> presents a schematic for the core identification for each activity. Beginning with an activity from the codex TwitterEvent object, the keywords, activity timeframe, and location are queried. For each keyword in the keywords object, tweets are found that are published within the bounding box during the timespan with that keyword. The API returns a maximum of 500 tweets per query. In cases when there are more than 500 tweets in the timeline, the code paginates through the API results until all tweets with that keyword are downloaded<sup>4</sup>. At the end of each keyword search, the collected tweets are saved as a JSON file in a folder called “Core” within an activity-specific folder in the specified codex base_directory.</p><p><xref ref-type="fig" rid="fig3">Figure 3</xref> shows that the collection of echo and influence users follows a similar process. A list of the individuals belonging to the core is created. Their tweets are then examined from two days proceeding the start of the activity until two days after. Echos are designated as individuals who retweet any of the tweets during that period, while influences are the original creators of core user’s retweets. The user IDs of these users are then stored in the Echo (Influence) folders within the Activity folder in the base directory as text files names echo (influence)-ids.txt.</p><p>In order to run any tweet or user identification processes using gatherTweet, the researcher uses the codex get_tweets command; <xref ref-type="table" rid="table8">Table 8</xref> shows its arguments. This function has the ability to retrieve the core, echos, and influences user ID numbers as well as each of their timelines. This command, which in its default form is</p><p>event.pull.get_tweets(event, types = [<xref ref-type="bibr" rid="scirp.123470-ref"></xref>], max_results = 500,</p><p>tweets_per_file = 1000, expansions = [“author_id”,</p><p>“in_reply_to_user_id”], tweetfields = [“author_id”,</p><p>“created_at”, “geo”, “entities”, “public_metrics”,</p><p>“text”, “referenced_tweets”]),</p><table-wrap id="table8" ><label><xref ref-type="table" rid="table8">Table 8</xref></label><caption><title> Get_tweets inputs</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Event</th><th align="center" valign="middle" >TwitterEvent object</th></tr></thead><tr><td align="center" valign="middle" >Types</td><td align="center" valign="middle" >a list of the types of Tweets and users you want to collect, options are: [Core, CoreTimeline, Echos, EchosTimeline, Influences, InfluencesTimeline]. If left as an empty list, all will be evaluated. In order to run the Timeline versions, all activities are checked to make sure they have the base version. For Echos and Influences it checks that a core exists. Everything but the Core can restart after being interrupted with minimal redundancy.</td></tr><tr><td align="center" valign="middle" >max_results</td><td align="center" valign="middle" >Number of tweets to attempt to pull in each query, must be an integer between 1 and 500.</td></tr><tr><td align="center" valign="middle" >tweets_per _file</td><td align="center" valign="middle" >Number of tweets to save per file before beginning a new file.</td></tr><tr><td align="center" valign="middle" >Expansions</td><td align="center" valign="middle" >A list of tweetfields the researcher would like more information on, taken from https://developer.twitter.com/en/docs/twitter-api/expansions, options are: author_id, referenced_tweets.id, in_reply_to_user_id, attachments.media_keys, attachments.poll_ids, geo.place_id, entities.mentions.username, referenced_tweets. id.author_id</td></tr><tr><td align="center" valign="middle" >twEetfields</td><td align="center" valign="middle" >A list of values within each tweet to be returned from each call are taken from https://developer.twitter.com/en/docs/twitter-api/data-dictionary/object-model/tweet: id (default), text (default), attachments, author_id, context_annotations, conversation_id, created_at, entities, geo, in_reply_to_user_id, lang, non_public_metrics, organic_metrics, possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets, reply_settings, source, withheld)</td></tr></tbody></table></table-wrap><p>is flexible and customizable. If “codex Core” is not in the codex types input and has not already been pulled for the event, the process stops and issues an error. gatherTweet checks for other dependencies and issues errors as appropriate. Additional examples of such dependencies include finding the echo or influence timeline before having found the echo or influence accounts.</p></sec><sec id="s3_3"><title>3.3. Timeline Tweet Collection</title><p>The timeline tweet collection process is the same for all three groups of individuals. Given a list of Twitter user IDs, all tweets from the users during the event period are accessed. While timeline tweet collection is programmatically simple, it can be the most time intensive part of gatherTweet as it has to collect the largest number of tweets. To do this collection, the function codex event.pull.get_tweets() must be run with codex types = [CoreTimeline, EchosTimeline, InfluencesTimeline]. This function is the same one that identifies individuals who belong to the core, echos, or influences; the difference is in the codex type declaration. Full details can be seen in <xref ref-type="table" rid="table8">Table 8</xref>. If the individuals for each type have not been pulled gatherTweet will notify the researcher with the warning message</p><p>At least one activity does not have a list of “type” and the function will exit.</p></sec></sec><sec id="s4"><title>4. Parsing</title><p>It is useful to provide the researcher a sense of the size of an activity or activities’ data. This can be used as a check as the method is applied to get a sense of the size of the final dataset. The function codex check.number_of_tweets estimates the numbers of tweets in each activity and type, and <xref ref-type="table" rid="table9">Table 9</xref> shows its inputs.</p><p>The package gatherTweet generates a series of JSON files in an informative file structure. The file structure is such that the location of the file clearly informs the researcher of which information is in the JSON file. This structure, however, keeps information separate and therefore requires the user to individually load numerous files into a processor to access the raw data. To aid the researcher in circumventing this process, gatherTweet also includes functions for merging the individual JSON files into a usable and accessible format.</p><p>Two functions, codex read.read_tweets and codex read.read_tweets_basic, combine all of the tweets from an activity into one file within the activity’s codex analysis folder. The functions transform the JSON files into one comma-separated values (.csv) file. The difference between the two functions is in the form which each outputs. The former includes all of the information in the original file, while the later includes only the text, author ID, tweet ID, created at date, and a string indicating which activity the tweet is associated with.</p><p>The information provided in codex read.read_tweets_basic lowers the storage requirements and in many cases provides sufficient data for analysis. For most purposes, this function is the appropriate one for placing the data within activity-specific files. If the researcher wants to further simplify their storage structure and have all of the event data in one location, the functions codex read.wrap_csv and codex read.wrap_csv_basic can be used. These functions further combine the results into a singular file within the codex analysis folder of each group of activities (a directory for each value of the separator variable). The four functions have the same input options (as seen in <xref ref-type="table" rid="table1">Table 1</xref>0) and the original and basic versions can be used interchangeably.</p><table-wrap id="table9" ><label><xref ref-type="table" rid="table9">Table 9</xref></label><caption><title> Check.number_of_tweets inputs</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Activities</th><th align="center" valign="middle" >A list of the activities in which to estimate tweets.</th></tr></thead><tr><td align="center" valign="middle" >Users</td><td align="center" valign="middle" >The types of users to count tweets from, options are [Core, Echo, Influence].</td></tr><tr><td align="center" valign="middle" >base_directory</td><td align="center" valign="middle" >Where to begin searching for the data.</td></tr><tr><td align="center" valign="middle" >Separator</td><td align="center" valign="middle" >Describes how the activities are split in the data saving structure, it can be any of the activity objects. For geographical differences “CityTown” makes the most sense.</td></tr><tr><td align="center" valign="middle" >Timeline</td><td align="center" valign="middle" >Boolean of whether to count tweets in the timeline or not, if not, only the original tweets of the core will be counted.</td></tr></tbody></table></table-wrap><table-wrap id="table10" ><label><xref ref-type="table" rid="table1">Table 1</xref>0</label><caption><title> Read.read_tweets(_basic) and read.wrap_csv(_basic) inputs</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Event</th><th align="center" valign="middle" >The name of the TwitterEvent object.</th></tr></thead><tr><td align="center" valign="middle" >Users</td><td align="center" valign="middle" >A list of the types of Tweets and users you want to aggregate the data for options are any subset of: [Core, CoreTimeline, Echos, EchosTimeline, Influences, InfluencesTimeline].</td></tr></tbody></table></table-wrap></sec><sec id="s5"><title>5. Research Results</title><sec id="s5_1"><title>5.1. 2020 Black Lives Matter Protests</title><p>This section demonstrates usage of gatherTweet to aid in the analysis of Twitter discourse about the Summer 2020 Black Lives Matter (BLM) protests. Between May 26th and August 22nd, 2020, approximately 7750 BLM demonstrations occurred in over 2440 locations in all 50 US states [<xref ref-type="bibr" rid="scirp.123470-ref18">18</xref>] . These protests were some of the most well attended and longest lasting in American history [<xref ref-type="bibr" rid="scirp.123470-ref19">19</xref>] . With the sheer number of individuals and tweets involved in the protests, collecting every tweet that used relevant keywords would overwhelm most systems. By restricting analysis to specific cities, gatherTweet significantly reduces the strain of this collection.</p><sec id="s5_1_1"><title>5.1.1. Preliminary Event Specification</title><p>We first choose which cities and protests to include as well as the event time span. We focus on Los Angeles, Chicago, and Houston—the second through fourth largest cities in the United States—and choose activities (protests) starting immediately after the murder of George Floyd. The timeline collection occurs from the 20th of May 2020 until the 1st of October. This span is 6 days before the first recorded activity until 5 days after the final one. The location, date, estimated size, and overall statistics from the process can be seen in Tables 11-13. The resulting data encompasses 13 activities in Los Angeles, 24 in Chicago and 7 in Houston.</p><table-wrap id="table11" ><label><xref ref-type="table" rid="table1">Table 1</xref>1</label><caption><title> Overview of Data: Los Angeles</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >City</th><th align="center" valign="middle" >Protest Date</th><th align="center" valign="middle" >CCC Estimated Size</th><th align="center" valign="middle" ># Core</th><th align="center" valign="middle" ># Influence</th><th align="center" valign="middle" ># Echo</th><th align="center" valign="middle" >Avg Core Timeline Size</th></tr></thead><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >05-27-2020</td><td align="center" valign="middle" >250</td><td align="center" valign="middle" >351</td><td align="center" valign="middle" >47,506</td><td align="center" valign="middle" >62,978</td><td align="center" valign="middle" >1593</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >05-28-2020</td><td align="center" valign="middle" >750</td><td align="center" valign="middle" >604</td><td align="center" valign="middle" >0</td><td align="center" valign="middle" >184,151</td><td align="center" valign="middle" >1582</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >05-29-2020</td><td align="center" valign="middle" >2000</td><td align="center" valign="middle" >516</td><td align="center" valign="middle" >48,301</td><td align="center" valign="middle" >136,280</td><td align="center" valign="middle" >1286</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >06-06-2020</td><td align="center" valign="middle" >3000</td><td align="center" valign="middle" >325</td><td align="center" valign="middle" >46,197</td><td align="center" valign="middle" >86,181</td><td align="center" valign="middle" >1473</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >06-13-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >326</td><td align="center" valign="middle" >38,583</td><td align="center" valign="middle" >59,360</td><td align="center" valign="middle" >1785</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >06-27-2020</td><td align="center" valign="middle" >100</td><td align="center" valign="middle" >143</td><td align="center" valign="middle" >35,151</td><td align="center" valign="middle" >50,522</td><td align="center" valign="middle" >2396</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >07-14-2020</td><td align="center" valign="middle" >50</td><td align="center" valign="middle" >79</td><td align="center" valign="middle" >7450</td><td align="center" valign="middle" >8977</td><td align="center" valign="middle" >4773</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >07-25-2020</td><td align="center" valign="middle" >150</td><td align="center" valign="middle" >88</td><td align="center" valign="middle" >14,634</td><td align="center" valign="middle" >8735</td><td align="center" valign="middle" >2673</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >07-26-2020</td><td align="center" valign="middle" >500</td><td align="center" valign="middle" >78</td><td align="center" valign="middle" >13,818</td><td align="center" valign="middle" >23,805</td><td align="center" valign="middle" >4499</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >08-24-2020</td><td align="center" valign="middle" >112</td><td align="center" valign="middle" >112</td><td align="center" valign="middle" >12,274</td><td align="center" valign="middle" >13,560</td><td align="center" valign="middle" >4346</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >08-25-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >111</td><td align="center" valign="middle" >29,268</td><td align="center" valign="middle" >26,568</td><td align="center" valign="middle" >3537</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >08-26-2020</td><td align="center" valign="middle" >300</td><td align="center" valign="middle" >156</td><td align="center" valign="middle" >10,734</td><td align="center" valign="middle" >5297</td><td align="center" valign="middle" >4200</td></tr><tr><td align="center" valign="middle" >Los Angeles</td><td align="center" valign="middle" >09-23-2020</td><td align="center" valign="middle" >500</td><td align="center" valign="middle" >196</td><td align="center" valign="middle" >21,585</td><td align="center" valign="middle" >47551</td><td align="center" valign="middle" >4055</td></tr></tbody></table></table-wrap><table-wrap id="table12" ><label><xref ref-type="table" rid="table1">Table 1</xref>2</label><caption><title> Overview of Data: Chicago</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >City</th><th align="center" valign="middle" >Protest Date</th><th align="center" valign="middle" >CCC Estimated Size</th><th align="center" valign="middle" ># Core</th><th align="center" valign="middle" ># Influence</th><th align="center" valign="middle" ># Echo</th><th align="center" valign="middle" >Avg Core Timeline Size</th></tr></thead><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >05-29-2020</td><td align="center" valign="middle" >300</td><td align="center" valign="middle" >13</td><td align="center" valign="middle" >99</td><td align="center" valign="middle" >17</td><td align="center" valign="middle" >2350</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >05-30-2020</td><td align="center" valign="middle" >1750</td><td align="center" valign="middle" >35</td><td align="center" valign="middle" >2639</td><td align="center" valign="middle" >3386</td><td align="center" valign="middle" >1210</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >05-31-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >44</td><td align="center" valign="middle" >2624</td><td align="center" valign="middle" >938</td><td align="center" valign="middle" >395</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-05-2020</td><td align="center" valign="middle" >2000</td><td align="center" valign="middle" >48</td><td align="center" valign="middle" >11,534</td><td align="center" valign="middle" >12,616</td><td align="center" valign="middle" >466</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-06-2020</td><td align="center" valign="middle" >2500</td><td align="center" valign="middle" >69</td><td align="center" valign="middle" >18,611</td><td align="center" valign="middle" >3299</td><td align="center" valign="middle" >476</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-08-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >22</td><td align="center" valign="middle" >2832</td><td align="center" valign="middle" >133</td><td align="center" valign="middle" >535</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-12-2020</td><td align="center" valign="middle" >1400</td><td align="center" valign="middle" >13</td><td align="center" valign="middle" >2348</td><td align="center" valign="middle" >32</td><td align="center" valign="middle" >802</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-13-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >18</td><td align="center" valign="middle" >74</td><td align="center" valign="middle" >6</td><td align="center" valign="middle" >238</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-14-2020</td><td align="center" valign="middle" >2500</td><td align="center" valign="middle" >16</td><td align="center" valign="middle" >2277</td><td align="center" valign="middle" >69</td><td align="center" valign="middle" >520</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-17-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >12</td><td align="center" valign="middle" >13</td><td align="center" valign="middle" >11</td><td align="center" valign="middle" >219</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-19-2020</td><td align="center" valign="middle" >2000</td><td align="center" valign="middle" >28</td><td align="center" valign="middle" >4306</td><td align="center" valign="middle" >999</td><td align="center" valign="middle" >161</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-24-2020</td><td align="center" valign="middle" >500</td><td align="center" valign="middle" >7</td><td align="center" valign="middle" >353</td><td align="center" valign="middle" >47</td><td align="center" valign="middle" >1324</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >06-28-2020</td><td align="center" valign="middle" >2000</td><td align="center" valign="middle" >5</td><td align="center" valign="middle" >11</td><td align="center" valign="middle" >2</td><td align="center" valign="middle" >212</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >07-02-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >9</td><td align="center" valign="middle" >58</td><td align="center" valign="middle" >46</td><td align="center" valign="middle" >409</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >07-17-2020</td><td align="center" valign="middle" >1000</td><td align="center" valign="middle" >9</td><td align="center" valign="middle" >728</td><td align="center" valign="middle" >11</td><td align="center" valign="middle" >545</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >07-20-2020</td><td align="center" valign="middle" >100</td><td align="center" valign="middle" >3</td><td align="center" valign="middle" >162</td><td align="center" valign="middle" >77</td><td align="center" valign="middle" >308</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >07-24-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >3</td><td align="center" valign="middle" >0</td><td align="center" valign="middle" >0</td><td align="center" valign="middle" >113</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >07-25-2020</td><td align="center" valign="middle" >300</td><td align="center" valign="middle" >5</td><td align="center" valign="middle" >652</td><td align="center" valign="middle" >319</td><td align="center" valign="middle" >1709</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >08-08-2020</td><td align="center" valign="middle" >100</td><td align="center" valign="middle" >3</td><td align="center" valign="middle" >1</td><td align="center" valign="middle" >3</td><td align="center" valign="middle" >267</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >08-18-2020</td><td align="center" valign="middle" >135</td><td align="center" valign="middle" >3</td><td align="center" valign="middle" >0</td><td align="center" valign="middle" >2</td><td align="center" valign="middle" >174</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >08-29-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >5</td><td align="center" valign="middle" >45</td><td align="center" valign="middle" >65</td><td align="center" valign="middle" >280</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >09-23-2020</td><td align="center" valign="middle" >24</td><td align="center" valign="middle" >10</td><td align="center" valign="middle" >2428</td><td align="center" valign="middle" >0</td><td align="center" valign="middle" >607</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >09-24-2020</td><td align="center" valign="middle" >500</td><td align="center" valign="middle" >11</td><td align="center" valign="middle" >3650</td><td align="center" valign="middle" >6271</td><td align="center" valign="middle" >4174</td></tr><tr><td align="center" valign="middle" >Chicago</td><td align="center" valign="middle" >09-26-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >7</td><td align="center" valign="middle" >518</td><td align="center" valign="middle" >47</td><td align="center" valign="middle" >5755</td></tr></tbody></table></table-wrap><table-wrap id="table13" ><label><xref ref-type="table" rid="table1">Table 1</xref>3</label><caption><title> Overview of Data: Houston</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >City</th><th align="center" valign="middle" >Protest Date</th><th align="center" valign="middle" >CCC Estimated Size</th><th align="center" valign="middle" ># Core</th><th align="center" valign="middle" ># Influence</th><th align="center" valign="middle" ># Echo</th><th align="center" valign="middle" >Avg Core Timeline Size</th></tr></thead><tr><td align="center" valign="middle" >Houston</td><td align="center" valign="middle" >05-26-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >2</td><td align="center" valign="middle" >281</td><td align="center" valign="middle" >54</td><td align="center" valign="middle" >116</td></tr><tr><td align="center" valign="middle" >Houston</td><td align="center" valign="middle" >05-29-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >36</td><td align="center" valign="middle" >16,193</td><td align="center" valign="middle" >14,953</td><td align="center" valign="middle" >772</td></tr><tr><td align="center" valign="middle" >Houston</td><td align="center" valign="middle" >05-30-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >24</td><td align="center" valign="middle" >7997</td><td align="center" valign="middle" >7846</td><td align="center" valign="middle" >441</td></tr><tr><td align="center" valign="middle" >Houston</td><td align="center" valign="middle" >06-02-2020</td><td align="center" valign="middle" >200</td><td align="center" valign="middle" >180</td><td align="center" valign="middle" >25,426</td><td align="center" valign="middle" >0</td><td align="center" valign="middle" >637</td></tr><tr><td align="center" valign="middle" >Houston</td><td align="center" valign="middle" >06-08-2020</td><td align="center" valign="middle" >40</td><td align="center" valign="middle" >26</td><td align="center" valign="middle" >5448</td><td align="center" valign="middle" >12,923</td><td align="center" valign="middle" >700</td></tr><tr><td align="center" valign="middle" >Houston</td><td align="center" valign="middle" >06-13-2020</td><td align="center" valign="middle" >50</td><td align="center" valign="middle" >4</td><td align="center" valign="middle" >23</td><td align="center" valign="middle" >1</td><td align="center" valign="middle" >1026</td></tr><tr><td align="center" valign="middle" >Houston</td><td align="center" valign="middle" >07-04-2020</td><td align="center" valign="middle" >2000</td><td align="center" valign="middle" >8</td><td align="center" valign="middle" >752</td><td align="center" valign="middle" >259</td><td align="center" valign="middle" >647</td></tr></tbody></table></table-wrap><p>The keywords used are listed in <xref ref-type="table" rid="table1">Table 1</xref>4. They fall into three different categories: 1) calls to mobilize others to actively join protests, 2) names of the individuals who were victims of injustice, and 3) phrases that are commonly chanted during protests. They are designed to capture the organizational period immediately before the protests, the protest itself, and the topics most likely discussed during the protests.</p><p>Having created keywords, we then populate the package’s Excel template; these values are in the template in the GitHub repository. To generate the event, the following code is used:</p><p>import gatherTweet as tw</p><p>dirr = “directory”</p><p>BLM = tw.TwitterEvent(“BLM”, base_directory = dirr)</p><p>BLM.upload_from_excel(dirr+“event_template.xlsx”).</p></sec><sec id="s5_1_2"><title>5.1.2. Individual Identification and Timeline Tweet Collection</title><p>Once the codex TwitterEvent object is set up, the collection can begin. One command accomplishes all of the user and tweet collection:</p><p>BLM.pull.get_tweets(BLM, base_directory = dirr)</p><p>The default of this function sets:</p><p>types = [codex Core, codex CoreTimeline, codex Echos, codex EchosTimeline, codex Influences, InfluencesTimeline].</p><p>Thus, it executes both of the major data collection steps of the method. This function signifies the main contribution of gatherTweet; in one call, given appropriate setup, researchers are able to collect all of the Twitter data for their purpose.</p><table-wrap id="table14" ><label><xref ref-type="table" rid="table1">Table 1</xref>4</label><caption><title> Keywords for protesters</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Keywords</th></tr></thead><tr><td align="center" valign="middle" >Black Lives Matter</td></tr><tr><td align="center" valign="middle" >BLM</td></tr><tr><td align="center" valign="middle" >George Floyd</td></tr><tr><td align="center" valign="middle" >Justice for Floyd</td></tr><tr><td align="center" valign="middle" >Walk with Us</td></tr><tr><td align="center" valign="middle" >Kneel with Us</td></tr><tr><td align="center" valign="middle" >March with Us</td></tr><tr><td align="center" valign="middle" >I Can’t Breathe</td></tr><tr><td align="center" valign="middle" >March for Peace</td></tr><tr><td align="center" valign="middle" >Take a Knee</td></tr><tr><td align="center" valign="middle" >Breonna Taylor</td></tr><tr><td align="center" valign="middle" >No Justice No Peace</td></tr><tr><td align="center" valign="middle" >Say Their Names</td></tr><tr><td align="center" valign="middle" >Ahmaud Aubrey</td></tr></tbody></table></table-wrap></sec><sec id="s5_1_3"><title>5.1.3. Analysis</title><p>Parsing and analysis follow data collection. First, we populated Tables 11-13 using the codex check.number_of_tweets command for each activity and group. These tables present summary statistics for each event. Los Angeles has the most tweets and accounts for all three types.</p><p>The rest of this application focuses on the actions of the core. In order to place all of the tweets related to the core users in one place, we run the following four commands.</p><p>BLM.read.read_tweets(BLM, users = “Core”)</p><p>BLM.read.wrap_csv(BLM, users = “Core”)</p><p>BLM.read.read_tweets_basic(BLM, users = “CoreTimeline”)</p><p>BLM.read.wrap_csv_basic(BLM, users = “CoreTimeline”).</p><p>Despite descriptive differences, the events are similar when it comes to their discussion frequency. <xref ref-type="fig" rid="fig4">Figure 4</xref> plots the percent of tweets from individuals in the core of activities taking place in each city each day. It shows that despite differences in each city’s design, size of protests, and local events, the discourse pattern is remarkably similar. These individuals had a large increase in Twitter chatter in the days following the murder of George Floyd with similar patterns in the months following.</p><p>In addition to proportional tweeting frequency, we see that very few individuals appear in the core more than once. We believe that individuals who are in the core are at the physical protests since their location places them in the city, and prior work has found that this assumption accurately measures protest size variation [<xref ref-type="bibr" rid="scirp.123470-ref20">20</xref>] . The lack of repeating individuals suggests that the group protesters may not have been consistent over time [<xref ref-type="bibr" rid="scirp.123470-ref21">21</xref>] [<xref ref-type="bibr" rid="scirp.123470-ref22">22</xref>] . The statistics regarding repeat members of the cores can be seen in <xref ref-type="table" rid="table1">Table 1</xref>5. Most of the members of the core of each city only go to one protest. The number of people who attend multiple protests is significantly fewer, and the numbers continue to decrease as the number of protests increases. Results like these can give researchers insights into protest behavior and help categorize the protests.</p></sec><sec id="s5_1_4"><title>5.1.4. Data Collection Time Estimate</title><p>Given the large amounts of data that events can generate, it is important to estimate runtime associated with gatherTweet. The exact time required for the collection of core users cannot be determined a priori. Depending on the event and activities within it, there is no precise way of estimating the size of the core. However, once the core has been collected it is possible to estimate the time required to collect the echo and influence users. A directed search for a five day period takes on average 6 seconds per user<sup>5</sup>. To collect the echo and influence users, this search must be run for each member of the core. Therefore, a time estimate for the collection of all echo and influence users can be approximated by:</p><p>#coreusers &#215; 2 &#215; 6   seconds (1)</p><table-wrap id="table15" ><label><xref ref-type="table" rid="table1">Table 1</xref>5</label><caption><title> Percent BLM repeat protesters by city</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Protests</th><th align="center" valign="middle" >Houston</th><th align="center" valign="middle" >Chicago</th><th align="center" valign="middle" >Los Angeles</th></tr></thead><tr><td align="center" valign="middle" >1</td><td align="center" valign="middle" >100.00</td><td align="center" valign="middle" >87.38</td><td align="center" valign="middle" >92.37</td></tr><tr><td align="center" valign="middle" >2</td><td align="center" valign="middle" >0.00</td><td align="center" valign="middle" >9.23</td><td align="center" valign="middle" >7.38</td></tr><tr><td align="center" valign="middle" >3</td><td align="center" valign="middle" >0.00</td><td align="center" valign="middle" >1.85</td><td align="center" valign="middle" >0.24</td></tr><tr><td align="center" valign="middle" >4</td><td align="center" valign="middle" >0.00</td><td align="center" valign="middle" >0.92</td><td align="center" valign="middle" >0.00</td></tr><tr><td align="center" valign="middle" >7</td><td align="center" valign="middle" >0.00</td><td align="center" valign="middle" >0.31</td><td align="center" valign="middle" >0.00</td></tr><tr><td align="center" valign="middle" >17</td><td align="center" valign="middle" >0.00</td><td align="center" valign="middle" >0.31</td><td align="center" valign="middle" >0.00</td></tr></tbody></table></table-wrap><p>A similar process was applied to find the time taken for timeline collection. Again, the specific individuals being queried can change these values, especially if the event being sampled is made up of prolific or reserved individuals. Our estimate for timeline collection is 0.1 seconds per day<sup>6</sup>. When the timeline gets shorter the time per day may increase. This is a result of the way Tweets are pulled. The program can receive 500 tweets per query, therefore, if the time is short enough that fewer than 500 tweets are found in each query the time to accomplish the task will remain constant. To find a rough estimate, the following equation may be followed:</p><p>#users &#215; #days &#215; 0.1   seconds (2)</p><p>We emphasize that the time required to collect tweets is heavily dependent on the subject matter the researcher is exploring as the frequency of tweeting is highly dependent on the type event.</p></sec></sec><sec id="s5_2"><title>5.2. Other Applications</title><p>This paper’s methodology can be applied to other social media platforms and other activities. This subsection discusses examples where gatherTweet and the associated methodology would be useful.</p><p>One obvious application would be mass-mobilization events such as the Yellow Vest protests in France [<xref ref-type="bibr" rid="scirp.123470-ref23">23</xref>] , the Black Lives Matter protests [<xref ref-type="bibr" rid="scirp.123470-ref24">24</xref>] , or the Women’s March [<xref ref-type="bibr" rid="scirp.123470-ref25">25</xref>] . Such protests are ideally suited because they involve a large following and spread out over time and space. Collecting all of the relevant social media data for events of these magnitudes would overwhelm many computer systems. Instead, for gatherTweet, the researcher would choose a set of geographic and time combinations to focus on. With such criteria, the monitor will identity the core and then expands out to find the rest of their network at the time of the activity.</p><p>A second application includes phenomena that move over time, such as heat waves or hurricanes, or epidemics like COVID-19. They require a slightly different approach than mass-mobilization events because the timing and geographic locations have to be well-specified. For weather episodes, the researcher has to discretize locations and timings to create the core. The researcher could choose a time increment, such as a number of hours or days, and pick a corresponding geographical area large enough to encompass the entire activity. That approach makes the most sense for events that move over time, such as a hurricane. For other natural activities, such as disease, where the geographic path is obscured, or there are jumps, or the presence of the activity is unclear, a threshold approach makes sense. Examples would be beginning the spread of COVID-19 when cases in a city surpass a per capita threshold.</p><p>Other examples of possible applications are elections and pop culture activities, such as performer’s tours or sports teams’ games. With these, there is a clear point when the activity occurs in a location. For example, elections, specifically U.S. presidential primaries, occur at different times in different locations. Sports teams, musicians, and comedians perform in different locations on certain dates and times. In each case, the approach is similar to the mass-mobilization since the location and timing of the core detection is often obvious. A main drawback is that these events may be smaller so the method may only pick up a small number of individuals.</p></sec></sec><sec id="s6"><title>6. Social Media Data Collection Restrictions</title><p>The collection process of Twitter data for research purposes are subject to the restrictions of its representational state transfer (REST) APIs<sup>7</sup>. While the documentation for the usage of the APIs is relatively straightforward, there are specific limitations pertinent to the implementation of gatherTweet. Perhaps the most binding limitation is rate limits that very by endpoint. <xref ref-type="table" rid="table1">Table 1</xref>6 provides common rate limits encountered.</p><table-wrap id="table16" ><label><xref ref-type="table" rid="table1">Table 1</xref>6</label><caption><title> Summary of Twitter rate limits</title></caption><table><tbody><thead><tr><th align="center" valign="middle" >Endpoint</th><th align="center" valign="middle" >Per App (15 min window)</th><th align="center" valign="middle" >Per User (15 min window)</th></tr></thead><tr><td align="center" valign="middle" >User tweet timeline</td><td align="center" valign="middle" >1500</td><td align="center" valign="middle" >900</td></tr><tr><td align="center" valign="middle" >User mention timeline</td><td align="center" valign="middle" >450</td><td align="center" valign="middle" >180</td></tr><tr><td align="center" valign="middle" >Full-archive search</td><td align="center" valign="middle" >300</td><td align="center" valign="middle" >180</td></tr></tbody></table></table-wrap><p>To maximize the number of requests, gatherTweet sends 1 query per second to prevent errors and to avoid sending bad requests that count towards the rate limit. The 1 query per second is an explicit one for the full-archive search, however sometimes it may be helpful to slow down the query rate to prevent too many endpoint requests. For example the user mention timeline can be requested 450 times per 15 minute window, and by spacing the 450 requests to be within a 15 minute time window (sending a request every 2 seconds rather than 1) prevents querying after the rate limit is reached.</p><p>Compounded with the rate limit issue is the 10 million tweet per month per key restriction. While the only solution to the monthly cap is the utilization of multiple sets of keys, the data methodology presented in this paper seeks to maximize the 10 million tweets by gathering the most central information to the event.</p><p>The data collection process gets more complex as the time span studied increases. Therefore, to identify the core of the event we utilize keywords that are associated with the topics most discussed during the event. When querying utilizing keywords it is important to use every possible version of the phrase in regards to spelling and spacing. In addition to the keyword search, our method specifies a location and time component. Approximately 1% - 2% of all tweets are geotagged which means the creation of geographic restrictions on the core allows us to maximize the 10 million tweets as well as insure with a higher likelihood that the tweets collected belong to users involved in the event. Our second measure is to restrict the collection to users who tweet during the day of the activity, increasing the likelihood we collect users physically present during an activity.</p><p>The data collection process is designed to be versatile with regards to researchers’ access to resources. The package gatherTweet can be run on university servers, in the cloud, or locally. The storage method of this data can also been done on a server or locally. By reducing the amount of post-processing required of the data it is extremely easy for the researchers to use the tweets in any type of natural language processing methodology.</p></sec><sec id="s7"><title>7. Conclusions</title><p>Social media provides a wealth of information for researchers. gatherTweet, an easy-to-use Python package that requires very little prior programming knowledge, can aid researchers in the collection and analysis of large scale social media events. Since large events can produce more data than most researchers can feasibly acquire, store, and analyze, gatherTweet’s data methodology provides a solution by targeting the main participants in an event.</p><p>The methodology presented in this paper instructs researchers on a clear way to conceptualize massive physical events which have discrete geographic and temporal activities. In addition, it creates a non-random approach to limiting the data collected, while accounting for exogenous trends such as location and time. Finally, in collecting the individuals who echo and influence the participants, the network surrounding participants is included. Thus, the process can be used to easily find social media users who both participate in offline event activities and are in the same sphere as each other.</p><p>This method is all the more relevant in an increasingly interconnected world. Events such as protests have a dispersion of geographic loci, and isolating them individually enables researchers to better pinpoint time spans and geographies. In creating a standardized method for data collection of large scale social media data of events, gatherTweet also enables comparison across future research projects. gatherTweet helps researchers directly collect the data most relevant to their cause.</p></sec><sec id="s8"><title>Acknowledgements</title><p>We thank the Google Cloud Research Credits Program for providing credits for our use of the Google Cloud Platform for data collection and analysis. Related research was presented at the 2022 MPSA Annual Meetings, we thank participants for their comments. Thanks as well to Jian Cao and Danny Ebanks for their help with our research.</p></sec><sec id="s9"><title>Conflicts of Interest</title><p>The authors declare no conflicts of interest regarding the publication of this paper.</p></sec><sec id="s10"><title>Cite this paper</title><p>Kann, C., Hashash, S., Steinert-Threlkeld, Z. and Alvarez, R.M. (2023) GatherTweet: A Python Package for Collecting Social Media Data on Online Events. Journal of Computer and Communications, 11, 172-193. https://doi.org/10.4236/jcc.2023.112012</p></sec><sec id="s11"><title>NOTES</title></sec></body><back><ref-list><title>References</title><ref id="scirp.123470-ref1"><label>1</label><mixed-citation publication-type="other" xlink:type="simple">Tillery, A.B. (2019) What Kind of Movement Is Black Lives Matter? The View from Twitter. Journal of Race, Ethnicity, and Politics, 4, 297-323. https://doi.org/10.1017/rep.2019.17</mixed-citation></ref><ref id="scirp.123470-ref2"><label>2</label><mixed-citation publication-type="other" xlink:type="simple">Theocharis, Y., Lowe, W., Van Deth, J.W. and Garc&amp;imath;a-Albacete, G. (2015) Using Twitter to Mobilize Protest Action: Online Mobilization Patterns and Action Repertoires in the Occupy Wall Street, Indignados, and Aganaktismenoi Movements. Information, Communication &amp; Society, 18, 202-220. https://doi.org/10.1080/1369118X.2014.948035</mixed-citation></ref><ref id="scirp.123470-ref3"><label>3</label><mixed-citation publication-type="other" xlink:type="simple">Conover, M.D., Ferrara, E., Menczer, F. and Flammini, A. (2013) The Digital Evolution of Occupy Wall Street. PLOS ONE, 8, e64679. https://doi.org/10.1080/1369118X.2014.948035</mixed-citation></ref><ref id="scirp.123470-ref4"><label>4</label><mixed-citation publication-type="other" xlink:type="simple">Kann, C., Hashash, S., Steinert-Threlkeld, Z. and Alvarez, R.M. (2021) Collective Identity in Collective Action: Evidence from the 2020 Summer Blm Protests. The 2021 Annual Meetings of the Midwest Political Science Association, Chicago, April 9, 2022.</mixed-citation></ref><ref id="scirp.123470-ref5"><label>5</label><mixed-citation publication-type="other" xlink:type="simple">Bruns, A. and Liang, Y.E. (2012) Tools and Methods for Capturing Twitter Data during Natural Disasters. First Monday, 17, 1-8. https://doi.org/10.5210/fm.v17i4.3937</mixed-citation></ref><ref id="scirp.123470-ref6"><label>6</label><mixed-citation publication-type="other" xlink:type="simple">Cao, J., Adams-Cohen, N. and Alvarez, R.M. (2021) Reliable and Efficient Long-Term Social Media Monitoring. Journal of Computer and Communications, 9, 97-109. https://doi.org/10.4236/jcc.2021.910006</mixed-citation></ref><ref id="scirp.123470-ref7"><label>7</label><mixed-citation publication-type="other" xlink:type="simple">Bozarth, L. and Budak, C. (2022) Keyword Expansion Techniques for Mining Social Movement Data on Social Media. EPJ Data Science, 11, 30. https://doi.org/10.1140/epjds/s13688-022-00343-9</mixed-citation></ref><ref id="scirp.123470-ref8"><label>8</label><mixed-citation publication-type="other" xlink:type="simple">Zheng, X. and Sun, A.X. (2019) Collecting Event-Related Tweets from Twitter Stream. Journal of the Association for Information Science and Technology, 70, 176-186. https://doi.org/10.1002/asi.24096</mixed-citation></ref><ref id="scirp.123470-ref9"><label>9</label><mixed-citation publication-type="other" xlink:type="simple">McCormick, T.H., Lee, H., et al. (2017) Using Twitter for Demographic and Social Science Research: Tools for Data Collection and Processing. Sociological Methods &amp; Research, 46, 390-421. https://doi.org/10.1177/0049124115605339</mixed-citation></ref><ref id="scirp.123470-ref10"><label>10</label><mixed-citation publication-type="other" xlink:type="simple">Barbera, P. and Steinert-Threlkeld, Z.C. (2020) How to Use Social Media Data for Political Science Research. SAGE Publications, Thousand Oaks. https://doi.org/10.4135/9781526486387.n26</mixed-citation></ref><ref id="scirp.123470-ref11"><label>11</label><mixed-citation publication-type="other" xlink:type="simple">Roesslein, J. (2009) Tweepy. https://github.com/tweepy/tweepy</mixed-citation></ref><ref id="scirp.123470-ref12"><label>12</label><mixed-citation publication-type="other" xlink:type="simple">Gedulig, J. (2021) Twitterapi. https://github.com/geduldig/TwitterAPI</mixed-citation></ref><ref id="scirp.123470-ref13"><label>13</label><mixed-citation publication-type="other" xlink:type="simple">Taylor, M. (2007) Python-Twitter. https://github.com/bear/python-twitter</mixed-citation></ref><ref id="scirp.123470-ref14"><label>14</label><mixed-citation publication-type="other" xlink:type="simple">Gonzalez-Bailon, S., Borge-Holthoefer, J. and Moreno, Y. (2013) Broadcasters and Hidden Influentials in Online Protest Diffusion. American Behavioral Scientist, 57, 943-965. https://doi.org/10.1177/0002764213479371</mixed-citation></ref><ref id="scirp.123470-ref15"><label>15</label><mixed-citation publication-type="other" xlink:type="simple">Eubank, N. and Kronick, D. (2021) Friends Don’t Let Friends Free Ride. Quarterly Journal of Political Science, 16, 533-557. https://doi.org/10.1561/100.00020143</mixed-citation></ref><ref id="scirp.123470-ref16"><label>16</label><mixed-citation publication-type="other" xlink:type="simple">Rudig, W. and Karyotis, G. (2013) Beyond the Usual Suspects? New Participants in Anti-Austerity Protests in Greece. Mobilization, 18, 313-330. https://doi.org/10.17813/maiq.18.3.r3377266074133w5</mixed-citation></ref><ref id="scirp.123470-ref17"><label>17</label><mixed-citation publication-type="other" xlink:type="simple">Kryvasheyeu, Y., Chen, H.H., Obradovich, N., et al. (2016) Rapid Assessment of Disaster Damage Using Social Media Activity. Science Advances, 2, e1500779. https://doi.org/10.1126/sciadv.1500779</mixed-citation></ref><ref id="scirp.123470-ref18"><label>18</label><mixed-citation publication-type="other" xlink:type="simple">Raleigh, C., Linke, A., Hegre, H. and Karlsen, J. (2010) Introducing Acled-Armed Conflict Location and Event Data. Journal of Peace Research, 47, 651-660. https://doi.org/10.1177/0022343310378914</mixed-citation></ref><ref id="scirp.123470-ref19"><label>19</label><mixed-citation publication-type="other" xlink:type="simple">Putnam, L., Chenoweth, E. and Pressman, J. (2020) The Floyd Protests Are the Broadest in U.S. History—And Are Spreading to White, Small-Town America.</mixed-citation></ref><ref id="scirp.123470-ref20"><label>20</label><mixed-citation publication-type="other" xlink:type="simple">Sobolev, A., Joo, J., Chen, K. and Steinert-Threlkeld, Z.C. (2020) News and Geolocated Social Media Accurately Measure Protest Size Variation. American Political Science Review, 114, 1343-1351. https://doi.org/10.1017/S0003055420000295</mixed-citation></ref><ref id="scirp.123470-ref21"><label>21</label><mixed-citation publication-type="other" xlink:type="simple">Saunders, C., Grasso, M., et al. (2012) Explaining Differential Protest Participation: Novices, Returners, Repeaters, and Stalwarts. Mobilization, 17, 263-280. https://doi.org/10.17813/maiq.17.3.bqm553573058t478</mixed-citation></ref><ref id="scirp.123470-ref22"><label>22</label><mixed-citation publication-type="other" xlink:type="simple">Saunders, C. and Shlomo, N. (2021) A New Approach to Assess the Normalization of Differential Rates of Protest Participation. Quality and Quantity, 55, 79-102. https://doi.org/10.1007/s11135-020-00995-7</mixed-citation></ref><ref id="scirp.123470-ref23"><label>23</label><mixed-citation publication-type="other" xlink:type="simple">Smith, S. (2018) Who Are France’s “Yellow Jacket” Protesters and What Do They Want? NBC News.</mixed-citation></ref><ref id="scirp.123470-ref24"><label>24</label><mixed-citation publication-type="other" xlink:type="simple">Buchanan, L., Bui, Q. and Patel, J.K. (2020) Black Lives Matter May Be the Largest Movement in U.S. History. The New York Times.</mixed-citation></ref><ref id="scirp.123470-ref25"><label>25</label><mixed-citation publication-type="other" xlink:type="simple">Stein, P., Hendrix, S. and Hausiohner, A. (2017) Women’s Marches: More than One Million Protesters Vow to Resist President Trump. The Washington Post.</mixed-citation></ref></ref-list></back></article>