<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-7368492749480468247</atom:id><lastBuildDate>Wed, 17 Oct 2018 12:04:19 +0000</lastBuildDate><category>Linux</category><category>Management</category><category>programming</category><category>Software</category><category>StartUp</category><category>Book</category><category>Technology</category><category>Web Development</category><category>Finance</category><category>Learning Language</category><category>computer science</category><category>Web Server</category><category>Windows</category><category>Cloud Computing</category><category>Machine Learning</category><category>Photography</category><category>Big Data</category><category>Computer Algorithm</category><category>Database</category><category>Diary</category><category>Fitness</category><category>Java</category><category>PHP</category><category>Python</category><category>Smart Grid</category><category>Travel</category><category>Virtual Machine</category><title>Life Editor</title><description>Be patient, disciplined, and eager to learn</description><link>http://lifeeditor.blogspot.com/</link><managingEditor>noreply@blogger.com (MathBee)</managingEditor><generator>Blogger</generator><openSearch:totalResults>179</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-8673632609446304764</guid><pubDate>Tue, 28 Apr 2015 02:21:00 +0000</pubDate><atom:updated>2015-04-28T10:21:03.770+08:00</atom:updated><title>Ask HN: How do you log application events?</title><description>We are currently inserting our  logs in an sql database, with timestamp, logType, userId, userAgent and  description columns. It makes it trivial for us to debug any event by  just querying the db. However, after three and a half years of continued  use, the table is now way too large.&lt;br /&gt;How do you guys log application  events in such a way that extracting information from it is easy, but  still keep the size of the logs manageable?&lt;br /&gt;&lt;br /&gt;&lt;table border=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;img height=&quot;1&quot; src=&quot;https://news.ycombinator.com/s.gif&quot; width=&quot;0&quot; /&gt;&lt;/td&gt;        &lt;td valign=&quot;top&quot;&gt;&lt;center&gt;&lt;/center&gt;&lt;br /&gt;&lt;/td&gt;&lt;td class=&quot;default&quot;&gt;&lt;div style=&quot;margin-bottom: -10px; margin-top: 2px;&quot;&gt;&lt;span class=&quot;comhead&quot;&gt;          &lt;a href=&quot;https://news.ycombinator.com/user?id=thaumaturgy&quot;&gt;thaumaturgy&lt;/a&gt; &lt;a href=&quot;https://news.ycombinator.com/item?id=9447798&quot;&gt;8 hours ago&lt;/a&gt; &lt;span class=&quot;deadmark&quot;&gt;&lt;/span&gt;                            &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;                  &lt;span style=&quot;color: black;&quot;&gt;Ehm, the contrast between my answer and everyone else&#39;s here makes me feel surprisingly greybearded, but...Application  logging has been a solved problem for decades now. syslog or  direct-to-disk in a reasonable format, let logrotate do the job it&#39;s  faithfully done for years and let the gzipped old files get picked up by  the offsite backups that you&#39;re surely running, and use the standard  collection of tools for mining text files: grep, cut, tail, etc.&lt;/span&gt;&lt;span style=&quot;color: black;&quot;&gt;I&#39;m  a little weirded out that &quot;my logs are too big&quot; is still a thing, and  that the most common answer to this is &quot;glue even more complexity  together&quot;.&lt;/span&gt;                             &lt;br /&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;                      &lt;u&gt;&lt;a href=&quot;https://news.ycombinator.com/reply?id=9447798&amp;amp;goto=item%3Fid%3D9444470&quot;&gt;reply&lt;/a&gt;&lt;/u&gt;                  &lt;/span&gt;          &lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table border=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;img height=&quot;1&quot; src=&quot;https://news.ycombinator.com/s.gif&quot; width=&quot;40&quot; /&gt;&lt;/td&gt;        &lt;td valign=&quot;top&quot;&gt;&lt;center&gt;&lt;/center&gt;&lt;br /&gt;&lt;/td&gt;&lt;td class=&quot;default&quot;&gt;&lt;div style=&quot;margin-bottom: -10px; margin-top: 2px;&quot;&gt;&lt;span class=&quot;comhead&quot;&gt;          &lt;a href=&quot;https://news.ycombinator.com/user?id=nlh&quot;&gt;nlh&lt;/a&gt; &lt;a href=&quot;https://news.ycombinator.com/item?id=9448021&quot;&gt;7 hours ago&lt;/a&gt; &lt;span class=&quot;deadmark&quot;&gt;&lt;/span&gt;                            &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class=&quot;comment&quot;&gt;                  &lt;span style=&quot;color: black;&quot;&gt;100% agree.  Don&#39;t try to build your own when there are some excellent free (and commercial) ones that are battle-tested.grep, cut, tail, etc. work quite well if you&#39;re working on a single machine or small number of machines.&lt;br /&gt;The  &quot;ELK stack&quot; (ElasticSearch, Logstash, Kibana) is a step up in  complexity but gives you much more power than command line tools.&lt;br /&gt;There  are also some great commercial solutions that abstract away some of  that complexity if you don&#39;t feel like rolling your own (Scalyr, Splunk,  SumoLogic, etc.).&lt;br /&gt;But regardless of the path you take, don&#39;t reinvent the wheel!&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;</description><link>http://lifeeditor.blogspot.com/2015/04/ask-hn-how-do-you-log-application-events.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-2614157987358019547</guid><pubDate>Tue, 28 Apr 2015 02:16:00 +0000</pubDate><atom:updated>2015-04-28T10:16:09.785+08:00</atom:updated><title>FIFA 2014 World Cup live stream architecture</title><description>&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt=&quot;live_stream_nginx&quot; class=&quot;aligncenter wp-image-422 size-full&quot; height=&quot;213&quot; src=&quot;https://archsofty.files.wordpress.com/2014/10/live_stream_nginx.png?w=700&quot; width=&quot;477&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://opensource.globo.com/en/&quot; target=&quot;_blank&quot; title=&quot;Globo.com open source projects&quot;&gt;We&lt;/a&gt; were given the task to stream&amp;nbsp;the &lt;a href=&quot;http://en.wikipedia.org/wiki/2014_FIFA_World_Cup&quot; target=&quot;_blank&quot; title=&quot;2014 FIFA&quot;&gt;FIFA 14 World Cup&lt;/a&gt;&amp;nbsp;and I think this was an experience worth sharing. This is a &lt;strong&gt;quick&lt;/strong&gt; overview about: the architecture, the components, the pain, the learning, the open source and etc. &lt;br /&gt;&lt;h1&gt;The&amp;nbsp;numbers&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;GER 7×1 BRA (yeah, we’re not proud of it)&lt;/li&gt;&lt;li&gt;0.5M&amp;nbsp;simultaneous&amp;nbsp;users @ a single game – ARG x SUI&lt;/li&gt;&lt;li&gt;580Gbps @ a single game – ARG x SUI&lt;/li&gt;&lt;li&gt;=~ 1600 watched years @ the whole event&lt;/li&gt;&lt;/ul&gt;&lt;h1&gt;The core&amp;nbsp;overview&lt;/h1&gt;The project was to receive an input stream, generate&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/HTTP_Live_Streaming&quot; target=&quot;_blank&quot; title=&quot;hls&quot;&gt;HLS&lt;/a&gt;&amp;nbsp;output stream for hundreds of&amp;nbsp;thousands and to&amp;nbsp;provide a great experience for final users:&lt;br /&gt; &lt;ol&gt;&lt;li&gt;Fetch the RTMP input stream&lt;/li&gt;&lt;li&gt;Generate HLS and send it&amp;nbsp;to &lt;a href=&quot;http://cassandra.apache.org/&quot; target=&quot;_blank&quot; title=&quot;cassandra&quot;&gt;Cassandra&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Fetch binary and meta data from Cassandra and rebuild the HLS playlists with Nginx+lua&lt;/li&gt;&lt;li&gt;Serve and cache the live content&amp;nbsp;in a &lt;a href=&quot;http://leandromoreira.com.br/2014/11/20/how-to-start-to-learn-high-scalability/&quot; target=&quot;_blank&quot; title=&quot;how to learn high scalability&quot;&gt;scalable way&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Design and implement the player&lt;/li&gt;&lt;/ol&gt;If you want to understand why we chose HLS&amp;nbsp;check&amp;nbsp;&lt;a href=&quot;http://www.slideshare.net/leandro_moreira/fisl15-streaming-de-video-ao-vivo-na-globocom&quot; target=&quot;_blank&quot; title=&quot;Live Streaming @ Globo.com&quot;&gt;this presentation only in pt-BR&lt;/a&gt;. &lt;strong&gt;tip&lt;/strong&gt;:&amp;nbsp;sometimes we need to rebuild some things from scratch.&lt;br /&gt; &lt;h1&gt;The input&lt;/h1&gt;The live stream comes to our servers&amp;nbsp;as &lt;a href=&quot;http://en.wikipedia.org/wiki/Real_Time_Messaging_Protocol&quot; target=&quot;_blank&quot; title=&quot;rtmp&quot;&gt;RTMP&lt;/a&gt; and we were using &lt;a href=&quot;https://evostream.com/&quot; target=&quot;_blank&quot; title=&quot;ems&quot;&gt;EvoStream&lt;/a&gt; (now we’re moving to &lt;a href=&quot;https://github.com/arut/nginx-rtmp-module&quot; target=&quot;_blank&quot; title=&quot;nginx-rtmp&quot;&gt;nginx-rtmp&lt;/a&gt;) to &lt;strong&gt;receive this input and to generate HLS&lt;/strong&gt;&amp;nbsp;output to&amp;nbsp;a &lt;strong&gt;known folder&lt;/strong&gt;. Then we have some&lt;strong&gt;&amp;nbsp;python daemons&lt;/strong&gt;, running at the same machine, &lt;strong&gt;watching this known folder&lt;/strong&gt; and &lt;a href=&quot;https://github.com/globocom/m3u8&quot; target=&quot;_blank&quot; title=&quot;python m3u8&quot;&gt;parsing the m3u8&lt;/a&gt; and&amp;nbsp;&lt;strong&gt;posting&amp;nbsp;the&amp;nbsp;data&amp;nbsp;to Cassandra&lt;/strong&gt;.&lt;br /&gt; To watch files modification and to be notified by these events, we  first tried watchdog but for some reason we weren’t able to make it work  as fast as we expected and we changed to&amp;nbsp;pyinotify.&lt;br /&gt; Another challenge we had to overcome was to make the&amp;nbsp;python program  scale to x&amp;nbsp;cpu cores, we ended up by creating multiple Python processes  and using &lt;a href=&quot;http://datastax.github.io/python-driver/api/cassandra/cluster.html#cassandra.cluster.Session.execute_async&quot; target=&quot;_blank&quot; title=&quot;cassandra async&quot;&gt;async execution&lt;/a&gt;.&lt;br /&gt; &lt;strong&gt;tip&lt;/strong&gt;:&amp;nbsp;maybe the best language / tool &lt;a href=&quot;http://cdn.thedailybeast.com/content/dailybeast/articles/2014/05/27/your-princess-is-in-another-castle-misogyny-entitlement-and-nerds/jcr:content/image.crop.800.500.jpg/1405354940376.cached.jpg&quot; target=&quot;_blank&quot; title=&quot;joke another castle&quot;&gt;is in another castle&lt;/a&gt;.&lt;br /&gt; &lt;h1&gt;The storage&lt;/h1&gt;We previously were using Redis to store the live stream data&amp;nbsp;&lt;a href=&quot;http://planetcassandra.org/blog/interview/globo-rewinds-redis-for-their-dvr-system-fast-forwards-to-apache-cassandra-for-increased-availability/&quot; target=&quot;_blank&quot; title=&quot;moving from redis to cassandra&quot;&gt;but we thought&amp;nbsp;Cassandra was needed&lt;/a&gt;&amp;nbsp;to  offer DVR functionality easily (although we still uses&amp;nbsp;Redis a lot).  Cassandra response time was increasing with load&amp;nbsp;to&amp;nbsp;a certain point  where&amp;nbsp;clients started to timeout and the video playback completely  stopped.&lt;br /&gt; We were using it as &lt;a href=&quot;http://www.datastax.com/dev/blog/cassandra-anti-patterns-queues-and-queue-like-datasets&quot; target=&quot;_blank&quot; title=&quot;cassandra anti-pattern&quot;&gt;Queue-like&lt;/a&gt; which turns out to be a anti-pattern. We then denormalized our data and also changed to &lt;a href=&quot;http://www.datastax.com/documentation/cql/3.1/cql/cql_reference/tabProp.html?scroll=tabProp__moreCompaction&quot; target=&quot;_blank&quot;&gt;LeveledCompactionStrategy&lt;/a&gt; as well as we set &lt;strong&gt;durable_writes&lt;/strong&gt; to false, since we could treat our live stream as ephemeral data.&lt;br /&gt; &lt;blockquote&gt;Finally, but most importantly, since we knew the maximum  size a playlist could have, we could specify the start column (filtering  with id &amp;gt; minTimeuuid(now – playlist_duration)). This really  mitigated the effect of tombstones for reads. After these changes, we  were able to achieve a &lt;strong&gt;latency in the order of 10ms&lt;/strong&gt; for our 99% percentile.&lt;/blockquote&gt;&lt;strong&gt;tip&lt;/strong&gt;: limit your queries + denormalize your data&amp;nbsp;+ &lt;a href=&quot;http://www.datastax.com/dev/blog/pluggable-metrics-reporting-in-cassandra-2-0-2&quot; target=&quot;_blank&quot;&gt;send instrumentation data to graphite&lt;/a&gt; + use SSD.&lt;br /&gt; &lt;h1&gt;The&amp;nbsp;output&lt;/h1&gt;With all the data and meta-data we could build the HLS manifest and  serve the video chunks.&amp;nbsp;The only thing we were struggling was that we  didn’t want to add an extra server to fetch and build the manifests.&lt;br /&gt; Since&amp;nbsp;we already had&amp;nbsp;invested a lot of effort into&amp;nbsp;&lt;a href=&quot;https://blog.cloudflare.com/pushing-nginx-to-its-limit-with-lua/&quot; target=&quot;_blank&quot; title=&quot;nginx + lua&quot;&gt;Nginx+Lua&lt;/a&gt;, we thought it could be possible to use lua to fetch and build the manifest. It was a matter of building a &lt;a href=&quot;https://github.com/jbochi/lua-resty-cassandra%C2%A0&quot; target=&quot;_blank&quot; title=&quot;cassandra lua driver&quot;&gt;lua driver for Cassandra&lt;/a&gt; and use it. One good thing about this approach (rebuilding the  manifest) was that in the end we realized that we were almost ready to  serve &lt;a href=&quot;http://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP&quot; target=&quot;_blank&quot; title=&quot;dash&quot;&gt;DASH&lt;/a&gt;.&lt;br /&gt; &lt;strong&gt;tip&lt;/strong&gt;: &lt;a href=&quot;https://github.com/Olivine-Labs/busted&quot; target=&quot;_blank&quot; title=&quot;busted&quot;&gt;test your lua scripts&lt;/a&gt; + check the&amp;nbsp;lua global vars + &lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_use_stale&quot; target=&quot;_blank&quot; title=&quot;cache stale&quot;&gt;double check your caching&amp;nbsp;config&lt;/a&gt;&lt;br /&gt; &lt;h1&gt;The player&lt;/h1&gt;In order to provide a better experience, we chose to build &lt;a href=&quot;http://blog.flavioribeiro.com/clappr-an-extensible-media-player-for-the-web/&quot; target=&quot;_blank&quot; title=&quot;brief explanation about clappr&quot;&gt;Clappr&lt;/a&gt;,  an extensible open-source HTML5 video player. With Clappr – and a few  custom extensions like PiP (Picture In Picture) and Multi-angle replays –  we were able to deliver a great experience to our users. &lt;img alt=&quot;&quot; class=&quot;alignnone&quot; src=&quot;http://blog.flavioribeiro.com/content/images/2014/Nov/06_player_multicamera-1.jpg&quot; /&gt;&lt;br /&gt; &lt;strong&gt;tip&lt;/strong&gt;: open source it from day 0 + follow to flow issue&amp;nbsp;-&amp;gt; commit FIX#123&lt;br /&gt; &lt;h1&gt;The&amp;nbsp;sauron&lt;/h1&gt;To keep an eye over all these system, we built a monitoring dashboard  using&amp;nbsp;mostly open source projects like: logstash, elastic search,  graphite, graphana, kibana, seyren, angular, mongo, redis, rails and  many others. &lt;img alt=&quot;&quot; class=&quot;alignnone&quot; height=&quot;359&quot; src=&quot;http://image.slidesharecdn.com/fisl15-streamingdevideoaovivonaglobo-140509123535-phpapp01/95/fisl15-streaming-de-video-ao-vivo-na-globocom-22-638.jpg?cb=1399657062&quot; width=&quot;638&quot; /&gt;&lt;br /&gt; &lt;strong&gt;tip&lt;/strong&gt;: use SSD for graphite and elasticsearch&lt;br /&gt; &lt;h1&gt;The bonus round&lt;/h1&gt;Although we didn’t open sourced the entire&amp;nbsp;solution, you can check most of them:&lt;br /&gt; &lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/globocom/m3u8&quot; target=&quot;_blank&quot;&gt;Python HLS manifest parser / utility&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/jbochi/lua-resty-cassandra&quot; target=&quot;_blank&quot;&gt;Pure lua Cassandra client driver&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/clappr/clappr&quot; target=&quot;_blank&quot;&gt;Clappr&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/jbochi/live_thumb&quot; target=&quot;_blank&quot;&gt;Live thumbnail&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/flavioribeiro/nginx-audio-track-for-hls-module&quot; target=&quot;_blank&quot;&gt;Audio only from HLS nginx module&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/jbochi/bullock&quot; target=&quot;_blank&quot;&gt;Python lock (redis)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://blog.flavioribeiro.com/bemtv-hls-p2p-webrtc/&quot; target=&quot;_blank&quot; title=&quot;bem.tv p2p over http&quot;&gt;P2P and HTTP live streaming&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Source: &lt;a href=&quot;http://leandromoreira.com.br/2015/04/26/fifa-2014-world-cup-live-stream-architecture/&quot; target=&quot;_blank&quot;&gt;http://leandromoreira.com.br/2015/04/26/fifa-2014-world-cup-live-stream-architecture/ &lt;/a&gt;&lt;br /&gt;</description><link>http://lifeeditor.blogspot.com/2015/04/fifa-2014-world-cup-live-stream.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-2153871434859198572</guid><pubDate>Wed, 28 Jan 2015 07:28:00 +0000</pubDate><atom:updated>2015-01-28T15:29:14.999+08:00</atom:updated><title>DIY Device Cloud</title><description>&lt;ul class=&quot;buillogs-list&quot;&gt;&lt;li&gt;                            &lt;h2&gt;&lt;a href=&quot;http://hackaday.io/project/1109/log/2442-motivation-and-goals&quot;&gt;Motivation and Goals&lt;/a&gt;&lt;/h2&gt;&lt;small class=&quot;authorship&quot;&gt;                                &lt;/small&gt;                            &lt;div style=&quot;position: relative;&quot;&gt;&lt;div id=&quot;post-body-2442&quot;&gt;&lt;b&gt;What is a device cloud?&lt;/b&gt;&lt;br /&gt;I  consider a device cloud to be a service that provides both a broker for  communication between devices and a host for applications that interact  with devices.  The broker allows devices to communicate to other  devices or applications without having to be tightly coupled or directly  connected to each other.  The device cloud is also an easily accessible  host for applications that interact with devices, such as  visualizations of data or control of device functionality.&lt;br /&gt;&lt;b&gt;Why do you want a device cloud?&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Discovering  and connecting to your devices over the internet is hard!  Dynamic IP  addresses, NAT, firewalls, and more prevent you from easily accessing  your home network and devices.  Hosting your own device cloud on the  internet allows devices to connect and communicate without the trouble  of opening connectivity to your home network.&lt;/li&gt;&lt;li&gt;Not all devices  can be connected and online all the time. A device cloud allows for  asynchronous communication between devices. For example a sensor or  actuator can periodically connect to your device cloud to record data or  receive new instructions; because the device isn&#39;t connected all the  time it can greatly reduce its power consumption.&lt;/li&gt;&lt;li&gt;You have total  control over the data and services available to your devices.  You  aren&#39;t limited by what a 3rd party provides or concerned about what they  might do with your data. You own the entire infrastructure and can mold  it to your needs.&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Project Goals&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Automate  the setup and maintenance of services that form a personal device  cloud.  Setup should be an easily repeatable process from a single  command or script.&lt;/li&gt;&lt;li&gt;Target running the device cloud on cheap, low end cloud infrastructure like&amp;nbsp;&lt;a href=&quot;http://aws.amazon.com/free/?sc_channel=PS&amp;amp;sc_campaign=AWS_Free_Tier_2013&quot;&gt;Amazon EC2&#39;s micro instance free tier&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Build  on existing tools, services, and protocols--don&#39;t reinvent the wheel!   Many of the services to build a device cloud exist today, they just need  to be put together into an easy to use package.&lt;/li&gt;&lt;li&gt;Document how to connect popular development hardware like the Raspberry Pi, Beaglebone Black, and Arduino to a device cloud.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;                            &lt;h2&gt;&lt;a href=&quot;http://hackaday.io/project/1109/log/2444-mqtt-broker-that-ties-everything-together&quot;&gt;MQTT - Broker That Ties Everything Together&lt;/a&gt;&lt;/h2&gt;&lt;small class=&quot;authorship&quot;&gt;                                &lt;/small&gt;                            &lt;div style=&quot;position: relative;&quot;&gt;&lt;div id=&quot;post-body-2444&quot;&gt;&lt;a href=&quot;http://mqtt.org/&quot;&gt;MQTT&lt;/a&gt; is a publish-subscribe protocol that&#39;s perfect as a broker for device  to device communication. &amp;nbsp;Created by&amp;nbsp;Andy Stanford-Clark and Arlen  Nipper, it has been used in projects like Andy&#39;s own&amp;nbsp;&lt;a href=&quot;http://www.slideshare.net/andysc/the-house-that-twitters&quot;&gt;&#39;Twittering House&#39;&lt;/a&gt;. &amp;nbsp;You can see more from Andy in this TEDx talk:&lt;br /&gt;&lt;a href=&quot;http://mosquitto.org/&quot;&gt;Mosquitto&lt;/a&gt; is an open source MQTT broker implementation that&#39;s under active  development, has an established reputation, and is well documented.  &amp;nbsp;I&#39;ve done some informal testing with Mosquitto and it seems like the  perfect broker to use in this project.&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;                            &lt;h2&gt;&lt;a href=&quot;http://hackaday.io/project/1109/log/2445-ansible-automation-thats-easy&quot;&gt;Ansible - Automation That&#39;s Easy&lt;/a&gt;&lt;/h2&gt;&lt;small class=&quot;authorship&quot;&gt;&lt;a class=&quot;gray-link&quot; href=&quot;http://hackaday.io/project/1109/log/2445#discussion-list&quot;&gt;                                &lt;/a&gt;                                &lt;/small&gt;                            &lt;div style=&quot;position: relative;&quot;&gt;&lt;div id=&quot;post-body-2445&quot;&gt;&lt;a href=&quot;http://www.ansible.com/home&quot;&gt;Ansible&lt;/a&gt; is part of a new generation of open source IT automation tools which  aim to simplify the automation of tasks like installing software and  setting up servers. &amp;nbsp;You can see more about Ansible from its creator in  this recent PyCon talk:&lt;br /&gt;Ansible  strives to be simple and requires very little support infrastructure or  complex setup. &amp;nbsp;Even though the project is only a few years old, it is  already one of the largest on github and home to a healthy ecosystem of  modules that can automate almost any server task. &lt;br /&gt;I&#39;ve been  investigating Ansible and expect to make heavy use of it as the primary  means of automating the setup and maintenance of the device cloud. &amp;nbsp;The  primary output of this project will likely be a collection of Ansible  playbooks and tasks that help you build and manage your own device  cloud.&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;                            &lt;h2&gt;&lt;a href=&quot;http://hackaday.io/project/1109/log/2484-architecture-sketch&quot;&gt;Architecture Sketch&lt;/a&gt;&lt;/h2&gt;&lt;small class=&quot;authorship&quot;&gt;                                &lt;/small&gt;                            &lt;div style=&quot;position: relative;&quot;&gt;&lt;div id=&quot;post-body-2484&quot;&gt;Here&#39;s a high level look at how I see different components fitting together to form a device cloud:&lt;br /&gt;&lt;img src=&quot;http://static.hackaday.io/images/6614661399661017398.png&quot; height=&quot;492&quot; width=&quot;640&quot; /&gt;&lt;br /&gt;The  MQTT broker, mosquitto, is at the center of all communication and lives  on a server in Amazon EC2, Microsoft Azure, etc. &amp;nbsp;Along with the broker  other applications like visualizations or control apps are hosted on  the same server and can communicate with the broker directly. &amp;nbsp;I have  some early thoughts on these apps and will save that for a followup  post.&lt;br /&gt;Devices in your home network, or really anywhere, connect to  the MQTT broker using an encrypted SSL MQTT channel. &amp;nbsp;Normally SSL is a  tremendous pain to configure and manage (especially with self-signed  certificates), however I&#39;ve found it&#39;s easy to automate the certificate  creation tasks using Ansible so it should be painless. &amp;nbsp;I want the  device cloud to be secure by default and not require someone to be an  expert in security to setup or run the system.&lt;br /&gt;Devices can be any  hardware that&#39;s powerful enough to speak MQTT&#39;s protocol. &amp;nbsp;Embedded  Linux boards like the Raspberry Pi, Beaglebone Black, Arduino Yun, Intel  Galileo, etc. will be very easy to configure and use with the device  cloud. &amp;nbsp;I hope to even provide Ansible tasks that can deploy and  configure MQTT client tools and libraries on any embedded Linux device  automatically.&lt;br /&gt;What about devices which don&#39;t support SSL, like an  Arduino &amp;amp; CC3000? &amp;nbsp;In this case mosquitto has a concept of a bridge  server which can act both as an MQTT broker and client. &amp;nbsp;Any MQTT  messages sent to the bridge will be relayed back up to the parent broker  and vice-versa. &amp;nbsp;With this setup it will be possible to build a small,  low power Arduino + CC3000 device that periodically connects to the  bridge over an unencrypted channel to send/receive commands. &amp;nbsp;Because  the bridge lives inside your home network (which is secured with  wireless encryption, right?) it&#39;s still relatively secure. &amp;nbsp;Certainly  more secure than opening the broker in the cloud up to unencrypted MQTT  traffic! &amp;nbsp;Again Ansible tasks should be able to turn any Linux gadget  into a bridge for the device cloud easily.&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;                            &lt;h2&gt;&lt;a href=&quot;http://hackaday.io/project/1109/log/2487-github-home-documentation&quot;&gt;Github Home &amp;amp; Documentation&lt;/a&gt;&lt;/h2&gt;&lt;small class=&quot;authorship&quot;&gt;                                &lt;/small&gt;                            &lt;div style=&quot;position: relative;&quot;&gt;&lt;div id=&quot;post-body-2487&quot;&gt;I&#39;ve started a&amp;nbsp;&lt;a href=&quot;https://github.com/tdicola/DIYDeviceCloud&quot;&gt;repository on github&lt;/a&gt; that will be the home for all the software output from this project.  &amp;nbsp;Since documentation will be an important part of this project I&#39;ve also  created a base for the documentation at&amp;nbsp;&lt;a href=&quot;http://diy-device-cloud.readthedocs.org/&quot;&gt;http://diy-device-cloud.readthedocs.org/&lt;/a&gt;&amp;nbsp;using the excellent&amp;nbsp;&lt;a href=&quot;https://readthedocs.org/&quot;&gt;readthedocs.org&lt;/a&gt;&amp;nbsp;service.  &amp;nbsp;The documentation is actually built from files in the github  repository for the project (under the docs folder) based on the&amp;nbsp;&lt;a href=&quot;http://sphinx-doc.org/&quot;&gt;sphinx tool&lt;/a&gt;.  &amp;nbsp;Because the docs are in the repository it&#39;s easy to keep them  versioned and up to date. &amp;nbsp;For now I&#39;ve put up a couple docs that recap  what I&#39;ve covered so far in the project logs here.&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;                            &lt;h2&gt;&lt;a href=&quot;http://hackaday.io/project/1109/log/2536-mqtt-broker-setup-on-amazon-ec2&quot;&gt;MQTT Broker Setup On Amazon EC2&lt;/a&gt;&lt;/h2&gt;&lt;small class=&quot;authorship&quot;&gt;                                &lt;/small&gt;                            &lt;div style=&quot;position: relative;&quot;&gt;&lt;div id=&quot;post-body-2536&quot;&gt;In the past  couple days I&#39;ve added playbooks to the project github source which  allow you to provision an MQTT broker server on Amazon&#39;s EC2 cloud and  set up a basic device cloud. &amp;nbsp;Check out this video to see a walkthrough  of setting up a server and communicating with a Raspberry Pi:&amp;nbsp; &lt;br /&gt;I&#39;m  still a little new to using Ansibile, but so far am really happy with  how simple it&#39;s making the process of standing up a server from scratch.&lt;br /&gt;Also  I purchased the &#39;diydevicecloud.net&#39; domain name and am making  subdomains of it available to anyone who wants to host their device  cloud from an easily reachable address with the excellent&amp;nbsp;&lt;a href=&quot;http://freedns.afraid.org/&quot;&gt;FreeDNS.afraid.org dynamic DNS service&lt;/a&gt;. &amp;nbsp;You can&amp;nbsp;&lt;a href=&quot;http://freedns.afraid.org/domain/registry/?sort=5&amp;amp;q=diydevicecloud.net&amp;amp;submit=SEARCH&quot;&gt;find the domain here&lt;/a&gt; and just need a free account on FreeDNS to get a subdomain. &amp;nbsp;I&#39;ve even  integrated into the Ansible playbook a step to register a regular cron  job that will keep your broker server IP address up to date with your  FreeDNS domain. &amp;nbsp;Watch the video to see more details of the process. &lt;br /&gt;You  aren&#39;t limited to using this domain either--there are many other  domains on FreeDNS, or you can even buy your own domain and get a static  IP in Amazon&#39;s cloud.&lt;br /&gt;The next area I want to focus on are client  apps. &amp;nbsp;As a part of this project I want to document a few end to end  examples of MQTT applications, such as measuring sensor data or remotely  controlling devices.&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;                            &lt;h2&gt;&lt;a href=&quot;http://hackaday.io/project/1109/log/2580-server-deployment-updates&quot;&gt;Server Deployment Updates&lt;/a&gt;&lt;/h2&gt;&lt;div style=&quot;position: relative;&quot;&gt;&lt;div id=&quot;post-body-2580&quot;&gt;I&#39;ve done  some cleaning up and refactored the Ansible playbooks to use roles as  suggested by Ansible&#39;s best practices. &amp;nbsp;I&#39;m not super happy with how the  system is configured--right now global configuration is in the  inventory file under the [all:vars] group. &amp;nbsp;This is a good spot to  configure the entire system in one file but feels a little unwieldily. &amp;nbsp;  I&#39;ll be looking more into other options here to see if there&#39;s a  simpler and more flexible way to configure the system.&lt;br /&gt;I&#39;ve also added quite a few roles to form the base of the server, including:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;MQTT server: installs mosquitto server and configures it to use SSL secured MQTT communication.&lt;/li&gt;&lt;li&gt;MQTT  client: installs mosquitto client tools, Paho MQTT python client  library, and the SSL certs for communication with the server. &amp;nbsp;This role  can be installed on both the Ubuntu-based server and Debian-based  devices like the Raspberry Pi or Beaglebone Black.&lt;/li&gt;&lt;li&gt;Security:  installs and configures fail2ban brute force attack protection package.  &amp;nbsp;Ubuntu server is also pretty well locked down by only allowing SSH  login with keys (i.e. no password auth allowed), and denying root the  ability to login. &amp;nbsp;I want to look more into other useful security  software / configs, but am pretty happy with security for now.&lt;/li&gt;&lt;li&gt;Web  server: installs nginx web server. &amp;nbsp;There&#39;s not much configured right  now, but I plan to put some basic web apps on to help manage the server  &amp;amp; communicate with devices.&lt;/li&gt;&lt;li&gt;SMTP email relay: installs  postfix mail transport and configures it to relay mail to an SMTP server  like gmail. &amp;nbsp;This is handy for allowing the server to send emails, like  from fail2ban warnings or perhaps notifications of MQTT events.  &amp;nbsp;Surprisingly this was by far the most complex package to automate with  Ansible, mostly because installing postfix requires answering some  question prompts which are difficult to do with automation.&lt;/li&gt;&lt;/ul&gt;One  more major package I want to install is a Python WSGI app server that  can host web applications written in Python. &amp;nbsp;I plan to make a few  simple web apps for reading and writing MQTT messages and would prefer  to write them in Python with the Flask web app framework. &amp;nbsp;I&#39;ve looked  into some options here and it looks like it comes down to either uWSGI  or Gunicorn. &amp;nbsp;From my testing uWSGI is kind of painful to setup so I  might go for Gunicorn.&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;                            &lt;h2&gt;&lt;a href=&quot;http://hackaday.io/project/1109/log/2650-service-architecture&quot;&gt;Service Architecture&lt;/a&gt;&lt;/h2&gt;&lt;div style=&quot;position: relative;&quot;&gt;&lt;div id=&quot;post-body-2650&quot;&gt;Here&#39;s a deeper look at the services for the DIY device cloud:&lt;br /&gt;&lt;img src=&quot;http://static.hackaday.io/images/805591400452899080.png&quot; height=&quot;494&quot; width=&quot;640&quot; /&gt;&lt;br /&gt;This  diagram shows a simple device cloud &#39;hello world&#39; application that  turns an LED on from a web page over the internet. &amp;nbsp;You can see in the  bottom left a web page which is hosted on the broker server. &amp;nbsp;When a  button is clicked (1) it communicates to a python web application which  is hosted by&amp;nbsp;&lt;a href=&quot;http://gunicorn.org/&quot;&gt;gunicorn&lt;/a&gt; (python WSGI web app server) and&amp;nbsp;&lt;a href=&quot;http://nginx.org/&quot;&gt;nginx&lt;/a&gt; (main web server). &amp;nbsp;That web application talks directly to the MQTT  broker on the server (2), which will inform any connected clients of  MQTT messages. &amp;nbsp;A device runs a device service which is just a simple  python script that talks to the broker (3) and turns on/off the LED with  GPIO libraries (4). &amp;nbsp;The device service is hosted by the excellent&amp;nbsp;&lt;a href=&quot;http://supervisord.org/&quot;&gt;supervisor&lt;/a&gt; tool so it will automatically run in the background on the device--all  the messy details about properly running a background process are  abstracted away by supervisor.&lt;br /&gt;This diagram highlights the two main extension points I see where you can plug in your own code to build your device cloud:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Web services, written as python WSGI applications (using a simple framework like&amp;nbsp;&lt;a href=&quot;http://flask.pocoo.org/&quot;&gt;flask&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;Device services, written as simple python scripts that are run automatically by supervisor.&lt;/li&gt;&lt;/ul&gt;The  ansible deployment scripts for both the broker server and devices take  care of setting up all the services, configuring them, etc. &amp;nbsp;You only  need to place your web service and device service code in a certain  location and follow a few simple conventions.&lt;br /&gt;I made a video of creating this simple hello world application and will post it shortly when Youtube is finished processing it.&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;                            &lt;h2&gt;&lt;a href=&quot;http://hackaday.io/project/1109/log/2657-device-cloud-hello-world&quot;&gt;Device Cloud Hello World&lt;/a&gt;&lt;/h2&gt;&lt;div style=&quot;position: relative;&quot;&gt;&lt;div id=&quot;post-body-2657&quot;&gt;This is a video of how to create a &#39;hello world&#39; for the device cloud--blinking an LED from a webpage over the internet: &lt;br /&gt;&lt;br /&gt;Source: &lt;a href=&quot;http://hackaday.io/project/1109/logs&quot;&gt;http://hackaday.io/project/1109/logs&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;</description><link>http://lifeeditor.blogspot.com/2015/01/diy-device-cloud.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-8676637504998743861</guid><pubDate>Wed, 28 Jan 2015 07:25:00 +0000</pubDate><atom:updated>2015-01-28T15:32:06.948+08:00</atom:updated><title>How To Use Celery with RabbitMQ to Queue Tasks on an Ubuntu VPS</title><description>&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;/h3&gt;Asynchronous, or non-blocking, processing is a method of separating  the execution of certain tasks from the main flow of a program.  This  provides you with several advantages, including allowing your  user-facing code to run without interruption.&lt;br /&gt;Message passing is a method which program components can use to  communicate and exchange information.  It can be implemented  synchronously or asynchronously and can allow discrete processes to  communicate without problems.  Message passing is often implemented as  an alternative to traditional databases for this type of usage because  message queues often implement additional features, provide increased  performance, and can reside completely in-memory.&lt;br /&gt;&lt;b&gt;Celery&lt;/b&gt; is a task queue that is built on an  asynchronous message passing system.  It can be used as a bucket where  programming tasks can be dumped.  The program that passed the task can  continue to execute and function responsively, and then later on, it can  poll celery to see if the computation is complete and retrieve the  data.&lt;br /&gt;While celery is written in Python, its protocol can be implemented in  any language.  It can even function with other languages through  webhooks.&lt;br /&gt;By implementing a job queue into your program&#39;s environment, you can  easily offload tasks and continue to handle interactions from your  users.  This is a simple way to increase the responsiveness of your  applications and not get locked up while performing long-running  computations.&lt;br /&gt;In this guide, we will install and implement a celery job queue using RabbitMQ as the messaging system on an Ubuntu 12.04 VPS.&lt;br /&gt;&lt;h2 id=&quot;install-the-components&quot;&gt;Install the Components&lt;/h2&gt;&lt;h3 id=&quot;install-celery&quot;&gt;Install Celery&lt;/h3&gt;Celery is written in Python, and as such, it is easy to install in the same way that we handle regular Python packages.&lt;br /&gt;We will follow the recommended procedures for handling Python  packages by creating a virtual environment to install our messaging  system.  This helps us keep our environment stable and not effect the  larger system.&lt;br /&gt;Install the Python virtual environment package from Ubuntu&#39;s default repositories:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;sudo apt-get update&lt;br /&gt;sudo apt-get install python-virtualenv&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;We will create a messaging directory where we will implement our system:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;mkdir ~/messaging&lt;br /&gt;cd ~/messaging&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;We can now create a virtual environment where we can install celery by using the following command:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;virtualenv --no-site-packages venv&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;With the virtual environment configured, we can activate it by typing:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;source venv/bin/activate&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Your prompt will change to reflect that you are now operating in the  virtual environment we made above.  This will ensure that our Python  packages are installed locally instead of globally.&lt;br /&gt;If at any time we need to deactivate the environment (not now), you can type:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;deactivate&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Now that we have activated the environment, we can install celery with pip:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;pip install celery&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;install-rabbitmq&quot;&gt;Install RabbitMQ&lt;/h3&gt;Celery requires a messaging agent in order to handle requests from an external source.  This agent is referred to as a &quot;broker&quot;.&lt;br /&gt;There are quite a few options for brokers available to choose from,  including relational databases, NoSQL databases, key-value stores, and  actual messaging systems.&lt;br /&gt;We will be configuring celery to use the RabbitMQ messaging system,  as it provides robust, stable performance and interacts well with  celery.  It is a great solution because it includes features that mesh  well with our intended use.&lt;br /&gt;We can install RabbitMQ through Ubuntu&#39;s repositories:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;sudo apt-get install rabbitmq-server&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The RabbitMQ service is started automatically on our server upon installation.&lt;br /&gt;&lt;h2 id=&quot;create-a-celery-instance&quot;&gt;Create a Celery Instance&lt;/h2&gt;In order to use celery&#39;s task queuing capabilities, our first step  after installation must be to create a celery instance.  This is a  simple process of importing the package, creating an &quot;app&quot;, and then  setting up the tasks that celery will be able to execute in the  background.&lt;br /&gt;Let&#39;s create a Python script inside our messaging directory called &lt;code&gt;tasks.py&lt;/code&gt; where we can define tasks that our workers can perform.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;sudo nano ~/messaging/tasks.py&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The first thing we should do is import the Celery function from the celery package:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;from celery import Celery&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;After that, we can create a celery application instance that connects to the default RabbitMQ service:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;from celery import Celery&lt;br /&gt;&lt;br /&gt;app = Celery(&#39;tasks&#39;, backend=&#39;amqp&#39;, broker=&#39;amqp://&#39;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The first argument to the &lt;code&gt;Celery&lt;/code&gt; function is the name that will be prepended to tasks to identify them.&lt;br /&gt;The &lt;code&gt;backend&lt;/code&gt; parameter is an optional parameter that is  necessary if you wish to query the status of a background task, or  retrieve its results.&lt;br /&gt;If your tasks are simply functions that do some work and then quit,  without returning a useful value to use in your program, you can leave  this parameter out.  If only some of your tasks require this  functionality, enable it here and we can disable it on a case-by-case  basis further on.&lt;br /&gt;The &lt;code&gt;broker&lt;/code&gt; parameter specifies the URL needed to connect  to our broker.  In our case, this is the RabbitMQ service that is  running on our server.  RabbitMQ operates using a protocol called  &quot;amqp&quot;.  If RabbitMQ is operating under its default configuration,  celery can connect with no other information other than the &lt;code&gt;amqp://&lt;/code&gt; scheme.&lt;br /&gt;&lt;h3 id=&quot;build-celery-tasks&quot;&gt;Build Celery Tasks&lt;/h3&gt;Still in this file, we now need to add our tasks.&lt;br /&gt;Each celery task must be introduced with the decorator &lt;code&gt;@app.task&lt;/code&gt;.   This allows celery to identify functions that it can add its queuing  functions to.  After each decorator, we simply create a function that  our workers can run.&lt;br /&gt;Our first task will be a simple function that prints out a string to console.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;from celery import Celery&lt;br /&gt;&lt;br /&gt;app = Celery(&#39;tasks&#39;, backend=&#39;amqp&#39;, broker=&#39;amqp://&#39;)&lt;br /&gt;&lt;br /&gt;@app.task&lt;br /&gt;def print_hello():&lt;br /&gt;    print &#39;hello there&#39;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Because this function does not return any useful information (it  instead prints it to the console), we can tell celery to not use the  backend to store state information about this task.  This is less  complicated under the hood and requires fewer resources.&lt;br /&gt;&lt;pre&gt;from celery import Celery&lt;br /&gt;&lt;br /&gt;app = Celery(&#39;tasks&#39;, backend=&#39;amqp&#39;, broker=&#39;amqp://&#39;)&lt;br /&gt;&lt;br /&gt;&lt;a class=&quot;username-tag&quot; href=&quot;https://www.digitalocean.com/community/users/app&quot;&gt;@app&lt;/a&gt;.task&lt;span class=&quot;highlight&quot;&gt;(ignore_result=True)&lt;/span&gt;&lt;br /&gt;def print_hello():&lt;br /&gt;    print &#39;hello there&#39;&lt;br /&gt;&lt;/pre&gt;Next, we will add another function that will generate prime numbers (taken from &lt;a href=&quot;http://rosettacode.org/wiki/Sieve_of_Eratosthenes&quot;&gt;RosettaCode&lt;/a&gt;).   This can be a long-running process, so it is a good example for how we  can deal with asynchronous worker processes when we are waiting for a  result.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;from celery import Celery&lt;br /&gt;&lt;br /&gt;app = Celery(&#39;tasks&#39;, backend=&#39;amqp&#39;, broker=&#39;amqp://&#39;)&lt;br /&gt;&lt;br /&gt;@app.task(ignore_result=True)&lt;br /&gt;def print_hello():&lt;br /&gt;    print &#39;hello there&#39;&lt;br /&gt;&lt;br /&gt;@app.task&lt;br /&gt;def gen_prime(x):&lt;br /&gt;    multiples = []&lt;br /&gt;    results = []&lt;br /&gt;    for i in xrange(2, x+1):&lt;br /&gt;        if i not in multiples:&lt;br /&gt;            results.append(i)&lt;br /&gt;            for j in xrange(i*i, x+1, i):&lt;br /&gt;                multiples.append(j)&lt;br /&gt;    return results&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Because we care about what the return value of this function is, and  because we want to know when it has completed (so that we may use the  results, etc), we do not add the &lt;code&gt;ignore_result&lt;/code&gt; parameter to this second task.&lt;br /&gt;Save and close the file.&lt;br /&gt;&lt;h2 id=&quot;start-celery-worker-processes&quot;&gt;Start Celery Worker Processes&lt;/h2&gt;We can now start a worker processes that will be able to accept  connections from applications.  It will use the file we just created to  learn about the tasks it can perform.&lt;br /&gt;Starting a worker instance is as easy as calling out the application  name with the celery command.  We will include a &quot;&amp;amp;&quot; character at  the end of our string to put our worker process in the background:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;celery worker -A tasks &amp;amp;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;This will start up an application, and then detach it from the terminal, allowing you to continue to use it for other tasks.&lt;br /&gt;If you want to start multiple workers, you can do so by naming each one with the &lt;code&gt;-n&lt;/code&gt; argument:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;celery worker -A tasks -n one.%h &amp;amp;&lt;br /&gt;celery worker -A tasks -n two.%h &amp;amp;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The &lt;code&gt;%h&lt;/code&gt; will be replaced by the hostname when the worker is named.&lt;br /&gt;To stop workers, you can use the kill command.  We can query for the  process id and then eliminate the workers based on this information.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;ps auxww | grep &#39;celery worker&#39; | awk &#39;{print $2}&#39; | xargs kill&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;This will allow the worker to complete its current task before exiting.&lt;br /&gt;If you wish to shut down all workers without waiting for them to complete their tasks, you can execute:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;ps auxww | grep &#39;celery worker&#39; | awk &#39;{print $2}&#39; | xargs kill -9&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;use-the-queue-to-handle-work&quot;&gt;Use the Queue to Handle Work&lt;/h2&gt;We can use the worker process(es) we spawned to complete work in the background for our programs.&lt;br /&gt;Instead of creating an entire program to demonstrate how this works,  we will explore the different options in a Python interpreter:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;python&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;At the prompt, we can import our functions into the environment:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;from tasks import print_hello&lt;br /&gt;from tasks import gen_prime&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;If you test these functions, they appear to not have any special functionality.  The first function prints a line as expected:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;print_hello()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;hello there&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The second function returns a list of prime numbers:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;primes = gen_prime(1000)&lt;br /&gt;print primes&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;If we give the second function a larger range of numbers to check, the execution hangs while it calculates:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;primes = gen_prime(50000)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Stop the execution by typing &quot;CTRL-C&quot;.  This process is clearly not computing in the background.&lt;br /&gt;To access the background worker, we need to use the &lt;code&gt;.delay&lt;/code&gt; method.  Celery wraps our functions with additional capabilities.  This  method is used to pass the function to a worker to execute.  It should  return immediately:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;primes = gen_prime.delay(50000)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;This task is now being executed by the workers we started earlier.  Because we configured a &lt;code&gt;backend&lt;/code&gt; parameter for our application, we can check the status of the computation and get access to the result.&lt;br /&gt;To check whether the task is complete, we can use the &lt;code&gt;.ready&lt;/code&gt; method:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;primes.ready()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;False&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;A value of &quot;False&quot; means that the task is still running and a result  is not available yet.  When we get a value of &quot;True&quot;, we can do  something with the answer.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;primes.ready()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;True&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;We can get the value by using the &lt;code&gt;.get&lt;/code&gt; method.&lt;br /&gt;If we have already verified that the value is computed with the &lt;code&gt;.ready&lt;/code&gt; method, then we can use that method like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;print primes.get()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79,&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167,&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263,&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367,&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;467, 479, 487, 491, 499, 503, 509, 521, 523, . . .&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;If, however, you have not used the &lt;code&gt;.ready&lt;/code&gt; method prior to calling &lt;code&gt;.get&lt;/code&gt;,  you most likely want to add a &quot;timeout&quot; option so that your program  isn&#39;t forced to wait for the result, which would defeat the purpose of  our implementation:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;print primes.get(timeout=2)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;This will raise an exception if it times out, which you can handle in your program.&lt;br /&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;Although this is enough information to get you started on using  celery within your programs, it is only scratching the surface on the  full functionality of this library.  Celery allows you to string  background tasks together, group tasks, and combine functions in  interesting ways.&lt;br /&gt;Although celery is written in Python, it can be used with other  languages through webhooks.  This makes it incredibly flexible for  moving tasks into the background, regardless of your chosen language.&lt;br /&gt;&lt;br /&gt;Source: &lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-use-celery-with-rabbitmq-to-queue-tasks-on-an-ubuntu-vps&quot; target=&quot;_blank&quot;&gt;https://www.digitalocean.com/community/tutorials/how-to-use-celery-with-rabbitmq-to-queue-tasks-on-an-ubuntu-vps &lt;/a&gt;</description><link>http://lifeeditor.blogspot.com/2015/01/how-to-use-celery-with-rabbitmq-to.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-7650387132652010093</guid><pubDate>Wed, 28 Jan 2015 07:24:00 +0000</pubDate><atom:updated>2015-01-28T15:33:57.314+08:00</atom:updated><title>Creating a browser based EmonHub log console using python, flask, socketio, MQTT</title><description>Written in Python using the flask web framework this example  subscribes to a MQTT topic to which logs are posted from emonhub and  pushes messages up to the browser using socket.io. The results are  displayed in a html box that looks like a ubuntu linux terminal window.  The example includes basic session based authentication with a hardcoded  username and password see app.py.&lt;br /&gt;Username: demo, password: demo&lt;br /&gt;Being able to view the emonhub log from a browser rather than having to login via SSH could make debugging more convenient.&lt;br /&gt;&lt;a href=&quot;https://github.com/emoncms/development/blob/master/Tutorials/Python/socketiowebconsole/docs/emonhubweb.png&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;pythonwebconsole.png&quot; src=&quot;https://github.com/emoncms/development/raw/master/Tutorials/Python/socketiowebconsole/docs/emonhubweb.png&quot; style=&quot;max-width: 100%;&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h1&gt;Install&lt;/h1&gt;&lt;pre&gt;&lt;code&gt;sudo pip install Flask&lt;br /&gt;sudo pip install Flask-SocketIO&lt;br /&gt;sudo pip install mosquitto&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Installation of Flask-SocketIO can be slow on a raspberrypi.&lt;br /&gt;see: &lt;a href=&quot;https://flask-socketio.readthedocs.org/en/latest/&quot;&gt;https://flask-socketio.readthedocs.org/en/latest/&lt;/a&gt;&lt;br /&gt;Code is based on the flask-socketio example&lt;br /&gt;&lt;h3&gt;Changes to emonhub&lt;/h3&gt;In emonhub.py:&lt;br /&gt;In the import section at the top add:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;import mosquitto&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Just below the import section add:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;mqttc = mosquitto.Mosquitto()&lt;br /&gt;mqttc.connect(&quot;127.0.0.1&quot;,1883, 60, True)&lt;br /&gt;&lt;br /&gt;class MQTTLogHandler(logging.Handler):&lt;br /&gt;    def emit(self, record):        &lt;br /&gt;        mqttc.publish(&quot;log&quot;,record.asctime+&quot; &quot;+record.levelname+&quot; &quot;+record.message)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Lower down, just below the line (line 324):&lt;br /&gt;&lt;pre&gt;&lt;code&gt;logger.addHandler(loghandler)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;add:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;mqttloghandler = MQTTLogHandler()&lt;br /&gt;logger.addHandler(mqttloghandler)&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;Source: &amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;&lt;a href=&quot;https://github.com/emoncms/development/tree/master/Tutorials/Python/socketiowebconsole&quot; target=&quot;_blank&quot;&gt;https://github.com/emoncms/development/tree/master/Tutorials/Python/socketiowebconsole &lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;</description><link>http://lifeeditor.blogspot.com/2015/01/creating-browser-based-emonhub-log.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-5641259042379636408</guid><pubDate>Sun, 11 Jan 2015 09:29:00 +0000</pubDate><atom:updated>2015-01-11T17:29:07.246+08:00</atom:updated><title>Web Scraping With Scrapy and MongoDB</title><description>&lt;br /&gt;&lt;div class=&quot;center-text&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; text-align: center;&quot;&gt;&lt;img alt=&quot;scrapy&quot; class=&quot;no-border&quot; src=&quot;https://realpython.com/images/blog_images/scraping-with-scrapy-and-mongo/scrapy.png&quot; style=&quot;border: 0px; box-sizing: border-box; height: auto; max-width: 600px; vertical-align: middle;&quot; /&gt;&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;strong style=&quot;box-sizing: border-box;&quot;&gt;In this article we’re going to build a scraper for an&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;actual&lt;/em&gt;&amp;nbsp;freelance gig where the client wants a Python program to scrape data from&amp;nbsp;&lt;a href=&quot;http://stackoverflow.com/questions?pagesize=50&amp;amp;sort=newest&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Stack Overflow&lt;/a&gt;&amp;nbsp;to grab new questions (question title and URL). Scraped data should then be stored in&amp;nbsp;&lt;a href=&quot;http://www.mongodb.org/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;MongoDB&lt;/a&gt;.&lt;/strong&gt;&amp;nbsp;It’s worth noting that Stack Overflow has an&amp;nbsp;&lt;a href=&quot;https://api.stackexchange.com/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;API&lt;/a&gt;, which can be used to access the&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;exact&lt;/em&gt;&amp;nbsp;same data. However, the client wanted a scraper, so a scraper is what he got.&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;strong style=&quot;box-sizing: border-box;&quot;&gt;Updated on 01/03/2014 – refactored spider. Thanks,&amp;nbsp;&lt;a href=&quot;https://twitter.com/kissgyorgy&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;@kissgyorgy&lt;/a&gt;&lt;/strong&gt;.&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;blockquote style=&quot;background-color: white; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; box-sizing: border-box; color: #6f6f6f; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 18.75px; margin: 0px 0px 21px; padding: 10.5px 21px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box;&quot;&gt;As always, be sure to review the site’s terms of use/service and respect the&lt;em style=&quot;box-sizing: border-box;&quot;&gt;robots.txt&lt;/em&gt;&amp;nbsp;file before starting any scraping job. Make sure to adhere to ethical scraping practices by not flooding the site with numerous requests over a short span of time.&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;Treat any site you scrape as if it were your own&lt;/em&gt;.&lt;/div&gt;&lt;/blockquote&gt;&lt;h2 id=&quot;installation&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Installation&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;We need the&amp;nbsp;&lt;a href=&quot;http://doc.scrapy.org/en/latest/index.html&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Scrapy&lt;/a&gt;&amp;nbsp;library (v0.24.4) along with&amp;nbsp;&lt;a href=&quot;http://api.mongodb.org/python/current/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;PyMongo&lt;/a&gt;&amp;nbsp;(v2.7.2) for storing the data in MongoDB. You need to install&amp;nbsp;&lt;a href=&quot;http://docs.mongodb.org/manual/installation/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;MongoDB&lt;/a&gt;&amp;nbsp;as well (not covered).&lt;/div&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Scrapy&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;If you’re running OSX or a flavor of Linux, install Scrapy with pip (with your virtualenv activated):&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 191.33332824707px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;pip install Scrapy&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;If you are on Windows machine, you will need to manually install a number of dependencies. Please refer to the&amp;nbsp;&lt;a href=&quot;http://doc.scrapy.org/en/latest/intro/install.html&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;official documentation&lt;/a&gt;&amp;nbsp;for detailed instructions as well as&amp;nbsp;&lt;a href=&quot;https://www.youtube.com/watch?v=eEK2kmmvIdw&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;this Youtube video&lt;/a&gt;that I created.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Once Scrapy is setup, verify your installation by running this command in the Python shell:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 166px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import scrapy&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;If you don’t get an error then you are good to go!&lt;/div&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;PyMongo&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Next, install PyMongo with pip:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 200px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;pip install pymongo&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Now we can start building the crawler.&lt;/div&gt;&lt;h2 id=&quot;scrapy-project&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Scrapy Project&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Let’s start a new Scrapy project:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 250.66667175293px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;scrapy startproject stack&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;This creates a number of files and folders that includes a basic boilerplate for you to get started quickly:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 216.66667175293px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;├── scrapy.cfg&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;└── stack&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    ├── __init__.py&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    ├── items.py&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    ├── pipelines.py&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    ├── settings.py&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    └── spiders&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        └── __init__.py&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Specify Data&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;The&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;items.py&lt;/em&gt;&amp;nbsp;file is used to define storage “containers” for the data that we plan to scrape.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;The&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;StackItem()&lt;/code&gt;&amp;nbsp;class inherits from&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;Item&lt;/code&gt;&amp;nbsp;(&lt;a href=&quot;http://doc.scrapy.org/en/latest/topics/items.html&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;docs&lt;/a&gt;), which basically has a number of pre-defined objects that Scrapy has already built for us:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 427.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;box-sizing: border-box; color: rgb(211, 54, 130) !important;&quot;&gt;StackItem&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;scrapy&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: rgb(147, 161, 161) !important; font-style: italic !important;&quot;&gt;# define the fields for your item here like:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: rgb(147, 161, 161) !important; font-style: italic !important;&quot;&gt;# name = scrapy.Field()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;pass&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Let’s add some items that we actually want to collect. For each question the client needs the title and URL. So, update&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;items.py&lt;/em&gt;&amp;nbsp;like so:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 318px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy.item&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Field&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;box-sizing: border-box; color: rgb(211, 54, 130) !important;&quot;&gt;StackItem&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Create the Spider&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Create a file called&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;stack_spider.py&lt;/em&gt;&amp;nbsp;in the “spiders” directory. This is where the magic happens – e.g., where we’ll tell Scrapy how to find the&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;exact&lt;/em&gt;&amp;nbsp;data we’re looking for. As you can imagine, this is&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;specific&lt;/em&gt;&amp;nbsp;to each individual web page.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Start by defining a class that inherits from Scrapy’s&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;Spider&lt;/code&gt;&amp;nbsp;and then adding attributes as needed:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 604.666687011719px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Spider&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;box-sizing: border-box; color: rgb(211, 54, 130) !important;&quot;&gt;StackSpider&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Spider&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;stack&quot;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;allowed_domains&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;stackoverflow.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;start_urls&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;http://stackoverflow.com/questions?pagesize=50&amp;amp;sort=newest&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;The first few variables are self-explanatory (&lt;a href=&quot;http://doc.scrapy.org/en/latest/topics/spiders.html#spider&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;docs&lt;/a&gt;):&lt;/div&gt;&lt;ul style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px; margin-top: 0px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;name&lt;/code&gt;&amp;nbsp;defines the name of the Spider.&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;allowed_domains&lt;/code&gt;&amp;nbsp;contains the base-URLs for the allowed domains for the spider to crawl.&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;start_urls&lt;/code&gt;&amp;nbsp;is a list of URLs for the spider to start crawling from. All subsequent URLs will start from the data that the spider downloads from the URLS in&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;start_urls&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;XPath Selectors&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Next, Scrapy uses XPath selectors to extract data from a website. In other words, we can select certain parts of the HTML data based on a given XPath. As stated in Scrapy’s&amp;nbsp;&lt;a href=&quot;http://doc.scrapy.org/en/latest/topics/selectors.html&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;documentation&lt;/a&gt;, “XPath is a language for selecting nodes in XML documents, which can also be used with HTML.”&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;You can easily find a specific Xpath using Chrome’s Developer Tools. Simply inspect a specific HTML element, copy the XPath, and then tweak (as needed):&lt;/div&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Installation&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Scrapy&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;PyMongo&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Scrapy.Project&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Specify.Data&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Create.the.Spider&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;XPath.Selectors&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div class=&quot;center-text&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; text-align: center;&quot;&gt;&lt;img alt=&quot;copy xpath in chrome developer tools&quot; class=&quot;no-border&quot; src=&quot;https://realpython.com/images/blog_images/scraping-with-scrapy-and-mongo/chrome_copy_xpath.png&quot; style=&quot;border: 0px; box-sizing: border-box; height: auto; max-width: 600px; vertical-align: middle;&quot; /&gt;&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Developer Tools also gives you the ability to test XPath selectors in the JavaScript Console by using&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;$x&lt;/code&gt;&amp;nbsp;– i.e.,&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;$x(&quot;//img&quot;)&lt;/code&gt;:&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div class=&quot;center-text&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; text-align: center;&quot;&gt;&lt;img alt=&quot;test xpath in chrome developer tools&quot; class=&quot;no-border&quot; src=&quot;https://realpython.com/images/blog_images/scraping-with-scrapy-and-mongo/chrome_text_xpath.png&quot; style=&quot;border: 0px; box-sizing: border-box; height: auto; max-width: 600px; vertical-align: middle;&quot; /&gt;&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Again, we basically tell Scrapy where to start looking for information based on a defined XPath. Let’s navigate to the&amp;nbsp;&lt;a href=&quot;http://stackoverflow.com/questions?pagesize=50&amp;amp;sort=newest&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Stack Overflow&lt;/a&gt;&amp;nbsp;site in Chrome and find the XPath selectors.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Right click on the first question and select “Inspect Element”:&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div class=&quot;center-text&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; text-align: center;&quot;&gt;&lt;img alt=&quot;inspect element in chrome developer tools&quot; class=&quot;no-border&quot; src=&quot;https://realpython.com/images/blog_images/scraping-with-scrapy-and-mongo/stack_source_inspect_element.png&quot; style=&quot;border: 0px; box-sizing: border-box; height: auto; max-width: 600px; vertical-align: middle;&quot; /&gt;&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Now grab the XPath for the&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;&amp;lt;div class=&quot;summary&quot;&amp;gt;&lt;/code&gt;,&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;//*[@id=&quot;question-summary-27624141&quot;]/div[2]&lt;/code&gt;, and then test it out in the JavaScript Console:&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div class=&quot;center-text&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; text-align: center;&quot;&gt;&lt;img alt=&quot;test xpath in chrome developer tools&quot; class=&quot;no-border&quot; src=&quot;https://realpython.com/images/blog_images/scraping-with-scrapy-and-mongo/stack_source_test_xpath.png&quot; style=&quot;border: 0px; box-sizing: border-box; height: auto; max-width: 600px; vertical-align: middle;&quot; /&gt;&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;As you can tell, it just selects that&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;one&lt;/em&gt;&amp;nbsp;question. So we need to alter the XPath to grab&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;all&lt;/em&gt;questions. Any ideas? It’s simple:&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;//div[@class=&quot;summary&quot;]/h3&lt;/code&gt;. What does this mean? Essentially, this XPath states:&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;Grab all&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;&amp;lt;h3&amp;gt;&lt;/code&gt;&amp;nbsp;elements that are children of a&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;&amp;lt;div&amp;gt;&lt;/code&gt;&amp;nbsp;that has a class of&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;summary&lt;/code&gt;&lt;/em&gt;. Test this XPath out in the JavaScript Console.&lt;/div&gt;&lt;blockquote style=&quot;background-color: white; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; box-sizing: border-box; color: #6f6f6f; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 18.75px; margin: 0px 0px 21px; padding: 10.5px 21px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box;&quot;&gt;Notice how we are not using the actual XPath output from Chrome Developer Tools. In most cases, the output is just a helpful aside, which generally points you in the right direction for finding the working XPath.&lt;/div&gt;&lt;/blockquote&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Now let’s update the&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;stack_spider.py&lt;/em&gt;&amp;nbsp;script:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 647.333312988281px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Spider&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy.selector&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Selector&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;box-sizing: border-box; color: rgb(211, 54, 130) !important;&quot;&gt;StackSpider&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Spider&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;stack&quot;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;allowed_domains&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;stackoverflow.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;start_urls&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;http://stackoverflow.com/questions?pagesize=50&amp;amp;sort=newest&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;questions&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Selector&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;xpath&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;//div[@class=&quot;summary&quot;]/h3&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Extract the Data&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;We still need to parse and scrape the data we want, which falls within&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;&amp;lt;div class=&quot;summary&quot;&amp;gt;&amp;lt;h3&amp;gt;&lt;/code&gt;. Again, update&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;stack_spider.py&lt;/em&gt;&amp;nbsp;like so:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 647.333312988281px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Spider&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy.selector&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Selector&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;stack.items&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;StackItem&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;box-sizing: border-box; color: rgb(211, 54, 130) !important;&quot;&gt;StackSpider&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Spider&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;stack&quot;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;allowed_domains&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;stackoverflow.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;start_urls&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;http://stackoverflow.com/questions?pagesize=50&amp;amp;sort=newest&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;questions&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Selector&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;xpath&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;//div[@class=&quot;summary&quot;]/h3&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;question&lt;/span&gt; &lt;span class=&quot;ow&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important; font-weight: bold !important;&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;questions&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;StackItem&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;title&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;question&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;xpath&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;                &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;a[@class=&quot;question-hyperlink&quot;]/text()&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;extract&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;url&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;question&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;xpath&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;                &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;a[@class=&quot;question-hyperlink&quot;]/@href&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;extract&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;item&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;`&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;We are iterating through the&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;questions&lt;/code&gt;&amp;nbsp;and assigning the&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;title&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;url&lt;/code&gt;&amp;nbsp;values from the scraped data. Be sure to test out the XPath selectors in the JavaScript Console within Chrome Developer Tools – e.g.,&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;$x(&#39;//div[@class=&quot;summary&quot;]/h3/a[@class=&quot;question-hyperlink&quot;]/text()&#39;)&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;$x(&#39;//div[@class=&quot;summary&quot;]/h3/a[@class=&quot;question-hyperlink&quot;]/@href&#39;)&lt;/code&gt;.&lt;/div&gt;&lt;h2 id=&quot;test&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Test&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Ready for the first test? Simply run the following command within the “stack” directory:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 191.33332824707px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;scrapy crawl stack&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Along with the Scrapy stack trace, you should see 50 question titles and URLs outputted. You can render the output to a JSON file with this little command:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 377.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;scrapy crawl stack -o items.json -t json&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;We’ve now implemented our Spider based on our data that we are seeking. Now we need to store the scraped data within MongoDB.&lt;/div&gt;&lt;h2 id=&quot;store-the-data-in-mongodb&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Store the Data in MongoDB&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Each time an item is returned, we want to validate the data and then add it to a Mongo collection.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;The initial step is to create the database that we plan to use to save all of our crawled data. Open&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;settings.py&lt;/em&gt;&amp;nbsp;and specify the&amp;nbsp;&lt;a href=&quot;http://doc.scrapy.org/en/latest/topics/item-pipeline.html&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;pipeline&lt;/a&gt;&amp;nbsp;and add the database settings:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 478.666656494141px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;ITEM_PIPELINES&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;stack.pipelines.MongoDBPipeline&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;MONGODB_SERVER&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;localhost&quot;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;MONGODB_PORT&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;27017&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;MONGODB_DB&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;stackoverflow&quot;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;MONGODB_COLLECTION&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;questions&quot;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Pipeline Management&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;We’ve setup our spider to crawl and parse the HTML, and we’ve set up our database settings. Now we have to connect the two together through a pipeline in&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;pipelines.py&lt;/em&gt;.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;strong style=&quot;box-sizing: border-box;&quot;&gt;Connect to Database&lt;/strong&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;First, let’s define a method to actually connect to the database:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 529.333312988281px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;pymongo&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy.conf&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;box-sizing: border-box; color: rgb(211, 54, 130) !important;&quot;&gt;MongoDBPipeline&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;connection&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;pymongo&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;MONGODB_SERVER&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;],&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;MONGODB_PORT&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;MONGODB_DB&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;collection&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;MONGODB_COLLECTION&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Here, we create a class,&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;MongoDBPipeline()&lt;/code&gt;, and we have a constructor function to initialize the class by defining the Mongo settings and then connecting to the database.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;strong style=&quot;box-sizing: border-box;&quot;&gt;Process the Data&lt;/strong&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Next, we need to define a method to process the parsed data:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 529.333312988281px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;pymongo&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy.conf&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy.exceptions&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;DropItem&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;scrapy&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;log&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot; style=&quot;box-sizing: border-box; color: rgb(211, 54, 130) !important;&quot;&gt;MongoDBPipeline&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;connection&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;pymongo&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;MONGODB_SERVER&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;],&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;MONGODB_PORT&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;MONGODB_DB&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;collection&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;settings&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;MONGODB_COLLECTION&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;process_item&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;spider&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;valid&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;True&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;ow&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important; font-weight: bold !important;&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important; font-weight: bold !important;&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;                &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;valid&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;False&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;                &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;DropItem&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Missing {0}!&quot;&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;valid&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box;&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;collection&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;insert&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;))&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Question added to MongoDB database!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;                    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;spider&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;spider&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;item&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;We establish a connection to the database, unpack the data, and then save it to the database. Now we can test again!&lt;/div&gt;&lt;h2 id=&quot;test&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Test&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Again, run the following command within the “stack” directory:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 191.33332824707px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;scrapy crawl stack&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Hooray! We have successfully stored our crawled data into the database:&lt;/div&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Extract.the.Data&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Test&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Store.the.Data.in.MongoDB&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Pipeline.Management&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Test&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;div class=&quot;center-text&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; text-align: center;&quot;&gt;&lt;img alt=&quot;robomongo&quot; class=&quot;no-border&quot; src=&quot;https://realpython.com/images/blog_images/scraping-with-scrapy-and-mongo/robomongo.png&quot; style=&quot;border: 0px; box-sizing: border-box; height: auto; max-width: 600px; vertical-align: middle;&quot; /&gt;&lt;/div&gt;&lt;br style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot; /&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Conclusion&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;h2 id=&quot;conclusion&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Conclusion&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;This is a pretty simple example of using Scrapy to crawl and scrape a web page. The actual freelance project required the script to follow the pagination links and scrape each page using the&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;CrawlSpider&lt;/code&gt;&amp;nbsp;(&lt;a href=&quot;http://doc.scrapy.org/en/latest/topics/spiders.html#crawlspider&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;docs&lt;/a&gt;), which is super easy to implement. Try implementing this on your own, and leave a comment below with the link to the Github repository for a quick code review. Need help? Start with&amp;nbsp;&lt;a href=&quot;https://github.com/realpython/stack-spider/blob/master/stack/stack/spiders/stack_crawl.py&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;this script&lt;/a&gt;, which is nearly complete. Cheers!&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;You can download the entire source code from the&amp;nbsp;&lt;a href=&quot;https://github.com/realpython/stack-spider&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Github repository&lt;/a&gt;. Comment below with questions. Thanks for Reading!&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Source:&amp;nbsp;&lt;a href=&quot;https://realpython.com/blog/python/web-scraping-with-scrapy-and-mongodb/?utm_source=Python+Weekly+Newsletter&amp;amp;utm_campaign=3387594e10-Python_Weekly_Issue_172_January_1_2015&amp;amp;utm_medium=email&amp;amp;utm_term=0_9e26887fc5-3387594e10-312723701&quot;&gt;https://realpython.com/blog/python/web-scraping-with-scrapy-and-mongodb/?utm_source=Python+Weekly+Newsletter&amp;amp;utm_campaign=3387594e10-Python_Weekly_Issue_172_January_1_2015&amp;amp;utm_medium=email&amp;amp;utm_term=0_9e26887fc5-3387594e10-312723701&lt;/a&gt;&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2015/01/web-scraping-with-scrapy-and-mongodb.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-4329584727272188182</guid><pubDate>Sun, 11 Jan 2015 09:24:00 +0000</pubDate><atom:updated>2015-01-11T17:24:32.441+08:00</atom:updated><title>Web Scraping - It’s Your Civic Duty</title><description>&lt;div class=&quot;content-body&quot; itemprop=&quot;text articleBody&quot; style=&quot;box-sizing: border-box; color: #333333; font-family: &#39;Average Sans&#39;, sans-serif; font-size: 16px; line-height: 26px;&quot;&gt;&lt;div class=&quot;section&quot; id=&quot;introduction&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;h2 style=&quot;box-sizing: border-box; color: inherit; font-family: inherit; font-size: 30px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 20px;&quot;&gt;Introduction&lt;/h2&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;More and more information from local, state and federal governments is being placed on the web. However, a lot of the data is not presented in a way that is easy to download and manipulate. I think it is an important civic duty for us all to be aware of how government money is spent. Having the data in a more accessible format is a first step in that&amp;nbsp;process.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;In this article, I’ll use&amp;nbsp;&lt;a class=&quot;reference external&quot; href=&quot;http://www.crummy.com/software/BeautifulSoup/&quot; style=&quot;box-sizing: border-box; color: #337ab7; text-decoration: none;&quot;&gt;BeautifulSoup&lt;/a&gt;&amp;nbsp;to scrape some data from the Minnesota 2014 Capital Budget. Then I’ll load the data into a pandas&amp;nbsp;&lt;a class=&quot;reference external&quot; href=&quot;http://pandas.pydata.org/pandas-docs/dev/generated/pandas.DataFrame.html&quot; style=&quot;box-sizing: border-box; color: #337ab7; text-decoration: none;&quot;&gt;DataFrame&lt;/a&gt;&amp;nbsp;and create a simple plot showing where the money is&amp;nbsp;going.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;My purpose in writing this is not to make any specific political statements about this data set. I chose this data&amp;nbsp;because:&lt;/div&gt;&lt;ul class=&quot;simple&quot; style=&quot;box-sizing: border-box; margin-bottom: 10px; margin-top: 0px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;I personally found it&amp;nbsp;interesting&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;I think it translates well across other states and across the&amp;nbsp;world&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;It highlights several useful python tools both in and outside of the&amp;nbsp;stdlib&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;The process is applicable to other domains outside of government&amp;nbsp;data&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;It is a manageable size so you can understand it using basic&amp;nbsp;tools&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class=&quot;section&quot; id=&quot;the-data&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;h2 style=&quot;box-sizing: border-box; color: inherit; font-family: inherit; font-size: 30px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 20px;&quot;&gt;The&amp;nbsp;Data&lt;/h2&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;I live in&amp;nbsp;&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;MN&lt;/span&gt;&amp;nbsp;so thought I would take a look at what sort of budget information is available to us via the various state websites. To be honest, there is a lot of information but it seems like the vast majority is stored in a&amp;nbsp;&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;PDF&lt;/span&gt;&amp;nbsp;or on an&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;HTML&lt;/span&gt;&amp;nbsp;page.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;I applaud the state for making the data available but it is not easy to analyze the data in the way it is currently presented. As I looked through the Minnesota government website, I found this&amp;nbsp;&lt;a class=&quot;reference external&quot; href=&quot;https://www.revisor.mn.gov/laws/?year=2014&amp;amp;type=0&amp;amp;doctype=Chapter&amp;amp;id=294&quot; style=&quot;box-sizing: border-box; color: #337ab7; text-decoration: none;&quot;&gt;2014 Capital Budget page&lt;/a&gt;&amp;nbsp;which is actually pretty straightforward to&amp;nbsp;understand.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;The first part of the document contains a high level summary of all the projects receiving capital dollars as well as how the capital budget will be&amp;nbsp;funded.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;The second part of the document has a lot of detail on each of the summary items. For the purpose of this exercise, I am only going to scrape the summary section but the same basic principle can be applied to the detailed line&amp;nbsp;items.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;One final note, I realize that this data set is not that large and that you could easily type it all into Excel. However, if we were to scale this to pull in more data, you quickly get to the point where hand typing the data just does not make sense. The principles I walk through will scale to much larger sets. I hope it has the added bonus that you will learn something as well. I know I enjoyed working on this little&amp;nbsp;project.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;section&quot; id=&quot;the-tools&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;h2 style=&quot;box-sizing: border-box; color: inherit; font-family: inherit; font-size: 30px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 20px;&quot;&gt;The&amp;nbsp;Tools&lt;/h2&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;For this particular task, I am going to use 2 very common python tools for scraping the&amp;nbsp;site:&lt;/div&gt;&lt;ul class=&quot;simple&quot; style=&quot;box-sizing: border-box; margin-bottom: 10px; margin-top: 0px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;&lt;a class=&quot;reference external&quot; href=&quot;http://www.crummy.com/software/BeautifulSoup/&quot; style=&quot;box-sizing: border-box; color: #337ab7; text-decoration: none;&quot;&gt;BeautifulSoup&lt;/a&gt;&amp;nbsp;to parse the&amp;nbsp;data&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;&lt;a class=&quot;reference external&quot; href=&quot;http://docs.python-requests.org/en/latest/&quot; style=&quot;box-sizing: border-box; color: #337ab7; text-decoration: none;&quot;&gt;Requests&lt;/a&gt;&amp;nbsp;to get the data from the&amp;nbsp;website.&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Strictly speaking, Requests is not being used for much in this case but I think it makes sense to start using it. If/when you start getting more complicated situations, you’ll be happy you are already using&amp;nbsp;it.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;&lt;a class=&quot;reference external&quot; href=&quot;http://scrapy.org/&quot; style=&quot;box-sizing: border-box; color: #337ab7; text-decoration: none;&quot;&gt;Scrapy&lt;/a&gt;&amp;nbsp;is another powerful tool for doing web scraping but for my needs BeautifulSoup was perfect so that’s what I’m sticking with for this article. Maybe I’ll look at it for a future&amp;nbsp;article.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Once I scrape the data, I’ll convert it to a pandas&amp;nbsp;&lt;a class=&quot;reference external&quot; href=&quot;http://pandas.pydata.org/pandas-docs/dev/generated/pandas.DataFrame.html&quot; style=&quot;box-sizing: border-box; color: #337ab7; text-decoration: none;&quot;&gt;DataFrame&lt;/a&gt;&amp;nbsp;so that I can analyze and plot the&amp;nbsp;data.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;One final note, I’m trying to use idiomatic python as much as possible. My current environment is python 2.7 but I’ll use the&lt;code class=&quot;code&quot; style=&quot;background-color: #f9f2f4; border-radius: 4px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.3999996185303px; padding: 2px 4px;&quot;&gt;print_function&lt;/code&gt;&amp;nbsp;to make the python 3 conversion much easier. Also, I’m going to use the&amp;nbsp;&lt;code class=&quot;code&quot; style=&quot;background-color: #f9f2f4; border-radius: 4px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.3999996185303px; padding: 2px 4px;&quot;&gt;defaultdict&lt;/code&gt;&amp;nbsp;to streamline the processing of the data. This was first introduced in python 2.5 and is pretty handy when working with dictionaries where the values are&amp;nbsp;lists.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;section&quot; id=&quot;start-the-process&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;h2 style=&quot;box-sizing: border-box; color: inherit; font-family: inherit; font-size: 30px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 20px;&quot;&gt;Start the&amp;nbsp;Process&lt;/h2&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Import all the modules we&amp;nbsp;need:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;__future__&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;print_function&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;os.path&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;collections&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;defaultdict&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;string&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;requests&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;bs4&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;BeautifulSoup&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;pd&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;np&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;plt&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Now we need to initialize the variables. I’m going to use two dictionaries. One will store all of the expense items and the other will include the funding source. Note, I am not going to store the total. We can calculate it so we’ll skip that piece of data. I am using the&amp;nbsp;&lt;code class=&quot;code&quot; style=&quot;background-color: #f9f2f4; border-radius: 4px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.3999996185303px; padding: 2px 4px;&quot;&gt;defaultdict&lt;/code&gt;&amp;nbsp;to make it easy to append the values I&amp;nbsp;scrape:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;https://www.revisor.mn.gov/laws/?year=2014&amp;amp;type=0&amp;amp;doctype=Chapter&amp;amp;id=294&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Init the variables&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Use a defaultdict with an empty list because it eases the DataFrame creation&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_lines&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;defaultdict&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_lines&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;defaultdict&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;False&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Use requests to get the data and pass it to BeautifulSoup. In my final script, I’m going to store the&amp;nbsp;&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;HTML&lt;/span&gt;&amp;nbsp;to disk so that I don’t need to hit the website every time I run it. I won’t show it in this section in order to keep the code&amp;nbsp;short.&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;content&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Now that we have the data, let&#39;s process it&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;soup&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;BeautifulSoup&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;section&quot; id=&quot;understand-your-html&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;h2 style=&quot;box-sizing: border-box; color: inherit; font-family: inherit; font-size: 30px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 20px;&quot;&gt;Understand Your&amp;nbsp;&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;HTML&lt;/span&gt;&lt;/h2&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;The key to understanding any scraping is looking at the&amp;nbsp;&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;HTML&lt;/span&gt;&amp;nbsp;and understanding how you want to pull your data&amp;nbsp;out.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;In this case, I downloaded the&amp;nbsp;&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;HTML&lt;/span&gt;&amp;nbsp;into an editor and collapsed some of the data. It is very helpful that there is a div that wraps the data I&amp;nbsp;need:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;enacting_clause&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;BE IT ENACTED BY THE LEGISLATURE OF THE STATE OF MINNESOTA:&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;article&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;laws.1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;h1&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;article_no&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;ARTICLE 1&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;h1&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;article_header&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;APPROPRIATIONS&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;bill_section&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;laws.1.1.0&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Within that div, there are mutliple tables which ultimately contain the info we&amp;nbsp;need:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;bill_section&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;laws.1.1.0&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;table&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;col&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;width:100%&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;border-bottom: 1px solid transparent; border-right: 1px solid transparent;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;valign=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;bottom&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;h1&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;bill_sec_no&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;Section 1. &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;h3&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;headnote&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;             &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;new&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;text-decoration: underline&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;CAPITAL IMPROVEMENT APPROPRIATIONS.&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;p&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;first&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;table&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Finally, here is a row of&amp;nbsp;data:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;border-bottom: 1px solid transparent; border-right: 1px solid transparent;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;valign=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;bottom&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;new&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;text-decoration: underline&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;University of Minnesota&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;border-bottom: 1px solid transparent; border-right: 1px solid transparent;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;valign=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;bottom&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;new&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;text-decoration: underline&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;$&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;td&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;border-bottom: 1px solid transparent; border-right: 1px solid transparent;&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;valign=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;bottom&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;new&quot;&lt;/span&gt; &lt;span class=&quot;na&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;style=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;text-decoration: underline&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;119,367,000&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: #062873; font-weight: bold;&quot;&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;In the example above, we want to parse out two pieces of data - the description (Universty of Minnesota) and the amount (119,367,000). Another item to note is that the number comes through with commas as well as parenthesis for negative values so we are going to need to clean it up a little. I also found that I pulled in a lot of extra white space in the process, so using&amp;nbsp;&lt;code class=&quot;code&quot; style=&quot;background-color: #f9f2f4; border-radius: 4px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.3999996185303px; padding: 2px 4px;&quot;&gt;string.strip&lt;/code&gt;&amp;nbsp;is a good&amp;nbsp;idea.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Here is the clean up function we’ll&amp;nbsp;use:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: #06287e;&quot;&gt;convert_num&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;    Convert the string number value to a float&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;     - Remove all extra whitespace&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;     - Remove commas&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;     - If wrapped in (), then it is negative number&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;    &quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;(&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;-&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;section&quot; id=&quot;parse-the-html&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;h2 style=&quot;box-sizing: border-box; color: inherit; font-family: inherit; font-size: 30px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 20px;&quot;&gt;Parse the&amp;nbsp;&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;HTML&lt;/span&gt;&lt;/h2&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Now that we know how to get to our tables, use BeautifulSoup’s powerful&amp;nbsp;&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;API&lt;/span&gt;&amp;nbsp;to get at our&amp;nbsp;data.&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# After looking at the data, we can see that the summary has a div id we can use&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;summary&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;soup&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;bill_section&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;laws.1.1.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;})&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Get all the tables in the summary&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;tables&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;table&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# The first table is not useful header info&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# The second table contains all the we need (the list is 0 indexed)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;data_table&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;tables&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Parse each row in the table and add to the appropriate dictionary depending on whether it is a funding line or expense&amp;nbsp;line:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;#Go through each row of the table and pull out our data&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;ow&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;data_table&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;tr&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;cells&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;td&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Ignore lines that don&#39;t have 3 cells of data because it is just spacing&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;cells&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;cells&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;convert_num&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;cells&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;))&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Once we get to the total line we start getting the funding lines&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;TOTAL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;True&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# We don&#39;t want to capture the total because we can calc it&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;continue&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_lines&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;])&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_lines&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;])&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;section&quot; id=&quot;convert-the-data&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;h2 style=&quot;box-sizing: border-box; color: inherit; font-family: inherit; font-size: 30px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 20px;&quot;&gt;Convert the&amp;nbsp;Data&lt;/h2&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Our dictionaries contain the data we need, let’s add them to a pandas DataFrame using&amp;nbsp;&lt;code class=&quot;code&quot; style=&quot;background-color: #f9f2f4; border-radius: 4px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.3999996185303px; padding: 2px 4px;&quot;&gt;DataFrame.from_dict()&lt;/code&gt;&amp;nbsp;:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Create the DataFrame using from_dict&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;from_dict&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_lines&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;orient&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;index&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;from_dict&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_lines&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;orient&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;index&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Label our column&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;Amount&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;Amount&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;First, we look at a small subset of the spending&amp;nbsp;lines:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; max-height: 1000px; max-width: 1500px; overflow: auto;&quot;&gt;&lt;table border=&quot;1&quot; class=&quot;dataframe&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; box-sizing: border-box;&quot;&gt;&lt;thead style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box; text-align: right;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px; text-align: left;&quot;&gt;&lt;/th&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px; text-align: left;&quot;&gt;Amount&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Administration&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;127000000&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Bond Sale Expenses&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;900000&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Minnesota State Academies&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;11354000&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Public Facilities Authority&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;45993000&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Housing Finance Agency&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;20000000&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Then look at how it is&amp;nbsp;funded.&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; max-height: 1000px; max-width: 1500px; overflow: auto;&quot;&gt;&lt;table border=&quot;1&quot; class=&quot;dataframe&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; box-sizing: border-box;&quot;&gt;&lt;thead style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box; text-align: right;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px; text-align: left;&quot;&gt;&lt;/th&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px; text-align: left;&quot;&gt;Amount&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;State Transportation Fund&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;36613000&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Trunk Highway Fund&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;7950000&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Bond Proceeds Fund (User Financed Debt Service)&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;39104000&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Bond Proceeds Cancellations&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;-10849000&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Maximum Effort School Loan Fund&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;5491000&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;th style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;Bond Proceeds Fund (General Fund Debt Service)&lt;/th&gt;&lt;td style=&quot;box-sizing: border-box; padding: 0px;&quot;&gt;814745000&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;We can check our totals too to make sure we processed the data&amp;nbsp;correctly.&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;Amount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre class=&quot;literal-block&quot; style=&quot;background-color: whitesmoke; border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;893054000.0&lt;br /&gt;&lt;/pre&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;Amount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre class=&quot;literal-block&quot; style=&quot;background-color: whitesmoke; border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;893054000.0&lt;br /&gt;&lt;/pre&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;It looks like everything was processed correctly. Now, we can analyze the data any way we&amp;nbsp;want.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;section&quot; id=&quot;plot-the-data&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;h2 style=&quot;box-sizing: border-box; color: inherit; font-family: inherit; font-size: 30px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 20px;&quot;&gt;Plot The&amp;nbsp;Data&lt;/h2&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;In this specific case, I am going to generate a simple horizontal bar graph so that it is easy to see where the biggest expenditures&amp;nbsp;are.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;First, I’ll sort both sets of&amp;nbsp;data:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;Amount&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;Amount&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;panel panel-info&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0470588) 0px 1px 1px; background-color: white; border-radius: 4px; border: 1px solid rgb(188, 232, 241); box-shadow: rgba(0, 0, 0, 0.0470588) 0px 1px 1px; box-sizing: border-box; margin-bottom: 20px;&quot;&gt;&lt;div class=&quot;panel-heading&quot; style=&quot;background-color: #d9edf7; border-bottom-style: solid; border-bottom-width: 1px; border-color: rgb(188, 232, 241); border-top-left-radius: 3px; border-top-right-radius: 3px; box-sizing: border-box; color: #31708f; padding: 10px 15px;&quot;&gt;Making Nice Plots&lt;/div&gt;&lt;div class=&quot;panel-body&quot; style=&quot;box-sizing: border-box; padding: 15px;&quot;&gt;If you don’t learn anything else from this article, don’t forget that you can make your default plots look a lot nicer by using a simple pandas settings -&amp;nbsp;&lt;code class=&quot;code&quot; style=&quot;background-color: #f9f2f4; border-radius: 4px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.3999996185303px; padding: 2px 4px;&quot;&gt;pd.options.display.mpl_style = &#39;default&#39;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Set our default plot style so it looks&amp;nbsp;nicer:&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;mpl_style&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;default&#39;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Plot horizontal bar&amp;nbsp;chart&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;barh&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;2014 MN Capital Budget Spending&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;figure&quot; style=&quot;box-sizing: border-box; height: auto; max-width: 100%; width: 572px;&quot;&gt;&lt;img alt=&quot;Image compare&quot; src=&quot;http://pbpython.com/images/output_21_1.png&quot; style=&quot;border: 0px; box-sizing: border-box; height: auto; max-width: 100%; padding: 10px 0px 26px; vertical-align: middle; width: 572px;&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;For comparison, here is what the image looks like if you don’t set&amp;nbsp;&lt;code class=&quot;code&quot; style=&quot;background-color: #f9f2f4; border-radius: 4px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.3999996185303px; padding: 2px 4px;&quot;&gt;pd.options.display.mpl_style&lt;/code&gt;&lt;/div&gt;&lt;div class=&quot;figure&quot; style=&quot;box-sizing: border-box; height: auto; max-width: 100%; width: 570px;&quot;&gt;&lt;img alt=&quot;Image compare&quot; src=&quot;http://pbpython.com/images/output_MN-budget-1.png&quot; style=&quot;border: 0px; box-sizing: border-box; height: auto; max-width: 100%; padding: 10px 0px 26px; vertical-align: middle; width: 570px;&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;Regardless of the format, I think you’ll agree that viewing the capital budget in this plot yields a lot more insight than the raw&amp;nbsp;&lt;span class=&quot;caps&quot; style=&quot;box-sizing: border-box;&quot;&gt;HTML&lt;/span&gt;&amp;nbsp;data.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;section&quot; id=&quot;final-thoughts&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;h2 style=&quot;box-sizing: border-box; color: inherit; font-family: inherit; font-size: 30px; font-weight: 500; line-height: 1.1; margin-bottom: 10px; margin-top: 20px;&quot;&gt;Final&amp;nbsp;Thoughts&lt;/h2&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;This little project has been useful for me and I hope it provides a starting point for you to understand how to use various python tools to scrape the web. In this case, I learned a little bit that I think could be applicable to lots of other projects. I also am curious about this little slice of data and intend to look into it some more and see what insight I can&amp;nbsp;glean.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 24px;&quot;&gt;For reference, here is the complete code for this example. This version will download the data to a file and use that locally instead of hitting the site each&amp;nbsp;time.&lt;/div&gt;&lt;div class=&quot;highlight&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;pre style=&quot;background: rgb(240, 240, 240); border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(153, 153, 153); border-radius: 4px; border-style: solid; border-width: 1px 1px 1px 5px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 13px; line-height: 1.42857143; margin-bottom: 10px; overflow: auto; padding: 9.5px 9.5px 9.5px 20px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;#Parse 2014 MN Capital budget - https://www.revisor.mn.gov/laws/?year=2014&amp;amp;type=0&amp;amp;doctype=Chapter&amp;amp;id=294&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;#Store the summary in a DataFrame for eventual manipulation&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;__future__&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;print_function&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;os.path&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;collections&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;defaultdict&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;string&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;requests&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;bs4&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;BeautifulSoup&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;pandas&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;pd&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;np&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: #0e84b5; font-weight: bold;&quot;&gt;plt&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;MNBudget-2014.html&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;https://www.revisor.mn.gov/laws/?year=2014&amp;amp;type=0&amp;amp;doctype=Chapter&amp;amp;id=294&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: #06287e;&quot;&gt;convert_num&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;    Convert the string number value to a float&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;     - Remove all extra whitespace&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;     - Remove commas&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;     - If wrapped in (), then it is negative number&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;sd&quot; style=&quot;box-sizing: border-box; color: #4070a0; font-style: italic;&quot;&gt;    &quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;(&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;-&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# As we work through the process, it is easier to&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# download it once and work with the saved copy instead of&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# trying to hit the server each time&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Just delete the output file to force a new download&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;isfile&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;Loading the data via the file.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;r&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;Fetching the data via the URL.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;content&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;w&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Init the variables&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Use a defaultdict with an empty list because it eases the DataFrame creation&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_lines&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;defaultdict&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_lines&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;defaultdict&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;False&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Now that we have the data, let&#39;s process it&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;soup&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;BeautifulSoup&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# After looking at the data, we can see that the summary has a div id we can use&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;summary&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;soup&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;div&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;class&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;bill_section&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;laws.1.1.0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;})&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Get all the tables in the summary&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;tables&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;table&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# The first table is not useful header info&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# The second table contains all the we need (the list is 0 indexed)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;data_table&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;tables&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;#Go through each row of the table and pull out our data&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;ow&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;data_table&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;tr&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;cells&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;find_all&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;td&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Ignore lines that don&#39;t have 3 cells of data because it is just spacing&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;cells&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;cells&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;convert_num&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;cells&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;))&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Once we get to the total line we start getting the funding lines&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;TOTAL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;True&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# We don&#39;t want to capture the total because we can calc it&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;continue&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_lines&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;])&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_lines&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Create the DataFrame using from_dict&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;from_dict&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_lines&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;orient&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;index&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;DataFrame&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;from_dict&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_lines&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;orient&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;index&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;# Label our column&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;Amount&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;rename&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;Amount&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;inplace&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot; style=&quot;box-sizing: border-box; color: #007020;&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;Amount&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;columns&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;Amount&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;Amount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;())&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: #007020; font-weight: bold;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;Amount&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;())&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: #60a0b0; font-style: italic;&quot;&gt;#Set some nicer defaults for plots&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;pd&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;mpl_style&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;default&#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_bar&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;expense_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;barh&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: #40a070;&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;2014 MN Capital Budget Spending&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;savefig&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;MN-2014-Expense.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_bar&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;funding_df&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&#39;barh&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;2014 MN Capital Budget Funding&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; color: #666666;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box;&quot;&gt;savefig&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: #4070a0;&quot;&gt;&quot;MN-2014-Funding.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;ul class=&quot;pager&quot; style=&quot;box-sizing: border-box; color: #333333; font-family: &#39;Average Sans&#39;, sans-serif; font-size: 16px; line-height: 26px; list-style: none; margin: 20px 0px; padding-left: 0px; text-align: center;&quot;&gt;&lt;li class=&quot;previous&quot; style=&quot;box-sizing: border-box; display: inline;&quot;&gt;&lt;a href=&quot;http://pbpython.com/pandas-pivot-table-explained.html&quot; style=&quot;background-color: white; border-radius: 15px; border: 1px solid rgb(221, 221, 221); box-sizing: border-box; color: #337ab7; display: inline-block; float: left; padding: 5px 14px; text-decoration: none;&quot;&gt;← Pandas Pivot Table&amp;nbsp;Explained&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;article-tag-list&quot; style=&quot;box-sizing: border-box; color: #333333; font-family: &#39;Average Sans&#39;, sans-serif; font-size: 16px; line-height: 26px; padding-top: 15px;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;article-tag-list&quot; style=&quot;box-sizing: border-box; color: #333333; font-family: &#39;Average Sans&#39;, sans-serif; font-size: 16px; line-height: 26px; padding-top: 15px;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;article-tag-list&quot; style=&quot;box-sizing: border-box; color: #333333; font-family: &#39;Average Sans&#39;, sans-serif; font-size: 16px; line-height: 26px; padding-top: 15px;&quot;&gt;Source:&amp;nbsp;&lt;a href=&quot;http://pbpython.com/web-scraping-mn-budget.html?utm_source=Python+Weekly+Newsletter&amp;amp;utm_campaign=220a86923f-Python_Weekly_Issue_173_January_8_2015&amp;amp;utm_medium=email&amp;amp;utm_term=0_9e26887fc5-220a86923f-312723701&quot;&gt;http://pbpython.com/web-scraping-mn-budget.html?utm_source=Python+Weekly+Newsletter&amp;amp;utm_campaign=220a86923f-Python_Weekly_Issue_173_January_8_2015&amp;amp;utm_medium=email&amp;amp;utm_term=0_9e26887fc5-220a86923f-312723701&lt;/a&gt;&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2015/01/web-scraping-its-your-civic-duty.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-4426778797912561785</guid><pubDate>Thu, 18 Dec 2014 10:20:00 +0000</pubDate><atom:updated>2014-12-18T18:40:21.628+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Web Development</category><title>An Architecture for Real-Time Geo-tracking with Python, Celery, RabbitMQ, and More</title><description>&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Source:&amp;nbsp;&lt;a href=&quot;http://blog.pivotal.io/pivotal/case-studies-2/an-architecture-for-real-time-geo-tracking-with-python-celery-rabbitmq-and-more&quot;&gt;http://blog.pivotal.io/pivotal/case-studies-2/an-architecture-for-real-time-geo-tracking-with-python-celery-rabbitmq-and-more&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;If you look at a map online and someone asked what you see, most people will answer, “a map.”&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;That’s not the answer you would get from Ragi Burham. He&amp;nbsp;sees the underlying geometry, vectors, styling, raster data, GUI controls, application logic, and data store.&amp;nbsp;That’s because Burham&amp;nbsp;is an expert in the area of mapping solutions, and his background includes over a decade of geo-related work with organizations like ESRI, NIMA, National Geographic, Navteq, TeleAtlas, and his own company,&amp;nbsp;&lt;a href=&quot;http://www.amigocloud.com/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;AmigoCloud&quot;&gt;AmigoCloud&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;At Pivotal, we get excited about people like Ragi Burham—an open source minded software engineer with a new way of doing things. At&amp;nbsp;&lt;a href=&quot;https://us.pycon.org/2013/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;PyCon in March of 2013&quot;&gt;PyCon in March of 2013&lt;/a&gt;, Burham&amp;nbsp;shared a talk titled, “Realtime Tracking and Mapping of Geographic Objects using Python”—it’s another way to look at geography-based big, fast data architectures.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Below, we recap the “Normal” and “Real-time” architectures that Burham&amp;nbsp;shared in his talk. These two approaches use&amp;nbsp;&lt;a href=&quot;http://openlayers.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;OpenLayers&quot;&gt;OpenLayers&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;https://www.varnish-cache.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Varnish&quot;&gt;Varnish&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://wiki.nginx.org/Main&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Nginx&quot;&gt;Nginx&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://gunicorn.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Gunicorn&quot;&gt;Gunicorn&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;https://www.djangoproject.com/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Django&quot;&gt;Django&lt;/a&gt;,&lt;a href=&quot;http://tilestache.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;TileStache&quot;&gt;TileStache&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://memcached.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Memcached&quot;&gt;Memcached&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://mapnik.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Mapnik&quot;&gt;Mapnik&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://www.postgresql.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;PostgreSQL&quot;&gt;PostgreSQL&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://postgis.net/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;PostGIS&quot;&gt;PostGIS&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://socket.io/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Socket.io&quot;&gt;Socket.io&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://nodejs.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Node.js&quot;&gt;Node.js&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://www.celeryproject.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Celery&quot;&gt;Celery&lt;/a&gt;, and&lt;a href=&quot;http://www.rabbitmq.com/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;RabbitMQ&quot;&gt;RabbitMQ&lt;/a&gt;. Much like our recent post on&amp;nbsp;&lt;a href=&quot;http://blog.gopivotal.com/products/socialvane-gears-up-to-organize-social-media-with-rabbitmq-and-celery&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;scaling social media with Celery and RabbitMQ&quot;&gt;scaling social media with Celery and RabbitMQ&lt;/a&gt;, Burham&amp;nbsp;adds these two components along with Socket.io and Node.js to help his real-time architecture work in a fundamentally differently way and scale.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;If you have 26 minutes, you can also view the video below.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white; color: black; font-family: Arial, Helvetica, &#39;sans-serif normal&#39;; font-size: 12px; line-height: normal;&quot;&gt;&lt;a href=&quot;http://www.youtube.com/embed/WQQr0UM17gI&quot;&gt;http://www.youtube.com/embed/WQQr0UM17gI&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;http://www.youtube.com/embed/WQQr0UM17gI&quot; width=&quot;420&quot;&gt;&lt;/iframe&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: freight-sans-pro, sans-serif; font-size: 18px; font-weight: 100; margin: 20px 0px !important; text-transform: uppercase;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;a href=&quot;http://www.gopivotal.com/products/pivotal-rabbitmq&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;cta-download-rabbitmq&quot; class=&quot;alignnone size-full wp-image-5875&quot; src=&quot;http://blog.gopivotal.com/wp-content/uploads/2014/01/cta-download-rabbitmq.png&quot; height=&quot;135&quot; style=&quot;border: none; height: auto; max-width: 617px;&quot; width=&quot;600&quot; /&gt;&lt;/a&gt;A “NORMAL” GEO-BASED ARCHITECTURE&lt;br /&gt;THE CHALLENGES WITH REAL-TIME GEO-BASED ARCHITECTURES&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Beyond an explanation of underlying geometry, vectors, styling, raster data, and architecture, Burham&amp;nbsp;covered some of use cases and requirements driving the specifics of what geo-based systems do—determining the amount of information on the map, omitting certain types of mapping objects, making calculations like speed or direction, alerting that something has crossed a boundary, and more.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;He began outlining his “Normal” GeoStack architecture by listing the most popular open source data sets and covering some of the pros and cons of&amp;nbsp;&lt;a href=&quot;http://www.openstreetmap.org/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;OpenStreetMap&quot;&gt;OpenStreetMap&lt;/a&gt;,&lt;a href=&quot;http://www.fsa.usda.gov/FSA/apfoapp?area=home&amp;amp;subject=prog&amp;amp;topic=nai&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;NAIP&quot;&gt;NAIP&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://srtm.usgs.gov/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;SRTM&quot;&gt;SRTM&lt;/a&gt;, and&amp;nbsp;&lt;a href=&quot;http://www.naturalearthdata.com/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Natural Earth Data&quot;&gt;Natural Earth Data&lt;/a&gt;. With the data sources covered, he filled in the details of the architecture. This included a client with OpenLayers, a JavaScript library that helps with rendering maps (another option is&amp;nbsp;&lt;a href=&quot;http://leafletjs.com/&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;Leaflet&quot;&gt;Leaflet&lt;/a&gt;). Varnish was used in front of servers with the following components: Nginx, Gunicorn, TileStache, Memcached, and Mapnik. Then, a PostgreSQL database stores the map information with the PostGIS spatial database extension.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Because rendering style can take a lot of time, Varnish is used for speeding things up and can also be used as a reverse proxy. For those unfamiliar, TileStache is used to serve map tiles based on rendered geographic data the Mapnik toolkit is used for map development. Here is a screen shot of his normal architecture:&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;a data-slb-active=&quot;1&quot; href=&quot;http://blog.gopivotal.com/wp-content/uploads/2013/06/normal-geostack.jpg&quot; style=&quot;background-color: white; border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;normal-geostack&quot; class=&quot;alignnone size-full wp-image-3270&quot; src=&quot;http://blog.gopivotal.com/wp-content/uploads/2013/06/normal-geostack.jpg&quot; height=&quot;278&quot; style=&quot;border: none; height: auto; max-width: 617px;&quot; width=&quot;469&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;One of the key challenges with this type of architecture is when you need to get state from the database. Clients end up polling for many real-time tracking scenarios. This presents a problem when, for example, you have 1000s of vehicles confirming state every second. Polling the database at this rate can create an overwhelming and unnecessary amount of traffic. And it doesn’t scale.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;But, what if the server could notify a client? To evolve the architecture, Burham&amp;nbsp;proposes four additional components—Node.js with Socket.io and Celery with RabbitMQ.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;a data-slb-active=&quot;1&quot; href=&quot;http://blog.gopivotal.com/wp-content/uploads/2013/06/real-time-geostack.jpg&quot; style=&quot;background-color: white; border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot;&gt;&lt;img alt=&quot;real-time-geostack&quot; class=&quot;alignnone size-full wp-image-3271&quot; src=&quot;http://blog.gopivotal.com/wp-content/uploads/2013/06/real-time-geostack.jpg&quot; height=&quot;353&quot; style=&quot;border: none; height: auto; max-width: 617px;&quot; width=&quot;469&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;By adding Socket.io to the client, we get a way to use&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/WebSocket&quot; style=&quot;border: none; color: #3ea7bc; text-decoration: none;&quot; target=&quot;_blank&quot; title=&quot;websockets&quot;&gt;websockets&lt;/a&gt;&amp;nbsp;across browsers and allow data to be transported bi-directionally. We can send information from the server back to the client specifically and only when it is needed. Varnish changes purpose slightly in this architecture—it still does the HTTP caching, but now it also acts as a reverse proxy. You can configure small lines of code on Varnish to deal with traffic differently. For example, if websocket traffic comes in, you can tell it to go to server A, and, if other types of traffic come in, use server B. In this case, Node.js is connected with Varnish and offers a way to push or publish notifications back out to clients.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #3c3d42; font-family: freight-sans-pro, sans-serif; font-size: 18px; line-height: 1.4;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;Now, we need a way to take an incoming client’s geo-position update, asynchronously decide if some alert should happen, and distribute a notification back out for only certain clients. This is where we add Celery and RabbitMQ to the architecture. With these two components, we can support asynchronous tasks and queues. If you aren’t familiar with Celery, it is a task queue based on distributed message passing. Your code can call Celery tasks to execute concurrently and operate in either asynchronous or synchronous modes. This is great for geographic use cases like crossing a boundary or fence—when something is entering or leaving a polygon. You don’t need to calculate when an update happens in real-time, you can receive a task, make a calculation, and decide to notify others later. With the addition of RabbitMQ (Celery’s default broker), we then transform these tasks and calculations into a Pub/Sub channel where Node.js is listening. Whenever an appropriate event is triggered, we can push a message down the channel, and Node.js forwards the information back to the appropriate clients using Socket.io.&lt;/span&gt;&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/12/an-architecture-for-real-time-geo.html</link><author>noreply@blogger.com (MathBee)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/WQQr0UM17gI/default.jpg" height="72" width="72"/><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-4893218966031956406</guid><pubDate>Thu, 18 Dec 2014 07:33:00 +0000</pubDate><atom:updated>2014-12-18T15:33:57.536+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Web Development</category><title>Flask performance optimization</title><description>&lt;header class=&quot;post-header&quot;&gt;&lt;hgroup&gt;&lt;div class=&quot;intro&quot;&gt;Source: &lt;a href=&quot;http://www.vadimkravcenko.com/flask-performance/&quot;&gt;http://www.vadimkravcenko.com/flask-performance/&lt;/a&gt;&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;intro&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;intro&quot;&gt;Here are my performance optimization guidelines that I try to follow&lt;/div&gt;&lt;/hgroup&gt;        &lt;/header&gt;&lt;h3 id=&quot;general&quot;&gt;General&lt;/h3&gt;After transitioning from PHP to Python development I was quite  surprised by the lack of performance optimization tips and scaling  advice in general. So with this post I will try and lay out the basic  ideas of scaling a website from 10 to 50,000 users with Flask Framework.&lt;br /&gt;&lt;h3 id=&quot;server-setup&quot;&gt;Server Setup&lt;/h3&gt;It all starts with your server setup, and the server depends on your budget. There are several options that you can chose from:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;4GB RAM 8 Core VPS from Linode (80$)&lt;/li&gt;&lt;li&gt;4GB RAM 2 Core VPS from DigitalOcean (40$)&lt;/li&gt;&lt;li&gt;Or a dedicated server from any of hundreds of hosting companies.&lt;/li&gt;&lt;/ol&gt;But I would strongly advise taking something with &amp;gt;= 2GB RAM. This  much RAM and a decent CPU will help you scale to hundreds of thousands  of views per day. (With the proper amount of caching of course)&lt;br /&gt;&lt;h3 id=&quot;frontend-reverse-proxy&quot;&gt;Frontend Reverse Proxy&lt;/h3&gt;Now that we have our server, we need to setup a frontend proxy. Your  choice is between Apache, Lighttpd or Nginx. I would suggest using Nginx  because it’s event-driven (that means amazingly low memory footprint)  and possibility to serve 10,000 concurrent users with no problems at  all.&lt;br /&gt;&lt;h3 id=&quot;caching-static-pages-with-nginx-itself&quot;&gt;Caching static pages with Nginx itself&lt;/h3&gt;Before the users even gets to your dynamic site, it’s usually a good  idea to cache some pages with nginx. For example you have a page with a  list of posts that updates only once a day, or a comments page, that  updates only once a week. For such pages you can setup Nginx caching, so  that the user wont even get to the python interpeter. A guide on how to  setup Filesystem cache is &lt;a href=&quot;http://lucor.github.io/post/caching-dynamic-content-using-nginx/&quot;&gt;here&lt;/a&gt;, or if you want to setup Nginx + Memcached &lt;a href=&quot;http://stackoverflow.com/questions/10016499/nginx-with-flask-and-memcached-returns-some-garbled-characters&quot;&gt;guide&lt;/a&gt;.&lt;br /&gt;&lt;h3 id=&quot;uwsgi-and-gevent&quot;&gt;UWSGI and Gevent&lt;/h3&gt;Now that the user got to the dynamic part of your application, we  need to decide what kind of web server we want to use. There are  different benchmarks &lt;a href=&quot;http://nichol.as/benchmark-of-python-web-servers&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;http://blog.kgriffs.com/2012/12/18/uwsgi-vs-gunicorn-vs-node-benchmarks.html&quot;&gt;here&lt;/a&gt; that praise different kinds of web servers. But I personally prefer  UWSGI, because it’s fast and lightweight plus there are many different  CLI options that you can provide. For example: Auto-reload python  compiled files on every request. (Good for development).&lt;br /&gt;Now we add some asynchronous IO and lightweight multi-threading to it with &lt;a href=&quot;http://uwsgi-docs.readthedocs.org/en/latest/Gevent.html&quot;&gt;Gevent&lt;/a&gt; and boom we have a very fast web server, able to handle thousands of concurrent connections.&lt;br /&gt;&lt;h3 id=&quot;flask-pypy&quot;&gt;Flask PyPy&lt;/h3&gt;If you’re not using any 3rd party extensions that are mainly written  in C (Like the MySQLdb driver for python) your should consider trying  PyPy for more performance boost. Flask is fully compatible with PyPy  although some patching will be required to use Gevent with PyPy (&lt;a href=&quot;http://stackoverflow.com/questions/14294643/which-setup-is-more-efficient-flask-with-pypy-or-flask-with-gevent&quot;&gt;source&lt;/a&gt;)&lt;br /&gt;Here are some benchmarks CPython vs PyPy: &lt;a href=&quot;http://casbon.me/what-will-pypy-do-for-your-website-benchmarki&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;http://blog.irukado.org/2013/06/pypy-vs-cpython-speed-memory-usage-benchmarks/&quot;&gt;here&lt;/a&gt;&lt;br /&gt;&lt;h3 id=&quot;flask-cache&quot;&gt;Flask-Cache&lt;/h3&gt;This should be the first &lt;a href=&quot;http://pythonhosted.org/Flask-Cache/&quot;&gt;extension&lt;/a&gt; that you install. It’s easy to setup and easy to use.&lt;br /&gt;Example caching with decorator:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;@cache.cached(timeout=500, key_prefix=&#39;daily_posts&#39;)&lt;br /&gt;def get_posts():&lt;br /&gt;    posts = get_all_posts_with_multiple_joins_heavy_db()&lt;br /&gt;    return [x.content for x in posts]&lt;br /&gt;&lt;br /&gt;cached_posts = get_posts()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;memcachedredis&quot;&gt;Memcached/Redis&lt;/h3&gt;Another advice I can give you is storing EVERYTHING, that can be  cached, in memory. It doesn’t matter what kind of system you prefer  (Although a horizontally scalable structure would be nice) Memcached,  Redis, &lt;a href=&quot;http://www.project-voldemort.com/voldemort/&quot;&gt;Voldemort&lt;/a&gt;. The main point is, cache, cache, cache. Don’t do anything dynamic if you can get the results from cache.&lt;br /&gt;&lt;h3 id=&quot;jinja2-template-bytecode-caching&quot;&gt;Jinja2 template bytecode caching&lt;/h3&gt;With Jinja2 you have several options of &lt;a href=&quot;http://jinja.pocoo.org/docs/api/#bytecode-cache&quot;&gt;caching bytecode&lt;/a&gt; of compiled templates:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;    FileSystemBytecodeCache&lt;br /&gt;   &lt;/li&gt;&lt;li&gt;    MemcachedBytecodeCache&lt;br /&gt;   &lt;/li&gt;&lt;/ol&gt;Use them.&lt;br /&gt;&lt;h3 id=&quot;consider-using-elasticsearch&quot;&gt;Consider using ElasticSearch&lt;/h3&gt;If you’re doing a lot of queries like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;SELECT * FROM posts WHERE author=&#39;someauthor&#39;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Then you should definitely consider replacing these kinds of queries with ElasticSearch. Here are some articles on ES performance: &lt;a href=&quot;http://blog.liip.ch/archive/2013/07/19/on-elasticsearch-performance.html&quot;&gt;here&lt;/a&gt; and &lt;a href=&quot;http://cloudspace.com/blog/2013/05/06/read-this-before-using-elasticsearch/&quot;&gt;here&lt;/a&gt;&lt;br /&gt;Although ES is not a database, you can feed data into it from your RDBMS and then serve the data to user from it.&lt;br /&gt;The main points are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;    ES is easily scalable. You can scale it from 1 to 10 servers “with just a click of a button”&lt;br /&gt;   &lt;/li&gt;&lt;li&gt;    Very fast. Based on Apache Lucene the FULL-TEXT search capabilities are extremely fast.&lt;br /&gt;   &lt;/li&gt;&lt;li&gt;    Easy to use. You can add remove documents with requests to the REST API.&lt;br /&gt;   &lt;/li&gt;&lt;li&gt;    Active development and big community.&lt;br /&gt;   &lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;code-profiling-and-optimization&quot;&gt;Code Profiling and Optimization&lt;/h3&gt;Now we’ve come down to the last thing you must regularly do. Profile  your application! Check out how many queries you’re doing per page, how  long does the sorting last, maybe there are ways you can optimize the  nested for loops? There’s always something that can be rewritten.&lt;br /&gt;Good for you there’s a good &lt;a href=&quot;https://github.com/mgood/flask-debugtoolbar&quot;&gt;profiling tool for Flask&lt;/a&gt; that makes it easy to find the bottlenecks of your application&lt;br /&gt;&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;&lt;br /&gt;I’m pretty sure everyone has their own “performance guidelines” that  they usually follow with their apps. But this one is mine, and I hope  you found out something useful here.</description><link>http://lifeeditor.blogspot.com/2014/12/flask-performance-optimization.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-8724623546131149077</guid><pubDate>Thu, 18 Dec 2014 07:28:00 +0000</pubDate><atom:updated>2014-12-18T15:28:55.046+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Web Development</category><title>What is the technology stack behind Pinterest?</title><description>&lt;div id=&quot;ld_cdnlse_2433&quot; style=&quot;color: #333333; font-family: &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 14.8571424484253px; line-height: 12px;&quot;&gt;&lt;div class=&quot;AnswerHeader ContentHeader&quot; style=&quot;line-height: 1.4; margin: 0px 0px 4px; min-height: 40px; position: relative;&quot;&gt;&lt;div class=&quot;author_info&quot;&gt;&lt;span class=&quot;feed_item_answer_user&quot; id=&quot;__w2_afe91qh_answer_user_sig&quot; style=&quot;display: block; font-weight: bold;&quot;&gt;&lt;span id=&quot;ld_qxekhn_2432&quot;&gt;&lt;a action_mousedown=&quot;UserLinkClickthrough&quot; class=&quot;user hover&quot; href=&quot;http://www.quora.com/Paul-Sciarra&quot; id=&quot;__w2_ORJ5aIt_link&quot; style=&quot;background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; color: #333333; line-height: 14px; margin-bottom: 2px; text-decoration: none;&quot; target=&quot;_blank&quot;&gt;Paul Sciarra&lt;/a&gt;&lt;span class=&quot;IdentitySig ActorNameSig IdentityNameSig&quot; id=&quot;__w2_Z8bgafW_bio&quot; style=&quot;font-weight: normal;&quot;&gt;,&amp;nbsp;&lt;span id=&quot;__w2_Z8bgafW_link&quot;&gt;&lt;span class=&quot;IdentitySig ActorNameSig IdentityNameSig&quot; id=&quot;__w2_Z8bgafW_sig&quot;&gt;&lt;span class=&quot;expanded_q_text&quot; id=&quot;__w2_PhZaS4F_text_snip&quot; style=&quot;line-height: 1.4;&quot;&gt;&lt;span id=&quot;__w2_PhZaS4F_text_snip_content&quot;&gt;I&#39;m a co-founder.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div id=&quot;ld_qxekhn_2433&quot;&gt;&lt;span class=&quot;answer_voters&quot; style=&quot;color: #999999; display: block; font-size: 13px;&quot;&gt;377&amp;nbsp;&lt;span id=&quot;ld_qhzgbl_2698&quot;&gt;upvotes by&amp;nbsp;&lt;span class=&quot;user&quot; style=&quot;color: inherit;&quot;&gt;Quora User&lt;/span&gt;,&amp;nbsp;&lt;a action_mousedown=&quot;UserLinkClickthrough&quot; class=&quot;user&quot; href=&quot;http://www.quora.com/Yash-Nelapati&quot; id=&quot;__w2_QBc5ctu_link&quot; style=&quot;background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; text-decoration: none;&quot; target=&quot;_blank&quot;&gt;Yash Nelapati&lt;/a&gt;,&amp;nbsp;&lt;a action_mousedown=&quot;UserLinkClickthrough&quot; class=&quot;user&quot; href=&quot;http://www.quora.com/Ben-Silbermann&quot; id=&quot;__w2_JIomigp_link&quot; style=&quot;background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; text-decoration: none;&quot; target=&quot;_blank&quot;&gt;Ben Silbermann&lt;/a&gt;,&amp;nbsp;&lt;a class=&quot;more_link&quot; href=&quot;http://www.quora.com/What-is-the-technology-stack-behind-Pinterest-1#&quot; id=&quot;__w2_fzhQg9J_toggle_link&quot; style=&quot;background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; text-decoration: none;&quot;&gt;(more)&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div id=&quot;__w2_FQBJhwA_answer_content&quot; style=&quot;color: #333333; font-family: &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 14.8571424484253px; line-height: 12px;&quot;&gt;&lt;div id=&quot;ld_cdnlse_2434&quot;&gt;&lt;/div&gt;&lt;div id=&quot;ld_cdnlse_2435&quot;&gt;&lt;div class=&quot;ExpandedQText QuotableExpandedAnswer ExpandedAnswer&quot; style=&quot;font-family: Georgia, Times, &#39;Times New Roman&#39;, serif; line-height: 1.4;&quot;&gt;&lt;div id=&quot;__w2_cXnbfJH_outer&quot;&gt;&lt;div id=&quot;__w2_cXnbfJH_container&quot;&gt;We use python + heavily-modified Django at the application layer.&amp;nbsp; Tornado and (very selectively) node.js as web-servers.&amp;nbsp; Memcached and membase / redis for object- and logical-caching, respectively.&amp;nbsp; RabbitMQ as a message queue.&amp;nbsp; Nginx, HAproxy and Varnish for static-delivery and load-balancing.&amp;nbsp; Persistent data storage using MySQL.&amp;nbsp; MrJob on EMR for map-reduce.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/12/what-is-technology-stack-behind.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-2593701166518505614</guid><pubDate>Thu, 18 Dec 2014 07:27:00 +0000</pubDate><atom:updated>2014-12-18T15:27:13.644+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Web Development</category><title>Quora’s Technology Examined</title><description>&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Source:&amp;nbsp;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined&quot;&gt;http://www.bigfastblog.com/quoras-technology-examined&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Quora has taken the tech and entrepreneurial world by storm, providing a system that works so fluidly that it is sometimes hard to see what the big fuss is all about. This slick tool is powered, not only by an intelligent crowd of askers and answerers, but by a well-crafted backend created by co-founders who honed their skills at Facebook.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;It is not surprising that, with all the smart people using this smart tool, there are many pondering on how it works so well. The NoSQL boffins scratch their heads and ponder such questions as, “&lt;a href=&quot;http://www.quora.com/Why-does-Quora-use-MySQL-as-the-data-store-rather-than-NoSQLs-such-as-Cassandra-MongoDB-CouchDB-etc&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Why does Quora use MySQL as the data store rather than NoSQLs such as Cassandra, MongoDB, CouchDB, etc?&lt;/a&gt;“.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;In this blog post I will delve into the snippets of information available on Quora and look at Quora from a technical perspective. What technical decisions have they made? What does their architecture look like? What languages and frameworks do they use? How do they make that search bar respond so quickly?&lt;/div&gt;&lt;ul style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; list-style: square; margin: 0px 0px 21px 2.5em; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#components-of-quora&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Components Of Quora&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#whats-cooking-under-that-hood&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;What’s Cooking Under That Hood?&lt;/a&gt;&lt;/li&gt;&lt;ul style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; list-style: square; margin: 0px 0px 0px 2.5em; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#the-search-box&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;The Search-Box&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#webnode2-and-livenode&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Webnode2 And LiveNode&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Amazon Web Services&lt;/a&gt;&lt;/li&gt;&lt;ul style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; list-style-image: initial; list-style-position: initial; margin: 0px 0px 0px 2.5em; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#ubuntu-linux&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Ubuntu Linux&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#static-content&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Static Content&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#haproxy-load-balancing&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;HAProxy Load-Balancing&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#nginx&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Nginx&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#pylons-and-paste&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Pylons And Paste&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#python&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Python&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#thrift&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Thrift&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#tornado&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Tornado&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#long-polling-comet&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Long Polling (Comet)&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#mysql&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;MySQL&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#memcached&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Memcached&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#git&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Git&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#charlie-cheever-follows-14-rules-for-faster-loading-web-sites&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Charlie Cheever Follows “14 Rules for Faster-Loading Web Sites”&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#conclusion&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#recommended-reading&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Recommended Reading&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#resources&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Resources&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;components-of-quora&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 21px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Components Of Quora&lt;/h2&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;The general components that make up Quora are…&lt;/div&gt;&lt;ul style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; list-style: square; margin: 0px 0px 21px 2.5em; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;You can ask&amp;nbsp;&lt;strong style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;questions&lt;/strong&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;You can&amp;nbsp;&lt;strong style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;answer&lt;/strong&gt;&amp;nbsp;questions (anonymously if you desire)&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;You can&amp;nbsp;&lt;strong style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;comment&lt;/strong&gt;&amp;nbsp;on answered questions&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;You can&amp;nbsp;&lt;strong style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;vote&lt;/strong&gt;-up or vote-down answers to questions&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Questions can be assigned to&amp;nbsp;&lt;strong style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;topics&lt;/strong&gt;&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;You can write a&amp;nbsp;&lt;strong style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;post&lt;/strong&gt;&amp;nbsp;(a informative statement, rather like a orphaned answer or blog post)&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;You can&amp;nbsp;&lt;strong style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;follow&lt;/strong&gt;&amp;nbsp;questions, topics or other users&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;A super-fast auto-complete&amp;nbsp;&lt;strong style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;search&lt;/strong&gt;-box at the top, which doubles as the method for entering new questions&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;The last point, the super-fast auto-complete search-box, is one of the defining features of Quora. You can see immediately, as you begin to enter a question, whether somebody else has already asked that question or if there is a topic or post on the subject. Let’s start there…&lt;/div&gt;&lt;h2 id=&quot;whats-cooking-under-that-hood&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 21px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;What’s Cooking Under That Hood?&lt;/h2&gt;&lt;h3 id=&quot;the-search-box&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;The Search-Box&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Only the questions, topic labels, user names or post titles are indexed and served up to the search-box. There is no full-text search, so searching the content of questions and answers will not work. The text that is indexed is tokenized so that words in a different order will still be matched. Prefix matching enables best matches to be shown before the entire word is entered. For instance, typing “mi” might immediately show “Microsoft” in the results.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;There is some simple stemming of words, since “nears” matches “near”, but “pony” does not match “ponies”. “Topic-aliases” allow for similar matches on topic names, such as “startup” and “start-up”. These topic-aliases have been manually entered by users. Otherwise these would not match.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;If a duplicate question is redirected to another question (a feature of Quora), then that original question will still appear in the search results, since it increases the chances of a match. There is no&amp;nbsp;&lt;a href=&quot;http://www.lucidimagination.com/blog/2009/09/08/auto-suggest-from-popular-queries-using-edgengrams/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;n-gram&lt;/a&gt;&amp;nbsp;indexing, so slight mis-spellings will not match. For instance, “gooogle” (with an extra “o”) finds nothing.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Previously, they did use an open source search server, called&amp;nbsp;&lt;a href=&quot;http://sphinxsearch.com/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Sphinx&lt;/a&gt;. It supports the features they are using above, but they have since moved from this&amp;nbsp;&lt;a href=&quot;http://www.quora.com/What-is-the-best-open-source-solution-for-implementing-fast-auto-complete&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;due to real-time constraints&lt;/a&gt;. Their new solution is built in-house and allows them better prefix indexing and control over the matching algorithms. They built this in Python.&lt;/div&gt;&lt;blockquote style=&quot;background: rgb(255, 255, 255); border: none; color: #555555; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; font-style: italic; line-height: 21px; margin: 0px 2.5em; outline: none; padding: 0px; quotes: none; vertical-align: baseline;&quot;&gt;&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.quora.com/What-libraries-does-Quora-use-for-search&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;&lt;img height=&quot;16&quot; src=&quot;http://www.quora.com/favicon.ico&quot; style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; max-width: 568px; outline: none; padding: 0px 10px 0px 0px; vertical-align: baseline;&quot; width=&quot;16&quot; /&gt;What libraries does Quora use for search?&lt;/a&gt;&lt;br /&gt;&lt;small style=&quot;background: transparent; border: none; font-size: 12px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Adam D’Angelo, Quora Founder (Nov 13, 2010)&lt;/small&gt;&lt;br /&gt;Our search is custom-written. It doesn’t use any libraries aside from Thrift, and Python’s unicode library, which we use for unicode normalization.&lt;/div&gt;&lt;/blockquote&gt;&lt;h4 id=&quot;speedy-queries&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 17px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Speedy Queries&lt;/h4&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Did I mention that the search-box is fast? I did some tests and found the responses to be impressive. Queries are sent over AJAX as a GET request. Responses come back as JSON with the rendered HTML embedded inside the JSON. Rendering of the results on the server-side, as opposed to rendering them in JavaScript, seems to be due to the need to highlight matching words in the text. This is sometimes too complex for JavaScript. For instance, typing “categories” might highlight the world “category” in the result text.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;I was seeing responses of roughly 50 milliseconds per query from my&amp;nbsp;&lt;a href=&quot;http://www.linode.com/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Linode&lt;/a&gt;&amp;nbsp;machine. Quora does not short-change you when sending requests. From within the browser, I found typing “Microsoft” (9 characters) would result in nine requests to the Quora search server, no matter how fast you type. As you will&amp;nbsp;&lt;a href=&quot;http://www.bigfastblog.com/quoras-technology-examined#long-polling-comet&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;see later&lt;/a&gt;, the server is in control, so if it did become over-loaded, then it could update the results less frequently without changing the JavaScript.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Quora uses persistent connections. A HTTP connection is established with the server when you start typing the search query. This connection is kept open and further requests are made on this same open connection. The connection will terminate (times-out) if not used for 60 seconds. If a connection times-out then a new connection is established when typing begins.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;To simulate the typing of a word into the search-box, I sent the following requests, character-by-character, across a persistent connection. For instance “butler” is six requests (“b”, “bu”, “but” … “butler”).&lt;/div&gt;&lt;pre style=&quot;background: rgb(249, 249, 249); border: 1px solid rgb(204, 204, 204); font-family: Monaco, monospace, Courier, &#39;Courier New&#39;; font-size: 0.9em; font-stretch: normal; line-height: 21px; margin-bottom: 21px; outline: none; overflow: auto; padding: 9px; vertical-align: baseline;&quot;&gt;&quot;butler&quot; (6 chars) duration: 0.393 secs 0.065 secs per query&lt;br /&gt;&quot;butler monkeys&quot; (14 chars) duration: 0.672 secs 0.048 secs per query&lt;br /&gt;&quot;fasdisajfosdffsa&quot; (16 chars) duration: 0.746 secs 0.046 secs per query&lt;/pre&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;That last query was used to test if there was a slow-down for a word that would obviously not be in a caching layer. I saw no slow-down. This means that they are not caching, caching is only used to take the load off the backend search engine or they are doing something smarter (e.g. if there is no match for “fasd” then there will be no match for “fasdi”, so abort).&lt;/div&gt;&lt;blockquote style=&quot;background: rgb(255, 255, 255); border: none; color: #555555; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; font-style: italic; line-height: 21px; margin: 0px 2.5em; outline: none; padding: 0px; quotes: none; vertical-align: baseline;&quot;&gt;&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.quora.com/Quora-product/Is-Quora-going-to-implement-full-text-search&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;&lt;img height=&quot;16&quot; src=&quot;http://www.quora.com/favicon.ico&quot; style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; max-width: 568px; outline: none; padding: 0px 10px 0px 0px; vertical-align: baseline;&quot; width=&quot;16&quot; /&gt;Is Quora going to implement full-text search?&lt;/a&gt;&lt;br /&gt;&lt;small style=&quot;background: transparent; border: none; font-size: 12px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Adam D’Angelo, I made a lot of the early Quora … (Sep 1, 2010)&lt;/small&gt;&lt;br /&gt;Yes, eventually. We haven’t implemented this yet because we’ve prioritized other things, but we will definitely do it in the future.&lt;/div&gt;&lt;/blockquote&gt;&lt;h3 id=&quot;webnode2-and-livenode&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Webnode2 And LiveNode&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Webnode2 and LiveNode are some of Quora’s internal systems, which were built for managing the content. Webnode2 generates HTML, CSS and JavaScript and is tightly coupled with LiveNode, which is responsible for managing the display of the content on the webpage. Charlie Cheever says that he were to start a similar project without LiveNode, then the&amp;nbsp;&lt;a href=&quot;http://www.quora.com/What-limitations-has-Quora-encountered-due-to-LiveNode-WebNode#answers&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;first thing he would do is rebuild it&lt;/a&gt;.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;They seem very pleased with the technology they have built and&amp;nbsp;&lt;a href=&quot;http://www.quora.com/What-limitations-has-Quora-encountered-due-to-LiveNode-WebNode#answers&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;struggled to find its weaknesses&lt;/a&gt;. One weakness is that it is tricky for LiveNode to keep track of what is happening within the browser as it pushes changes from the server. If users A and B are viewing the same question then ones interactions will affect the other. For instance, if user A up-votes an answer then that answer will be promoted and will visibly move up the page. This display change will be pushed over AJAX to user B’s browser. Any prior browser-side change that user B made, such as expanding a comments section, might be lost.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.quora.com/What-is-LiveNode-written-in&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;LiveNode is written in&lt;/a&gt;&amp;nbsp;Python, C++, and JavaScript.&amp;nbsp;&lt;a href=&quot;http://jquery.com/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;jQuery&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;http://cython.org/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Cython&lt;/a&gt;&amp;nbsp;is also used.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;While they&amp;nbsp;&lt;a href=&quot;http://www.quora.com/Is-Quora-planning-on-open-sourcing-LiveNode&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;would like to open-source LiveNode&lt;/a&gt;&amp;nbsp;and have tried to keep code separation, doing so right now would be too much work and would take time away from their main goal, which is making Quora better.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Charlie Cheever points out that webnode2 is&amp;nbsp;&lt;a href=&quot;http://www.quora.com/Quora-Infrastructure/What-is-webnode2&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;unrelated to the “free and easy website builder” called Webnode at webnode.com&lt;/a&gt;.&lt;/div&gt;&lt;h3 id=&quot;amazon-web-services&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Amazon Web Services&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Amazon EC2 and S3 is used for their hosting. While this is not as cost-effective in the long-term as running your own servers, it is perfectly designed for fast growing companies like Quora.&lt;/div&gt;&lt;h4 id=&quot;ubuntu-linux&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 17px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Ubuntu Linux&lt;/h4&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Quora uses Ubuntu Linux as its OS of choice. No major surprises there. It is easy to deploy and manage on Amazon EC2. Adam D’Angelo&amp;nbsp;&lt;a href=&quot;http://www.quora.com/Quora-Infrastructure/Which-Linux-flavor-does-Quora-use-Why&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;points out&lt;/a&gt;&amp;nbsp;that he used Debian Linux at high school and college and stuck with it because&amp;nbsp;&lt;a href=&quot;http://www.quora.com/Quora-Infrastructure/Which-Linux-flavor-does-Quora-use-Why&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;“it works and there hasn’t been a compelling reason to switch”&lt;/a&gt;.&lt;/div&gt;&lt;h4 id=&quot;static-content&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 17px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Static Content&lt;/h4&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;You only need to look at the source HTML of any Quora webpage to see that they are using Amazon’s distributed content delivery network,&amp;nbsp;&lt;a href=&quot;http://aws.amazon.com/cloudfront/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Cloudfront&lt;/a&gt;. URLs are in the form…&lt;/div&gt;&lt;pre style=&quot;background: rgb(249, 249, 249); border: 1px solid rgb(204, 204, 204); font-family: Monaco, monospace, Courier, &#39;Courier New&#39;; font-size: 0.9em; font-stretch: normal; line-height: 21px; margin-bottom: 21px; outline: none; overflow: auto; padding: 9px; vertical-align: baseline;&quot;&gt;http://d2o7bfz2il9cb7.&lt;strong style=&quot;background: transparent; border: none; font-size: 13.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;cloudfront&lt;/strong&gt;.net/main-thumb-670336-25-7kmigSSkkdusoE6gHRkdQsXfjuTCaxQs.jpeg&lt;/pre&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;CloudFront is used for all static images, CSS and JavaScript (except for Google’s Analytics JavaScript, which is hosted by Google).&amp;nbsp;&lt;a href=&quot;http://www.quora.com/How-is-Quora-doing-image-uploads-to-Amazon-S3&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Images are uploaded to the EC2 machine, then resized and uploaded to S3&lt;/a&gt;. This is managed using the&amp;nbsp;&lt;a href=&quot;http://aws.amazon.com/code/134&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Python S3 API&lt;/a&gt;.&lt;/div&gt;&lt;h3 id=&quot;haproxy-load-balancing&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;HAProxy Load-Balancing&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Quora uses&amp;nbsp;&lt;a href=&quot;http://haproxy.1wt.eu/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;HAProxy&lt;/a&gt;&amp;nbsp;at the front-line, which load-balances onto the distributed Nginx servers behind them.&lt;/div&gt;&lt;h3 id=&quot;nginx&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Nginx&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Behind the load-balancer,&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Nginx&lt;/a&gt;&amp;nbsp;is used as a reverse-proxy server onto the web-servers.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;To understand more about this setup I recommend reading “&lt;a href=&quot;http://kovyrin.net/2006/05/18/nginx-as-reverse-proxy/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Using Nginx As Reverse-Proxy Server On High-Loaded Sites&lt;/a&gt;“.&lt;/div&gt;&lt;h3 id=&quot;pylons-and-paste&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Pylons And Paste&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://pylonshq.com/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Pylons&lt;/a&gt;, a lightweight web framework, is used as their main web-server behind Nginx. They use the default&lt;a href=&quot;http://spacepants.org/blog/pylons-paste-stack&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Pylon + Paste stack&lt;/a&gt;.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://pylonshq.com/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Pylons&lt;/a&gt;&amp;nbsp;was selected much like you would select a pumpkin for Haloween. They scooped out the insides, such as templates and the ORM, and replaced it with their own technology, written in Python. This is where&lt;a href=&quot;http://www.quora.com/What-languages-and-frameworks-were-used-to-code-Quora&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;LiveNode and webnode2 reside&lt;/a&gt;.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.mochimedia.com/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;MochiMedia&lt;/a&gt;&amp;nbsp;was also one of the inspirations for using Pylons, since they were using it themselves.&lt;/div&gt;&lt;h3 id=&quot;python&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Python&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Coming from Facebook, it was a good bet that Charlie and Adam would choose PHP for their development language. As Adam points out, “&lt;a href=&quot;http://www.quora.com/Why-did-Quora-choose-Python-for-its-development&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Facebook is stuck on that for legacy reasons, not because it is the best choice right now&lt;/a&gt;“. From this experience they knew that choosing technologies, especially programming languages, for the long-run was very important. They also looked at C#, Java, and Scala.&amp;nbsp;&lt;a href=&quot;http://www.quora.com/Why-did-Quora-choose-Python-for-its-development&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Discounting Mono&lt;/a&gt;, C# would be a choice of more than just the language. It would require them to build on-top of a Microsoft stack. Python won over Java because it is more expressive and quicker to write code than Java. Scala was too new. Adam mentions&amp;nbsp;&lt;a href=&quot;http://www.quora.com/Why-did-Quora-choose-Python-for-its-development&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;speed and the lack of type-checking&lt;/a&gt;&amp;nbsp;as drawbacks with Python, but they both already knew the language reasonably well. Where Python lacks speed for performance critical backend components, they opt to write them in C++. They saw Ruby as a close match to Python, but their experience with Python and lack of experience in Ruby, made Python the winner. Python&amp;nbsp;&lt;em style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;2.6&lt;/em&gt;, to be precise.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Additional benefits for using Python are the fact that data-structures that map well to JSON, code readability, there is a large collection of libraries and the availability of good debuggers and reloaders. Browser-server communication using JSON is major component of what Quora does, so this was an important factor.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.quora.com/Adam-DAngelo/What-version-of-Python-are-you-programming-in-and-what-IDE-do-you-use&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;No IDEs&lt;/a&gt;&amp;nbsp;are used for development as most use the&amp;nbsp;&lt;a href=&quot;http://www.gnu.org/software/emacs/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Emacs text editor&lt;/a&gt;. Obviously this is personal choice, and would change as the team grows.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://codespeak.net/pypy/dist/pypy/doc/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;PyPy&lt;/a&gt;, a project that aims to produce a flexible and fast Python implementation, was also mentioned as something that might give them a speed-boost.&lt;/div&gt;&lt;h3 id=&quot;thrift&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Thrift&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://incubator.apache.org/thrift/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Thrift&lt;/a&gt;&amp;nbsp;is used for communications between backend systems. The Thrift service is written in C++.&lt;/div&gt;&lt;blockquote style=&quot;background: rgb(255, 255, 255); border: none; color: #555555; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; font-style: italic; line-height: 21px; margin: 0px 2.5em; outline: none; padding: 0px; quotes: none; vertical-align: baseline;&quot;&gt;&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.quora.com/Why-would-you-write-a-Thrift-service-in-C&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;&lt;img height=&quot;16&quot; src=&quot;http://www.quora.com/favicon.ico&quot; style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; max-width: 568px; outline: none; padding: 0px 10px 0px 0px; vertical-align: baseline;&quot; width=&quot;16&quot; /&gt;Why would you write a Thrift service in C++?&lt;/a&gt;&lt;br /&gt;&lt;small style=&quot;background: transparent; border: none; font-size: 12px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Adam D’Angelo, I’ve written a lot of Python, in… (Sep 4, 2010)&lt;/small&gt;&lt;br /&gt;Mainly if you want to keep data in memory between requests, and want to keep your Python code stateless. Writing a Python wrapper around a C library involves some memory management with reference counting that requires some understanding of the Python internals, but writing a thrift interface is simple. You also isolate failures this way – if the service goes down it won’t take the Python code down with it.&lt;/div&gt;&lt;/blockquote&gt;&lt;h3 id=&quot;tornado&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Tornado&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;The&amp;nbsp;&lt;a href=&quot;http://www.tornadoweb.org/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Tornado&lt;/a&gt;&amp;nbsp;web framework is used for live updating. This is their Comet server, which handles the large volumes of open connections used for long-polling and pushes updates to the browsers.&lt;/div&gt;&lt;h3 id=&quot;long-polling-comet&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Long Polling (Comet)&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Quora does not display just static web pages. Each page will update will new content as questions, answers and comments are submitted by other others. As Adam D’Angelo points out, one of the best ways to do this currently is with “long polling”. This is different to “polling”. With&amp;nbsp;&lt;em style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;polling&lt;/em&gt;&amp;nbsp;the browser will repeatedly send requests to the server saying “Any updates?” and the server will respond with “No”. A few seconds later it will ask again, “How about now?”. “No”. “How about now?”, “No, already!”. This puts the client (web-browser) in the driver’s seat. This is backwards because the client does not how long to wait before asking again. If the client asks the server too frequently then it will unduly overload the server. If it pings the server too infrequently, then server will be sitting on updates while it waits for the client to request them and the end-user will not see updates immediately.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Long polling, also known as&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Comet_(programming)&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Comet&lt;/a&gt;, puts the server in control, by making the client wait for responses. The conversation between the client and server is the same, but instead of the client waiting before making another request, the server waits before it makes the response. The server can keep the connection open for a long period of time (e.g. 60 seconds) while it waits to see if any updates come in. When updates do come in it can respond immediately to the client. On receiving the update, the client then immediately sends a new request for more updates. The server, once again, delays responding until it knows something worth telling the client or enough time has past that it would be rude not to respond.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;The benefit to long-polling is that there is less back-and-forth between the client and server. The server is in control of the timing, so updates to the browser can be made within milliseconds. This makes it ideal for chat applications or applications that want really snappy updates for their users.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;The down-side is that you are going have lots of open connections between the clients and your servers. If you have a million users (Quora will soon) and, if only 10% of them are online on your site, you will need an architecture that can hold open at least 100,000 concurrent connections. This assumes they only have one tab open to your site. Right now I have 7 tabs open for quora.com in my browser. Each tab usually has multiple connections open to quora.com. In short, Quora must maintain&amp;nbsp;&lt;em style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;a lot&lt;/em&gt;&amp;nbsp;of open connections.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;The good news is that there are technologies specifically designed for this. It costs very little to hold open connections in memory if you free up all the resources used for that connection. For instance, Nginx (Quora uses this for proxying requests) is a single-threaded event-based application and uses very little memory for each connection. Each Nginx process is actively dealing with only one connection at a time. This means it can scale to tens of thousands of concurrent connections.&lt;/div&gt;&lt;blockquote style=&quot;background: rgb(255, 255, 255); border: none; color: #555555; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; font-style: italic; line-height: 21px; margin: 0px 2.5em; outline: none; padding: 0px; quotes: none; vertical-align: baseline;&quot;&gt;&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.quora.com/How-do-you-push-messages-back-to-a-web-browser-client-through-AJAX-Is-there-any-way-to-do-this-without-having-the-client-constantly-polling-the-server-for-updates&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;&lt;img height=&quot;16&quot; src=&quot;http://www.quora.com/favicon.ico&quot; style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; max-width: 568px; outline: none; padding: 0px 10px 0px 0px; vertical-align: baseline;&quot; width=&quot;16&quot; /&gt;How do you push messages back to a web-browser client through AJAX? Is there any way to do this without having the client constantly polling the server for updates?&lt;/a&gt;&lt;br /&gt;&lt;small style=&quot;background: transparent; border: none; font-size: 12px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Adam D’Angelo, Quora (Sep 29, 2010)&lt;/small&gt;&lt;br /&gt;There is no reliable way to do this without having the client polling the server. However, you can make the server stall its responses (50 seconds is a safe bet) and then complete them when a message is ready for the client. This is called “long polling” and it’s how Quora, Gmail, Meebo, etc all handle the problem.&lt;/div&gt;&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;If you have a specialized server that uses epoll or kqueue, you should be able to hold on the order of 100k users per server (depending on how many messages are going). This is called the “c10k” problem. http://www.kegel.com/c10k.html&lt;/div&gt;&lt;/blockquote&gt;&lt;h3 id=&quot;mysql&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;MySQL&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Just like Facebook, where co-founder Adam D’Angelo previously worked, Quora heavily uses MySQL. In answer to the Quora question “&lt;a href=&quot;http://www.quora.com/When-Adam-DAngelo-says-partition-your-data-at-the-application-level-what-exactly-does-he-mean&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;When Adam D’Angelo says “partition your data at the application level”, what exactly does he mean?&lt;/a&gt;“, D’Angelo goes into the details of how to use MySQL (or relational-databases generally) as a distributed data-store.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;The basic advice is to only partition data if necessary, keep data on one machine if possible and use a hash of the primary key to partition larger datasets across multiple databases. Joins must be avoided. He sites FriendFeed’s architecture as a good example of this. FriendFeed’s architecture is described by Bret Taylor in his post “&lt;a href=&quot;http://bret.appspot.com/entry/how-friendfeed-uses-mysql&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;How FriendFeed uses MySQL to store schema-less data&lt;/a&gt;“. D’Angelo also&amp;nbsp;&lt;a href=&quot;http://www.quora.com/NoSQL/In-what-parts-of-a-social-site-with-concert-listings-should-one-use-a-NoSQL-DB-versus-a-SQL-DB&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;states&lt;/a&gt;&amp;nbsp;that you should not use a NoSQL database for a social site until you have millions of users.&lt;/div&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;It is not only Quora and FriendFeed who are heavily using MySQL. Ever heard of “Google”? It is hard to imagine, since everything Google does has to scale so well, but in&amp;nbsp;&lt;a href=&quot;http://googlecode.blogspot.com/2007/04/google-releases-patches-that-enhance.html&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;the words of Google&lt;/a&gt;, “Google uses MySQL [...] in some of the applications that we build that are not search related”. Google has released&amp;nbsp;&lt;a href=&quot;http://code.google.com/p/google-mysql-tools/wiki/Mysql4Patches&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;patches&lt;/a&gt;&amp;nbsp;for MySQL related to replication, syncing, monitoring and faster master promotion.&lt;/div&gt;&lt;blockquote style=&quot;background: rgb(255, 255, 255); border: none; color: #555555; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; font-style: italic; line-height: 21px; margin: 0px 2.5em; outline: none; padding: 0px; quotes: none; vertical-align: baseline;&quot;&gt;&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.quora.com/How-does-one-evaluate-if-a-database-is-efficient-enough-to-not-crash-as-its-put-under-increasing-load&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;&lt;img height=&quot;16&quot; src=&quot;http://www.quora.com/favicon.ico&quot; style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; max-width: 568px; outline: none; padding: 0px 10px 0px 0px; vertical-align: baseline;&quot; width=&quot;16&quot; /&gt;How does one evaluate if a database is efficient enough to not crash as it’s put under increasing load?&lt;/a&gt;&lt;br /&gt;&lt;small style=&quot;background: transparent; border: none; font-size: 12px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Adam D’Angelo, Quora (Oct 10, 2010)&lt;/small&gt;&lt;br /&gt;One option is to simulate some load. Write a script that mimics the kinds of queries your application will be doing, and make sure it can handle the amount of load you want it to be ready for (especially as the size of the dataset changes).&lt;/div&gt;&lt;/blockquote&gt;&lt;h3 id=&quot;memcached&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Memcached&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://memcached.org/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Memcached&lt;/a&gt;&amp;nbsp;is used as a caching layer in front of MySQL.&lt;/div&gt;&lt;h3 id=&quot;git&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Git&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://git-scm.com/&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Git&lt;/a&gt;&amp;nbsp;is&amp;nbsp;&lt;a href=&quot;http://www.quora.com/What-languages-and-frameworks-were-used-to-code-Quora&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;used for version control&lt;/a&gt;.&lt;/div&gt;&lt;h3 id=&quot;javascript-placement&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 19px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;JavaScript Placement&lt;/h3&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;If you look at Quora’s source you will see that the JavaScript comes at the end of the page. Charlie Cheever&lt;a href=&quot;http://www.quora.com/Why-is-the-Quora-website-so-fast&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;suggests&lt;/a&gt;&amp;nbsp;that this give the feeling of a quicker loading page, since the browser has content to display before the JavaScript has be seen.&lt;/div&gt;&lt;h2 id=&quot;charlie-cheever-follows-14-rules-for-faster-loading-web-sites&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 21px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Charlie Cheever Follows “14 Rules for Faster-Loading Web Sites”&lt;/h2&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Steve Souders, author of High Performance Web Sites and Even Faster Web Sites, lists the following&amp;nbsp;&lt;a href=&quot;http://stevesouders.com/hpws/rules.php&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;rules for making websites faster&lt;/a&gt;. This list is mentioned by Charlie Cheever, the co-founder of Quora, as one of the reasons for Quora’s speed.&lt;/div&gt;&lt;blockquote style=&quot;background: rgb(255, 255, 255); border: none; color: #555555; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; font-style: italic; line-height: 21px; margin: 0px 2.5em; outline: none; padding: 0px; quotes: none; vertical-align: baseline;&quot;&gt;&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;“One resource we used as a guide is Steve Souders’ list of rules for high performance websites:&lt;a href=&quot;http://stevesouders.com/hpws/rules.php&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;http://stevesouders.com/hpws/rules.php&lt;/a&gt;”&lt;br /&gt;&lt;small style=&quot;background: transparent; border: none; font-size: 12px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.quora.com/Why-is-the-Quora-website-so-fast&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;– Charlie Cheever, Quora&lt;/a&gt;&lt;/small&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div style=&quot;background: transparent; border: none; float: left; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Steve Souders’ 14 rules are…&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;/div&gt;&lt;ul style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; list-style: square; margin: 0px 0px 21px 2.5em; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Make Fewer HTTP Requests&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Use a Content Delivery Network&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Add an Expires Header&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Gzip Components&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Put Stylesheets at the Top&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Put Scripts at the Bottom&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Avoid CSS Expressions&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Make JavaScript and CSS External&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Reduce DNS Lookups&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Minify JavaScript&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Avoid Redirects&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Remove Duplicate Scripts&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Configure ETags&lt;/li&gt;&lt;li style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Make AJAX Cacheable&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style=&quot;background: transparent; border: none; float: left; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px 0px 0px 80px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0596529309?ie=UTF8&amp;amp;tag=getafil-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596529309&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://images-na.ssl-images-amazon.com/images/I/41COtT-V1UL._SL160_.jpg&quot; style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; max-width: 568px; outline: none; padding: 0px 25px 0px 0px; vertical-align: baseline;&quot; /&gt;&lt;/a&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; height=&quot;1&quot; src=&quot;http://www.assoc-amazon.com/e/ir?t=getafil-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0596529309&quot; style=&quot;background: transparent; border: none !important; font-size: 15.3333330154419px; margin: 0px !important; max-width: 568px; outline: none; padding: 0px 25px 0px 0px; vertical-align: baseline;&quot; width=&quot;1&quot; /&gt;&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://www.amazon.com/gp/product/0596522304?ie=UTF8&amp;amp;tag=getafil-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596522304&quot; style=&quot;background: transparent; border: none; color: #551a8b; cursor: pointer; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://images-na.ssl-images-amazon.com/images/I/41vfOvQugoL._SL160_.jpg&quot; style=&quot;background: transparent; border: none; font-size: 15.3333330154419px; margin: 0px; max-width: 568px; outline: none; padding: 0px 25px 0px 0px; vertical-align: baseline;&quot; /&gt;&lt;/a&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; height=&quot;1&quot; src=&quot;http://www.assoc-amazon.com/e/ir?t=getafil-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0596522304&quot; style=&quot;background: transparent; border: none !important; font-size: 15.3333330154419px; margin: 0px !important; max-width: 568px; outline: none; padding: 0px 25px 0px 0px; vertical-align: baseline;&quot; width=&quot;1&quot; /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;background: transparent; border: none; clear: both; font-size: 15.3333330154419px; margin: 0px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;conclusion&quot; style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 21px; line-height: 21px; margin: 0px 0px 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Conclusion&lt;/h2&gt;&lt;div style=&quot;background: rgb(255, 255, 255); border: none; font-family: Arial, Georgia, Times, &#39;Times New Roman&#39;, serif; font-size: 15.3333330154419px; line-height: 21px; margin-bottom: 21px; outline: none; padding: 0px; vertical-align: baseline;&quot;&gt;Quora is a great example of a modern tech start-up. They are very small team who understand the technologies they are using very well. They have made considered choices in the technology they have selected and have a good vision of which components would be better written from scratch. They seem keen to share these in-house technologies with the open-source community and I look forward to when they have the time to make this a reality.&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/12/quoras-technology-examined.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-2717757627852416946</guid><pubDate>Thu, 18 Dec 2014 07:13:00 +0000</pubDate><atom:updated>2014-12-18T15:13:45.417+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Web Server</category><title>Using Nginx As Reverse-Proxy Server On High-Loaded Sites</title><description>&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;Source:&amp;nbsp;&lt;a href=&quot;http://kovyrin.net/2006/05/18/nginx-as-reverse-proxy/&quot;&gt;http://kovyrin.net/2006/05/18/nginx-as-reverse-proxy/&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;Two weeks ago we have started new version of one of our primary web projects and have started very massive advertisement campaign to promote this web site. As the result of that advertisements, our outgoing traffic has been increased to 200-250Mbit/s from only one server! In this article I will describe, how to build stable and efficient web site with two-layer architecture (with frontend + backend web servers) or how to modify your current server configuration to get additional resources to handle more requests.&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;&lt;span id=&quot;more-48&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;First of all, let me describe general structure of web-server and how it handles clients requests:&lt;/div&gt;&lt;ol style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;&lt;li&gt;Client initiates request to your server.&lt;/li&gt;&lt;li&gt;His browser connects to your server.&lt;/li&gt;&lt;li&gt;Your server (as for Apache) creates new thread/process to handle request.&lt;/li&gt;&lt;li&gt;If client requested dynamic content, web server spawns CGI process or executes dynamic content handling module (i.e. mod_php) and waits while request will be processed. When it receives result web-page, it sends it to client.&lt;/li&gt;&lt;li&gt;If client asked for some static file, web server sends this file to client&lt;/li&gt;&lt;li&gt;Client’s browser receives answer, closes connection to web server and displays content.&lt;/li&gt;&lt;/ol&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;As you can see, when there are many requests coming to your server, your server needs to create many parallel threads/processes and keep them running while client will close connection. If client has slow connection, web server process will wait too long and resource consumption will increase very fast.&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;What we can do in such situation? Simple solution is to buy more memory and more CPUs for your server and wait while web server load will crash your server. But there is more efficient solution! You can simply put some small piece of software (nginx, for example) behind your big web server and let it handle all requests to static content and to pass all dynamic requests to primary web-server. With this solution your big server will spawn additional threads/processes only for static pages and it will return answers to small frontend very fast and then can free resources to use them to handle another queries. Small frontend can wait very long time while client will receive his content and will close connection – backend server will not consume resources for such long time!&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;Here you can see simple diagram of proposed web server configuration:&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;&lt;a href=&quot;http://kovyrin.net/wp-content/uploads/2006/05/general_c.png&quot; rel=&quot;lightbox&quot; style=&quot;color: #7398a3; text-decoration: none;&quot; title=&quot;Web-Server Structure Diagram&quot;&gt;&lt;br /&gt;&lt;img alt=&quot;General Data Flow Diagram&quot; scale=&quot;0&quot; src=&quot;http://kovyrin.net/wp-content/uploads/2006/05/general_c.thumbnail.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;As additional benefit from such configuration you can get very useful feature of managed downloads that will be described below.&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;If your server contains some static resources, which can be downloaded not by all users (content provider can provide mp3 files only to users with positive balance or some site can provide downloads only to logged-in users), in generic configuration you need to create some script to handle this downloads and to create some ugly links like&amp;nbsp;&lt;tt&gt;http://some.service.com/down.php?file=xxx.mp3&lt;/tt&gt;&amp;nbsp;and additionally your users will not be able to resume downloads (except such cases when your script so complex, that it handles Ranges HTTP-header)…&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;In configuration with nginx frontend, you can create simple URL-rewriting rule, that will pass all requests to pretty URLs like&amp;nbsp;&lt;tt&gt;http://your.cool-service.com/files/cool.mp3&lt;/tt&gt;&amp;nbsp;to some simple script /down.php automatically and, if this script has returned X-Accel-Redirect header, will send requested file to user automatically with Ranges header support and when user will download his cool content, your backend server can handle other requests. Your users even will not know that your script controls their downloads. Simple diagram for described algorithm is following:&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;&lt;a href=&quot;http://kovyrin.net/wp-content/uploads/2006/05/algorithm_c.png&quot; rel=&quot;lightbox&quot; style=&quot;color: #7398a3; text-decoration: none;&quot;&gt;&lt;br /&gt;&lt;img alt=&quot;Functional Algorithm&quot; scale=&quot;0&quot; src=&quot;http://kovyrin.net/wp-content/uploads/2006/05/algorithm_c.thumbnail.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;Let me bring your attention to interesting fact: If you only accelerate your site with described technique and do not want to create download control system,&amp;nbsp;&lt;b&gt;you do not need to modify any of your scripts on your backend server!&lt;/b&gt;&amp;nbsp;They will work as in original configuration!&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;So, the last thing you need to boost your web server with nginx reverse proxying technique is following configuration file snipet:&lt;/div&gt;&lt;div class=&quot;codecolorer-container nginx twitlight&quot; style=&quot;background-color: #141414; border: 1px solid rgb(159, 159, 159); color: #f8f8f8; font-family: Monaco, &#39;Lucida Console&#39;, monospace; font-size: 13px; font-stretch: normal; height: 300px; line-height: 1.4em; margin: 10px 0px; overflow: auto; padding: 0px; white-space: nowrap;&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;border: 0px; font-size: 13px; font-stretch: normal; line-height: 1.4em;&quot;&gt;&lt;tbody style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;&lt;tr style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;&lt;td class=&quot;line-numbers&quot; style=&quot;background-color: #eeeeee; border-right-color: rgb(159, 159, 159); border-right-style: solid; border-width: 0px 1px 0px 0px; color: #888888; font-stretch: normal; line-height: 1.4em; margin: 0px; padding: 5px; text-align: right;&quot;&gt;&lt;div style=&quot;font-stretch: normal; line-height: 1.4em; width: 23px;&quot;&gt;1&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;2&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;3&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;4&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;5&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;6&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;7&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;8&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;9&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;10&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;11&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;12&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;13&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;14&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;15&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;16&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;17&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;18&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;19&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;20&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;21&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;22&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;23&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;24&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;25&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;26&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;27&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;28&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;29&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;30&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;31&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;32&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;33&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;34&lt;/div&gt;&lt;/td&gt;&lt;td style=&quot;border: 0px; font-stretch: normal; line-height: 1.4em; margin: 0px; padding: 0px;&quot;&gt;&lt;div class=&quot;nginx codecolorer&quot; style=&quot;color: #f8f8f8; font-stretch: normal; line-height: 1.4em; padding: 5px;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw1&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;server&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;br0&quot; style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;{&lt;/span&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;listen&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;nu0&quot; style=&quot;color: #cf6a4c; font-stretch: normal; line-height: 1.4em;&quot;&gt;80&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;server_name&lt;/span&gt;&amp;nbsp;&amp;nbsp;some-&lt;span class=&quot;kw1&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;server&lt;/span&gt;.com www.server-name.com;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;access_log&lt;/span&gt;&amp;nbsp;&amp;nbsp;logs/&lt;span class=&quot;kw4&quot; style=&quot;color: #f9ee98; font-stretch: normal; line-height: 1.4em;&quot;&gt;host&lt;/span&gt;.access.log &amp;nbsp;main;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;co1&quot; style=&quot;color: #5f5a60; font-stretch: normal; font-style: italic; line-height: 1.4em;&quot;&gt;# Main location&lt;/span&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw1&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;location&lt;/span&gt;&amp;nbsp;/&amp;nbsp;&lt;span class=&quot;br0&quot; style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;{&lt;/span&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_pass&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw1&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;http&lt;/span&gt;://127.0.0.1:&lt;span class=&quot;nu0&quot; style=&quot;color: #cf6a4c; font-stretch: normal; line-height: 1.4em;&quot;&gt;8080&lt;/span&gt;/;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_redirect&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw3&quot; style=&quot;color: #f9ee98; font-stretch: normal; line-height: 1.4em;&quot;&gt;off&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_set_header&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw4&quot; style=&quot;color: #f9ee98; font-stretch: normal; line-height: 1.4em;&quot;&gt;Host&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;re0&quot; style=&quot;color: #7587a6; font-stretch: normal; line-height: 1.4em;&quot;&gt;$host&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_set_header&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw4&quot; style=&quot;color: #f9ee98; font-stretch: normal; line-height: 1.4em;&quot;&gt;X-Real-IP&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class=&quot;re0&quot; style=&quot;color: #7587a6; font-stretch: normal; line-height: 1.4em;&quot;&gt;$remote_addr&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_set_header&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw4&quot; style=&quot;color: #f9ee98; font-stretch: normal; line-height: 1.4em;&quot;&gt;X-Forwarded-For&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span class=&quot;re0&quot; style=&quot;color: #7587a6; font-stretch: normal; line-height: 1.4em;&quot;&gt;$proxy_add_x_forwarded_for&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;client_max_body_size&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;re1&quot; style=&quot;color: #7587a6; font-stretch: normal; line-height: 1.4em;&quot;&gt;10m&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;client_body_buffer_size&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span class=&quot;re1&quot; style=&quot;color: #7587a6; font-stretch: normal; line-height: 1.4em;&quot;&gt;128k&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_connect_timeout&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class=&quot;nu0&quot; style=&quot;color: #cf6a4c; font-stretch: normal; line-height: 1.4em;&quot;&gt;90&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_send_timeout&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;nu0&quot; style=&quot;color: #cf6a4c; font-stretch: normal; line-height: 1.4em;&quot;&gt;90&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_read_timeout&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;nu0&quot; style=&quot;color: #cf6a4c; font-stretch: normal; line-height: 1.4em;&quot;&gt;90&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_buffer_size&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class=&quot;re1&quot; style=&quot;color: #7587a6; font-stretch: normal; line-height: 1.4em;&quot;&gt;4k&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_buffers&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span class=&quot;nu0&quot; style=&quot;color: #cf6a4c; font-stretch: normal; line-height: 1.4em;&quot;&gt;4&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;re1&quot; style=&quot;color: #7587a6; font-stretch: normal; line-height: 1.4em;&quot;&gt;32k&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_busy_buffers_size&lt;/span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;span class=&quot;re1&quot; style=&quot;color: #7587a6; font-stretch: normal; line-height: 1.4em;&quot;&gt;64k&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;proxy_temp_file_write_size&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;re1&quot; style=&quot;color: #7587a6; font-stretch: normal; line-height: 1.4em;&quot;&gt;64k&lt;/span&gt;;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;br0&quot; style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;}&lt;/span&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;co1&quot; style=&quot;color: #5f5a60; font-stretch: normal; font-style: italic; line-height: 1.4em;&quot;&gt;# Static files location&lt;/span&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw1&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;location&lt;/span&gt;&amp;nbsp;~* ^.+.&lt;span class=&quot;br0&quot; style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;(&lt;/span&gt;jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js&lt;span class=&quot;br0&quot; style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;)&lt;/span&gt;$&amp;nbsp;&lt;span class=&quot;br0&quot; style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;{&lt;/span&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;kw2&quot; style=&quot;color: #cda869; font-stretch: normal; line-height: 1.4em;&quot;&gt;root&lt;/span&gt;&amp;nbsp;&amp;nbsp; /spool/www/members_ng;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;br0&quot; style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;}&lt;/span&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&lt;br style=&quot;font-stretch: normal; line-height: 1.4em;&quot; /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class=&quot;br0&quot; style=&quot;font-stretch: normal; line-height: 1.4em;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;Full version of sample config file you can get&amp;nbsp;&lt;a href=&quot;http://kovyrin.net/files/nginx-conf/rproxy-boost.nginx.conf&quot; style=&quot;color: #7398a3; text-decoration: none;&quot;&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;&lt;i&gt;Notice:&lt;/i&gt;&amp;nbsp;If your backend scripts are using user IP addresses for some purposes, you will need to install&lt;a href=&quot;http://stderr.net/apache/rpaf/&quot; style=&quot;color: #7398a3; text-decoration: none;&quot; target=&quot;_blank&quot;&gt;mod_rpaf module&lt;/a&gt;&amp;nbsp;to use X-Real-IP header provided by nginx instead of real user’s IP address.&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;That is all! Now you can simply install nginx on your server, configure it and your server will be able to handle more traffic with the less resources that it uses now! Everything will be done transparently for your currently written scripts and if you want, you will be able to provide download handling with simple trick, that I will describe in my next post&amp;nbsp;&lt;img alt=&quot;;-)&quot; class=&quot;wp-smiley&quot; scale=&quot;0&quot; src=&quot;http://kovyrin.net/wp-includes/images/smilies/icon_wink.gif&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;color: #444444; font-family: &#39;Open Sans&#39;, sans-serif; font-size: 16px; line-height: 25.6000003814697px;&quot;&gt;If you have some questions, do not hesitate to ask them here in comments – I will try to answer all of them. If you liked this article, you can support author by taking a look at advertisements on this page or simply&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/12/using-nginx-as-reverse-proxy-server-on.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-2090022328247213728</guid><pubDate>Thu, 18 Dec 2014 07:00:00 +0000</pubDate><atom:updated>2014-12-18T15:00:36.038+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Database</category><title>How FriendFeed uses MySQL to store schema-less data</title><description>&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Raleway, sans-serif; font-size: 14px; font-weight: 300; margin: 0px 0px 12px; text-transform: uppercase;&quot;&gt;Source:&amp;nbsp;&lt;a href=&quot;http://backchannel.org/blog/friendfeed-schemaless-mysql&quot;&gt;http://backchannel.org/blog/friendfeed-schemaless-mysql&lt;/a&gt;&lt;/div&gt;&lt;h2 style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Raleway, sans-serif; font-size: 14px; font-weight: 300; margin: 0px 0px 12px; text-transform: uppercase;&quot;&gt;BACKGROUND&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;We use MySQL for storing all of the data in&amp;nbsp;&lt;a href=&quot;http://friendfeed.com/&quot; style=&quot;box-sizing: border-box; color: #064c82;&quot;&gt;FriendFeed&lt;/a&gt;. Our database has grown a lot as our user base has grown. We now store over 250 million entries and a bunch of other data, from comments and &quot;likes&quot; to friend lists.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;As our database has grown, we have tried to iteratively deal with the scaling issues that come with rapid growth. We did the typical things, like using read slaves and memcache to increase read throughput and sharding our database to improve write throughput. However, as we grew, scaling our existing features to accomodate more traffic turned out to be much less of an issue than adding&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;new&lt;/em&gt;&amp;nbsp;features.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;In particular, making schema changes or adding indexes to a database with more than 10 - 20 million rows completely locks the database for hours at a time. Removing old indexes takes just as much time, and not removing them hurts performance because the database will continue to read and write to those unused blocks on every&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;INSERT&lt;/code&gt;, pushing important blocks out of memory. There are complex operational procedures you can do to circumvent these problems (like setting up the new index on a slave, and then swapping the slave and the master), but those procedures are so error prone and heavyweight, they implicitly discouraged our adding features that would require schema/index changes. Since our databases are all heavily sharded, the relational features of MySQL like&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;JOIN&lt;/code&gt;&amp;nbsp;have never been useful to us, so we decided to look outside of the realm of RDBMS.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;Lots of projects exist designed to tackle the problem storing data with flexible schemas and building new indexes on the fly (e.g.,&amp;nbsp;&lt;a href=&quot;http://couchdb.apache.org/&quot; style=&quot;box-sizing: border-box; color: #064c82;&quot;&gt;CouchDB&lt;/a&gt;). However, none of them seemed widely-used enough by large sites to inspire confidence. In the tests we read about and ran ourselves, none of the projects were stable or battle-tested enough for our needs (see&amp;nbsp;&lt;a href=&quot;http://userprimary.net/user/2007/12/16/a-quick-look-at-couchdb-performance/&quot; style=&quot;box-sizing: border-box; color: #064c82;&quot;&gt;this somewhat outdated article on CouchDB&lt;/a&gt;, for example). MySQL works. It doesn&#39;t corrupt data. Replication works. We understand its limitations already. We like MySQL for storage, just not RDBMS usage patterns.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;After some deliberation, we decided to implement a &quot;schema-less&quot; storage system on top of MySQL rather than use a completely new storage system. This post attempts to describe the high-level details of the system. We are curious how other large sites have tackled these problems, and we thought some of the design work we have done might be useful to other developers.&lt;/div&gt;&lt;h2 style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Raleway, sans-serif; font-size: 14px; font-weight: 300; margin: 0px 0px 12px; text-transform: uppercase;&quot;&gt;OVERVIEW&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;Our datastore stores schema-less bags of properties (e.g., JSON objects or Python dictionaries). The only required property of stored entities is&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;id&lt;/code&gt;, a 16-byte UUID. The rest of the entity is opaque as far as the datastore is concerned. We can change the &quot;schema&quot; simply by storing new properties.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;We index data in these entities by storing indexes in separate MySQL tables. If we want to index three properties in each entity, we will have three MySQL tables - one for each index. If we want to stop using an index, we stop writing to that table from our code and, optionally, drop the table from MySQL. If we want a new index, we make a new MySQL table for that index and run a process to asynchronously populate the index without disrupting our live service.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;As a result, we end up having more tables than we had before, but adding and removing indexes is easy. We have heavily optimized the process that populates new indexes (which we call &quot;The Cleaner&quot;) so that it fills new indexes rapidly without disrupting the site. We can store new properties and index them in a day&#39;s time rather than a week&#39;s time, and we don&#39;t need to swap MySQL masters and slaves or do any other scary operational work to make it happen.&lt;/div&gt;&lt;h2 style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Raleway, sans-serif; font-size: 14px; font-weight: 300; margin: 0px 0px 12px; text-transform: uppercase;&quot;&gt;DETAILS&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;In MySQL, our entities are stored in a table that looks like this:&lt;/div&gt;&lt;pre style=&quot;background: rgb(238, 238, 238); border-radius: 3px; box-sizing: border-box; color: #333333; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 14px; margin-bottom: 21px; padding: 3px;&quot;&gt;&lt;code style=&quot;background: rgb(250, 250, 250); border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 13px; margin: 0px; overflow: auto; padding: 10px;&quot;&gt;CREATE TABLE entities (&lt;br /&gt;    added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,&lt;br /&gt;    id BINARY(16) NOT NULL,&lt;br /&gt;    updated TIMESTAMP NOT NULL,&lt;br /&gt;    body MEDIUMBLOB,&lt;br /&gt;    UNIQUE KEY (id),&lt;br /&gt;    KEY (updated)&lt;br /&gt;) ENGINE=InnoDB;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;The&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;added_id&lt;/code&gt;&amp;nbsp;column is present because InnoDB stores data rows physically in primary key order. The&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;AUTO_INCREMENT&lt;/code&gt;&amp;nbsp;primary key ensures new entities are written sequentially on disk after old entities, which helps for both read and write locality (new entities tend to be read more frequently than old entities since FriendFeed pages are ordered reverse-chronologically). Entity bodies are stored as zlib-compressed,&amp;nbsp;&lt;a href=&quot;http://docs.python.org/library/pickle.html&quot; style=&quot;box-sizing: border-box; color: #064c82;&quot;&gt;pickled&lt;/a&gt;&amp;nbsp;Python dictionaries.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;Indexes are stored in separate tables. To create a new index, we create a new table storing the attributes we want to index on all of our database shards. For example, a typical entity in FriendFeed might look like this:&lt;/div&gt;&lt;pre style=&quot;background: rgb(238, 238, 238); border-radius: 3px; box-sizing: border-box; color: #333333; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 14px; margin-bottom: 21px; padding: 3px;&quot;&gt;&lt;code style=&quot;background: rgb(250, 250, 250); border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 13px; margin: 0px; overflow: auto; padding: 10px;&quot;&gt;{&lt;br /&gt;    &quot;id&quot;: &quot;71f0c4d2291844cca2df6f486e96e37c&quot;,&lt;br /&gt;    &quot;user_id&quot;: &quot;f48b0440ca0c4f66991c4d5f6a078eaf&quot;,&lt;br /&gt;    &quot;feed_id&quot;: &quot;f48b0440ca0c4f66991c4d5f6a078eaf&quot;,&lt;br /&gt;    &quot;title&quot;: &quot;We just launched a new backend system for FriendFeed!&quot;,&lt;br /&gt;    &quot;link&quot;: &quot;http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c&quot;,&lt;br /&gt;    &quot;published&quot;: 1235697046,&lt;br /&gt;    &quot;updated&quot;: 1235697046,&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;We want to index the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;user_id&lt;/code&gt;&amp;nbsp;attribute of these entities so we can render a page of all the entities a given user has posted. Our index table looks like this:&lt;/div&gt;&lt;pre style=&quot;background: rgb(238, 238, 238); border-radius: 3px; box-sizing: border-box; color: #333333; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 14px; margin-bottom: 21px; padding: 3px;&quot;&gt;&lt;code style=&quot;background: rgb(250, 250, 250); border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 13px; margin: 0px; overflow: auto; padding: 10px;&quot;&gt;CREATE TABLE index_user_id (&lt;br /&gt;    user_id BINARY(16) NOT NULL,&lt;br /&gt;    entity_id BINARY(16) NOT NULL UNIQUE,&lt;br /&gt;    PRIMARY KEY (user_id, entity_id)&lt;br /&gt;) ENGINE=InnoDB;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;Our datastore automatically maintains indexes on your behalf, so to start an instance of our datastore that stores entities like the structure above with the given indexes, you would write (in Python):&lt;/div&gt;&lt;pre style=&quot;background: rgb(238, 238, 238); border-radius: 3px; box-sizing: border-box; color: #333333; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 14px; margin-bottom: 21px; padding: 3px;&quot;&gt;&lt;code style=&quot;background: rgb(250, 250, 250); border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 13px; margin: 0px; overflow: auto; padding: 10px;&quot;&gt;user_id_index = friendfeed.datastore.Index(&lt;br /&gt;    table=&quot;index_user_id&quot;, properties=[&quot;user_id&quot;], shard_on=&quot;user_id&quot;)&lt;br /&gt;datastore = friendfeed.datastore.DataStore(&lt;br /&gt;    mysql_shards=[&quot;127.0.0.1:3306&quot;, &quot;127.0.0.1:3307&quot;],&lt;br /&gt;    indexes=[user_id_index])&lt;br /&gt;&lt;br /&gt;new_entity = {&lt;br /&gt;    &quot;id&quot;: binascii.a2b_hex(&quot;71f0c4d2291844cca2df6f486e96e37c&quot;),&lt;br /&gt;    &quot;user_id&quot;: binascii.a2b_hex(&quot;f48b0440ca0c4f66991c4d5f6a078eaf&quot;),&lt;br /&gt;    &quot;feed_id&quot;: binascii.a2b_hex(&quot;f48b0440ca0c4f66991c4d5f6a078eaf&quot;),&lt;br /&gt;    &quot;title&quot;: u&quot;We just launched a new backend system for FriendFeed!&quot;,&lt;br /&gt;    &quot;link&quot;: u&quot;http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c&quot;,&lt;br /&gt;    &quot;published&quot;: 1235697046,&lt;br /&gt;    &quot;updated&quot;: 1235697046,&lt;br /&gt;}&lt;br /&gt;datastore.put(new_entity)&lt;br /&gt;entity = datastore.get(binascii.a2b_hex(&quot;71f0c4d2291844cca2df6f486e96e37c&quot;))&lt;br /&gt;entity = user_id_index.get_all(datastore, user_id=binascii.a2b_hex(&quot;f48b0440ca0c4f66991c4d5f6a078eaf&quot;))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;The&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;Index&lt;/code&gt;&amp;nbsp;class above looks for the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;user_id&lt;/code&gt;&amp;nbsp;property in all entities and automatically maintains the index in the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;index_user_id&lt;/code&gt;&amp;nbsp;table. Since our database is sharded, the&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;shard_on&lt;/code&gt;&amp;nbsp;argument is used to determine which shard the index gets stored on (in this case,&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;entity[&quot;user_id&quot;] % num_shards&lt;/code&gt;).&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;You can query an index using the index instance (see&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;user_id_index.get_all&lt;/code&gt;above). The datastore code does the &quot;join&quot; between the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;index_user_id&lt;/code&gt;&amp;nbsp;table and the&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;entities&lt;/code&gt;&amp;nbsp;table in Python, by first querying the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;index_user_id&lt;/code&gt;&amp;nbsp;tables on all database shards to get a list of entity IDs and then fetching those entity IDs from the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;entities&lt;/code&gt;table.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;To add a new index, e.g., on the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;link&lt;/code&gt;&amp;nbsp;property, we would create a new table:&lt;/div&gt;&lt;pre style=&quot;background: rgb(238, 238, 238); border-radius: 3px; box-sizing: border-box; color: #333333; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 14px; margin-bottom: 21px; padding: 3px;&quot;&gt;&lt;code style=&quot;background: rgb(250, 250, 250); border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 13px; margin: 0px; overflow: auto; padding: 10px;&quot;&gt;CREATE TABLE index_link (&lt;br /&gt;    link VARCHAR(735) NOT NULL,&lt;br /&gt;    entity_id BINARY(16) NOT NULL UNIQUE,&lt;br /&gt;    PRIMARY KEY (link, entity_id)&lt;br /&gt;) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;We would change our datastore initialization code to include this new index:&lt;/div&gt;&lt;pre style=&quot;background: rgb(238, 238, 238); border-radius: 3px; box-sizing: border-box; color: #333333; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 14px; margin-bottom: 21px; padding: 3px;&quot;&gt;&lt;code style=&quot;background: rgb(250, 250, 250); border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 13px; margin: 0px; overflow: auto; padding: 10px;&quot;&gt;user_id_index = friendfeed.datastore.Index(&lt;br /&gt;    table=&quot;index_user_id&quot;, properties=[&quot;user_id&quot;], shard_on=&quot;user_id&quot;)&lt;br /&gt;link_index = friendfeed.datastore.Index(&lt;br /&gt;    table=&quot;index_link&quot;, properties=[&quot;link&quot;], shard_on=&quot;link&quot;)&lt;br /&gt;datastore = friendfeed.datastore.DataStore(&lt;br /&gt;    mysql_shards=[&quot;127.0.0.1:3306&quot;, &quot;127.0.0.1:3307&quot;],&lt;br /&gt;    indexes=[user_id_index, link_index])&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;And we could populate the index asynchronously (even while serving live traffic) with:&lt;/div&gt;&lt;pre style=&quot;background: rgb(238, 238, 238); border-radius: 3px; box-sizing: border-box; color: #333333; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 14px; margin-bottom: 21px; padding: 3px;&quot;&gt;&lt;code style=&quot;background: rgb(250, 250, 250); border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; font-family: &#39;Source Code Pro&#39;, monospace; font-size: 13px; margin: 0px; overflow: auto; padding: 10px;&quot;&gt;./rundatastorecleaner.py --index=index_link&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Raleway, sans-serif; font-size: 14px; font-weight: 300; margin: 0px 0px 12px; text-transform: uppercase;&quot;&gt;CONSISTENCY AND ATOMICITY&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;Since our database is sharded, and indexes for an entity can be stored on different shards than the entities themselves, consistency is an issue. What if the process crashes before it has written to all the index tables?&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;Building a transaction protocol was appealing to the most ambitious of FriendFeed engineers, but we wanted to keep the system as simple as possible. We decided to loosen constraints such that:&lt;/div&gt;&lt;ul style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin: 0px 0px 21px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;The property bag stored in the main&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;entities&lt;/code&gt;&amp;nbsp;table is canonical&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Indexes may not reflect the actual entity values&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;Consequently, we write a new entity to the database with the following steps:&lt;/div&gt;&lt;ol style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin: 0px 0px 21px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Write the entity to the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;entities&lt;/code&gt;&amp;nbsp;table, using the ACID properties of InnoDB&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Write the indexes to all of the index tables on all of the shards&lt;/li&gt;&lt;/ol&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;When we read from the index tables, we know they may not be accurate (i.e., they may reflect old property values if writing has not finished step 2). To ensure we don&#39;t return invalid entities based on the constraints above, we use the index tables to determine which entities to read, but we re-apply the query filters on the entities themselves rather than trusting the integrity of the indexes:&lt;/div&gt;&lt;ol style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin: 0px 0px 21px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Read the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;entity_id&lt;/code&gt;&amp;nbsp;from all of the index tables based on the query&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Read the entities from the&amp;nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: &#39;Source Code Pro&#39;, monospace;&quot;&gt;entities&lt;/code&gt;&amp;nbsp;table from the given entity IDs&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Filter (in Python) all of the entities that do not match the query conditions based on the actual property values&lt;/li&gt;&lt;/ol&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;To ensure that indexes are not missing perpetually and inconsistencies are eventually fixed, the &quot;Cleaner&quot; process I mentioned above runs continously over the entities table, writing missing indexes and cleaning up old and invalid indexes. It cleans recently updated entities first, so inconsistencies in the indexes get fixed fairly quickly (within a couple of seconds) in practice.&lt;/div&gt;&lt;h2 style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Raleway, sans-serif; font-size: 14px; font-weight: 300; margin: 0px 0px 12px; text-transform: uppercase;&quot;&gt;PERFORMANCE&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;We have optimized our primary indexes quite a bit in this new system, and we are quite pleased with the results. Here is a graph of FriendFeed page view latency for the past month (we launched the new backend a couple of days ago, as you can tell by the dramatic drop):&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;&lt;/div&gt;&lt;figure style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Raleway, sans-serif; font-size: 14px; margin: 0px 0px 21px;&quot;&gt;&lt;img src=&quot;http://d1udwvgzrtavb8.cloudfront.net/f066c739eb6ff1a5d4f3d275ac564ce70efccda5&quot; style=&quot;border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; margin-left: auto; margin-right: auto; max-width: 100%; padding: 3px; vertical-align: middle;&quot; /&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;In particular, the latency of our system is now remarkably stable, even during peak mid-day hours. Here is a graph of FriendFeed page view latency for the past 24 hours:&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;&lt;/div&gt;&lt;figure style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Raleway, sans-serif; font-size: 14px; margin: 0px 0px 21px;&quot;&gt;&lt;img src=&quot;http://d1udwvgzrtavb8.cloudfront.net/72a319e1cd1c16520e26fa428bed7039ecb67f6d&quot; style=&quot;border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; margin-left: auto; margin-right: auto; max-width: 100%; padding: 3px; vertical-align: middle;&quot; /&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;Compare this to one week ago:&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;&lt;/div&gt;&lt;figure style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Raleway, sans-serif; font-size: 14px; margin: 0px 0px 21px;&quot;&gt;&lt;img src=&quot;http://d1udwvgzrtavb8.cloudfront.net/aaf78c3d130196bf0f8863fadd7b7bf41aa04bd3&quot; style=&quot;border: 1px solid rgb(204, 204, 204); box-sizing: border-box; display: block; margin-left: auto; margin-right: auto; max-width: 100%; padding: 3px; vertical-align: middle;&quot; /&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px; margin-bottom: 21px;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #333333; font-family: Merriweather, Georgia, serif; font-size: 14px; line-height: 21px;&quot;&gt;The system has been really easy to work with so far. We have already changed the indexes a couple of times since we deployed the system, and we have started converting some of our biggest MySQL tables to use this new scheme so we can change their structure more liberally going forward.&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/12/how-friendfeed-uses-mysql-to-store.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-7082226422126402696</guid><pubDate>Tue, 09 Dec 2014 10:18:00 +0000</pubDate><atom:updated>2014-12-18T15:02:07.272+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Virtual Machine</category><title>Getting a ubuntu clone in VirtualBox to connect to the network </title><description>In order to &lt;strong&gt;clone a VM on Virtual Box&lt;/strong&gt;, you first  need to save the machine state of a given VM, or completely power off  the VM.  You cannot clone an actively running VM.&lt;br /&gt;&lt;br /&gt;Once a VM is powered off or saved, you can clone the VM by following this guide.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Go to &quot;Machine&quot; -&amp;gt; &quot;Clone&quot; on VirtualBox GUI menu.  It will open up VM clone wizard as follows.  Type in a new machine name.&lt;br /&gt;&lt;br /&gt;On the next screen, you will get to choose &quot;Clone type&quot;. If you want to  create an independent copy of your VM, choose &quot;Full clone&quot;.&lt;br /&gt;&lt;br /&gt;If there is any snapshot of an original VM, you can choose between  copying the current machine state only, or copying the current machine  state, plus all available snapshots.&lt;br /&gt;&lt;br /&gt;Finally, click on &quot;Clone button&quot; to proceed with cloning.  Once cloning is done, you can power on the cloned VM.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Solve networking problems of cloned Linux VM&lt;/h3&gt;When cloning a Linux VM, additional steps may be necessary to make the networking of its cloned VM work.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For example, for Ubuntu/Debian VM, you may notice that there is no  active network interface, upon powering on the cloned VM. The problem is  due to the fact that the Linux system of the cloned VM stores the  original VM&#39;s MAC address(es) for its network interface(s) in its &lt;tt&gt;udev&lt;/tt&gt; configuration file, even though VirtualBox has generated new MAC address(es) for the cloned VM.&lt;br /&gt;&lt;br /&gt;Since Linux 2.6 kernel, &lt;tt&gt;udev&lt;/tt&gt; device manager system has been introduced to handle devices including networking devices, hard drives, USB devices, etc. The &lt;tt&gt;udev&lt;/tt&gt; of the original VM assigns device name &quot;eth0&quot; to the VM&#39;s MAC address,  and this (eth0, MAC address) mapping rule is stored in  /etc/udev/rules.d/*-persistent-net.rules.&lt;br /&gt;&lt;br /&gt;The cloned VM will use the same &lt;tt&gt;udev&lt;/tt&gt; rule to attempt to  assign device names.  However, since VirtualBox has generated a  different MAC address for the cloned VM, it cannot assign &quot;eth0&quot; to the  cloned VM&#39;s primary interface, and ends up assigning a different name  (e.g., &quot;eth1&quot;) to the interface. Of course, because there is no network  configuration for eth1, networking cannot work.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div class=&quot;console&quot;&gt;&amp;nbsp;$ sudo vi /etc/udev/rules.d/*-persistent-net.rules &lt;/div&gt;&lt;br /&gt;&lt;pre&gt;# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:03.0 (e1000)&lt;br /&gt;SUBSYSTEM==&quot;net&quot;, ACTION==&quot;add&quot;, DRIVERS==&quot;?*&quot;, ATTR{address}==&quot;&lt;strong&gt;08:00:27:d9:c8:cc&lt;/strong&gt;&quot;, ATTR{dev_id}==&quot;0x0&quot;, ATTR{type}==&quot;1&quot;, KERNEL==&quot;eth*&quot;, NAME=&quot;&lt;strong&gt;eth0&lt;/strong&gt;&quot;&lt;br /&gt;&lt;br /&gt;# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:03.0 (e1000)&lt;br /&gt;SUBSYSTEM==&quot;net&quot;, ACTION==&quot;add&quot;, DRIVERS==&quot;?*&quot;, ATTR{address}==&quot;&lt;strong&gt;08:00:27:2d:49:3e&lt;/strong&gt;&quot;, ATTR{dev_id}==&quot;0x0&quot;, ATTR{type}==&quot;1&quot;, KERNEL==&quot;eth*&quot;, NAME=&quot;&lt;strong&gt;eth1&lt;/strong&gt;&quot;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In this example, the first line is a copy from the original VM, and  the second line was appended by the cloned VM.  &quot;08:00:27:d9:c8:cc&quot; is  the MAC address assigned to the original VM&#39;s interface, which is named  &quot;eth0&quot;, while &quot;08:00:27:2d:49:3e&quot; is the MAC address assigned to the  cloned VM&#39;s interface, which is assigned &quot;eth1&quot;.&lt;br /&gt;&lt;br /&gt;To fix this problem, remove the first line, and replace &quot;eth1&quot; with &quot;eth0&quot; in the second line.  Thus, a correct &lt;tt&gt;udev&lt;/tt&gt; rule for the cloned VM looks like:&lt;br /&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;# PCI device 0x8086:/sys/devices/pci0000:00/0000:00:03.0 (e1000)&lt;br /&gt;SUBSYSTEM==&quot;net&quot;, ACTION==&quot;add&quot;, DRIVERS==&quot;?*&quot;, ATTR{address}==&quot;&lt;strong&gt;08:00:27:2d:49:3e&lt;/strong&gt;&quot;, ATTR{dev_id}==&quot;0x0&quot;, ATTR{type}==&quot;1&quot;, KERNEL==&quot;eth*&quot;, NAME=&quot;&lt;strong&gt;eth0&lt;/strong&gt;&quot;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, reboot the cloned VM.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;One more thing: make sure to chance hostname of the cloned VM in  /etc/hostname and /etc/hosts, since the cloned VM has the same hostname  of the original VM.&lt;br /&gt;&lt;br /&gt;Source:&amp;nbsp;&lt;a href=&quot;http://xmodulo.com/how-to-clone-or-copy-virtual-machine-on-virtualbox.html&quot;&gt;http://xmodulo.com/how-to-clone-or-copy-virtual-machine-on-virtualbox.html&lt;/a&gt;</description><link>http://lifeeditor.blogspot.com/2014/12/getting-ubuntu-clone-in-virtualbox-to.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-3501116843679148687</guid><pubDate>Tue, 09 Dec 2014 03:53:00 +0000</pubDate><atom:updated>2014-12-09T11:53:00.000+08:00</atom:updated><title>Kickstarting Flask on Ubuntu - Setup and Deployment</title><description>&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;strong style=&quot;box-sizing: border-box;&quot;&gt;This tutorial details how to setup a Flask application on a server running Ubuntu.&lt;/strong&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Since this process can be difficult, as there are a number of moving pieces, we’ll look at this in multiple parts, starting with the most basic configuration and working our way up:&lt;/div&gt;&lt;ol style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px; margin-top: 0px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Part 1: Setting up the basic configuration&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Part 2: Adding Supervisor&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Part 3: Simplifying deployment with Git Hooks&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Part 4: Automating with Fabric (&lt;em style=&quot;box-sizing: border-box;&quot;&gt;with an example video!&lt;/em&gt;)&lt;/li&gt;&lt;/ol&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;Updated (10/28/2014):&lt;/em&gt;&amp;nbsp;Added info on how to add a new user on Ubuntu&lt;/div&gt;&lt;hr style=&quot;background-color: white; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-color: rgb(221, 221, 221); border-top-style: solid; box-sizing: content-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; height: 0px; line-height: 15.2380952835083px; margin-bottom: 21px; margin-top: 21px;&quot; /&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;We’ll specifically be using:&lt;/div&gt;&lt;ol style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px; margin-top: 0px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Ubuntu 14.04&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;nginx 1.4.6&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;gunicorn 19.1.1&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Python 2.7.8&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Pip 1.5.4&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;virtualenv 1.11.4&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Flask 0.10.1&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Supervisor 3.0b2&lt;/li&gt;&lt;/ol&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Assuming you already have a VPS running an Ubuntu operating system, we need to set up a web server on top of the operating system to serve static files – like stylesheets, JavaScript files, and images – to end users. We’ll use&amp;nbsp;&lt;a href=&quot;http://nginx.org/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;nginx&lt;/a&gt;&amp;nbsp;as our web server. Since a web server cannot communicate directly with Flask (err Python), we’ll use&amp;nbsp;&lt;a href=&quot;http://gunicorn.org/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;gunicorn&lt;/a&gt;&amp;nbsp;to act as a medium between the server and Python/Flask.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Wait, why do we need&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;two&lt;/em&gt;&amp;nbsp;servers? Think if Gunicorn as the&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;application&lt;/em&gt;&amp;nbsp;web server that will be running behind nginx – the front facing web server. Gunicorn is WSGI compatible. It can talk to other applications that support WSGI, like Flask or Django.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;img alt=&quot;nginx+gunicorn&quot; src=&quot;https://raw.githubusercontent.com/realpython/flask-deploy/master/images/localhost2.jpg&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 4px; border-radius: 0.3em; border: 0.5em solid rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 4px; box-sizing: border-box; height: auto; max-width: 100%; vertical-align: middle;&quot; /&gt;&lt;/div&gt;&lt;blockquote style=&quot;background-color: white; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; box-sizing: border-box; color: #6f6f6f; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 18.75px; margin: 0px 0px 21px; padding: 10.5px 21px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box;&quot;&gt;Need access to a web server? Check out&amp;nbsp;&lt;a href=&quot;https://www.digitalocean.com/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Digital Ocean&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;https://www.linode.com/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Linode&lt;/a&gt;, or&amp;nbsp;&lt;a href=&quot;http://aws.amazon.com/ec2/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Amazon EC2&lt;/a&gt;. Alternatively, you can use&amp;nbsp;&lt;a href=&quot;https://www.vagrantup.com/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Vagrant&lt;/a&gt;&amp;nbsp;to emulate a Linux environment. This setup was tested on both Digital Ocean and Linode.&lt;/div&gt;&lt;/blockquote&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;The end goal: HTTP requests are routed from the web server to Flask, which Flask handles appropriately, and the responses are then sent right back to the web server and, finally, back to the end user. Properly implementing a Web Server Gateway Interface (WSGI) will be paramount to our success.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;img alt=&quot;wsgi&quot; src=&quot;https://raw.githubusercontent.com/realpython/flask-deploy/master/images/wsgi.jpg&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 4px; border-radius: 0.3em; border: 0.5em solid rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 4px; box-sizing: border-box; height: auto; max-width: 100%; vertical-align: middle;&quot; /&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Let’s get to it.&lt;/div&gt;&lt;h2 id=&quot;part-1--setup&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Part 1 – Setup&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Let’s get the basic configuration setup.&lt;/div&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Add a new User&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;After SSH’ing into the server as the ‘root’ user, run-&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 208px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;adduser newuser&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;adduser newuser sudo&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;-to create a new user with ‘sudo’ privileges.&lt;/div&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Install the Requirements&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;SSH into the server with the new user, and then install the following packages:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 664px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo apt-get update&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo apt-get install -y python python-pip python-virtualenv nginx gunicorn&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Set up Flask&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Start by creating a new directory, “/home/www”, to store the project:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 344px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo mkdir /home/www &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;cd&lt;/span&gt; /home/www&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Then create and activate a virtualenv:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 233.33332824707px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo virtualenv env&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;source &lt;/span&gt;env/bin/activate&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Install the requirements:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 293.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo pip install &lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;==&lt;/span&gt;0.10.1&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Now set up your project:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 411.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo mkdir flask_project &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;cd &lt;/span&gt;flask_project&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo vim app.py&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Add the following code to&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;app.py&lt;/em&gt;:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 529.333312988281px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot; style=&quot;box-sizing: border-box; color: rgb(181, 137, 0) !important;&quot;&gt;flask&lt;/span&gt; &lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;jsonify&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;Flask&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nd&quot; style=&quot;box-sizing: border-box;&quot;&gt;@app.route&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;():&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;Flask is running!&#39;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nd&quot; style=&quot;box-sizing: border-box;&quot;&gt;@app.route&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;/data&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;():&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;names&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Jacob&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Julie&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Jennifer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;jsonify&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;__main__&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;blockquote style=&quot;background-color: white; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; box-sizing: border-box; color: #6f6f6f; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 18.75px; margin: 0px 0px 21px; padding: 10.5px 21px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box;&quot;&gt;Within VIM, press “i” to enter the INSERT mode. Add the code, then press “escape” to leave INSERT mode to go into COMMAND mode. Finally type “:wq” to save and exit VIM.&lt;/div&gt;&lt;/blockquote&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Set up a static directory-&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 183.33332824707px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo mkdir static&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;-and then add an&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;index.html&lt;/em&gt;&amp;nbsp;(&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;sudo vim static/index.html&lt;/code&gt;) file with the following html:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 143.33332824707px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;html&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Test!&lt;span class=&quot;nt&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Configure nginx&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Start nginx:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 276px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo /etc/init.d/nginx start&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Then:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 798.666687011719px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo rm /etc/nginx/sites-enabled/default&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo touch /etc/nginx/sites-available/flask_project&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo ln -s /etc/nginx/sites-available/flask_project /etc/nginx/sites-enabled/flask_project&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Here, we remove the default nginx configuration, create a new config file (called&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;flask_project&lt;/em&gt;), and, finally, set up a symlink to the config file we just created so that nginx loads it on startup.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Now, let’s add the config settings to&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;flask_project&lt;/em&gt;:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 436px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo vim /etc/nginx/sites-enabled/flask_project&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Add:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 419.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;server &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    location / &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        proxy_pass http://127.0.0.1:8000&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    location /static &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;alias&lt;/span&gt;  /home/www/flask_project/static/&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;So, HTTP requests that hit the&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;/&lt;/code&gt;&amp;nbsp;endpoint will be ‘&lt;a href=&quot;http://en.wikipedia.org/wiki/Reverse_proxy&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;reverse proxied&lt;/a&gt;’ to port 8000 on&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;127.0.0.1&lt;/code&gt;(or the “loopback ip” or “localhost”). This is same IP and port that gunicorn will use.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;We also indicate that we want nginx to directly serve the static files from the “/home/www/flask_project/static/” directory rather than routing the requests through gunicorn/WSGI. This will speed up our site’s load time since nginx knows to serve that directory directly.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Restart nginx:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 292.666656494141px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo /etc/init.d/nginx restart&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Profit!&lt;/h3&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 326.666656494141px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;cd&lt;/span&gt; /home/www/flask_project/&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;gunicorn app:app -b localhost:8000&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;The latter command manually runs gunicorn on localhost port 8000.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Open your browser and navigate to&amp;nbsp;&lt;a href=&quot;http://your_domain_name_or_ip_address/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;http://your_domain_name_or_ip_address&lt;/a&gt;.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Again, you should see the “Flask is running!” message. Test out the other URL,&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;/data&lt;/code&gt;, as well. If you navigate to&amp;nbsp;&lt;a href=&quot;http://your_domain_name_or_ip_address/static&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;http://your_domain_name_or_ip_address/static&lt;/a&gt;, you should see “Test!”, indicating that we’re serving static files correctly.&lt;/div&gt;&lt;h2 id=&quot;part-2--supervisor&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Part 2 – Supervisor&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;So, we have a working Flask app; however, there’s one problem: We have to manually (re)start gunicorn each time we make changes to our app. We can automate this with&amp;nbsp;&lt;a href=&quot;http://supervisord.org/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Supervisor&lt;/a&gt;.&lt;/div&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Configure Supervisor&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;SSH into your server, and then install Supervisor:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 326.666656494141px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo apt-get install -y supervisor&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Now create a configuration file:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 461.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo vim /etc/supervisor/conf.d/flask_project.conf&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Add:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 394px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;[&lt;/span&gt;program:flask_project&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; gunicorn app:app -b localhost:8000&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;directory&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; /home/www/flask_project&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; newuser&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Profit!&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Stop gunicorn:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 200px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo pkill gunicorn&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Start gunicorn with supervisor:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 360px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo supervisorctl reread&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo supervisorctl update&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo supervisorctl start flask_project&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Make sure your app is still running at&amp;nbsp;&lt;a href=&quot;http://your_domain_name_or_ip_address/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;http://your_domain_name_or_ip_address&lt;/a&gt;. Check out the Supervisor&amp;nbsp;&lt;a href=&quot;http://supervisord.org/index.html&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;documentation&lt;/a&gt;&amp;nbsp;for custom configuration info.&lt;/div&gt;&lt;h2 id=&quot;part-3--deployment&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Part 3 – Deployment&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;In this final part, we’ll look at using a post-receive&amp;nbsp;&lt;a href=&quot;http://git-scm.com/book/en/Customizing-Git-Git-Hooks&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Git Hook&lt;/a&gt;&amp;nbsp;along with Git, of course, to simplify the deployment process.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;&lt;img alt=&quot;githooks&quot; src=&quot;https://raw.githubusercontent.com/realpython/flask-deploy/master/images/githooks2.jpg&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 4px; border-radius: 0.3em; border: 0.5em solid rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 4px; box-sizing: border-box; height: auto; max-width: 100%; vertical-align: middle;&quot; /&gt;&lt;/div&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Configure Git&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Again, SSH into the remote server. And then install Git:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 267.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo apt-get install -y git&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Now run the following commands to set up a bare Git repo that we can push to:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 478.666656494141px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo mkdir /home/git &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;cd&lt;/span&gt; /home/git&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo mkdir flask_project.git &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0) !important;&quot;&gt;cd &lt;/span&gt;flask_project.git&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo git init --bare&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;blockquote style=&quot;background-color: white; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; box-sizing: border-box; color: #6f6f6f; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 18.75px; margin: 0px 0px 21px; padding: 10.5px 21px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 10.5px;&quot;&gt;Quick tip: displaying the git branch on your prompt will help remind you of where you are at while trekking through the terminal.&lt;/div&gt;&lt;div style=&quot;box-sizing: border-box; margin-bottom: 10.5px;&quot;&gt;Consider adding this to your bash profile on production:&lt;/div&gt;&lt;pre style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background-color: whitesmoke; border-radius: 0px; border: 1px solid rgb(204, 204, 204); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; margin-bottom: 10.5px; overflow: auto; padding: 10px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code style=&quot;background-color: transparent; border-radius: 0px; box-sizing: border-box; color: inherit; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: inherit; padding: 0px; white-space: pre-wrap;&quot;&gt;parse_git_branch() {&lt;br /&gt;    git branch 2&amp;gt; /dev/null | sed -e &#39;/^[^*]/d&#39; -e &#39;s/* \(.*\)/ (\1)/&#39;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;export PS1=&quot;\u@\h \W\[\033[32m\]\$(parse_git_branch)\[\033[00m\] $ &quot;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Configure the Post-Receive Hook&lt;/h3&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 267.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo vim hooks/post-receive&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Add:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 470px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;c&quot; style=&quot;box-sizing: border-box; color: rgb(147, 161, 161) !important; font-style: italic !important;&quot;&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;GIT_WORK_TREE&lt;/span&gt;&lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt;/home/www/flask_project git checkout -f&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Now on every push, the new files will copy over to the app directory, “/home/www/flask_project”.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Then make the file executable:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 309.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo chmod +x hooks/post-receive&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Profit!&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Back in your local Flask directory (“flask_project”) add a new Git repo along with the following remote:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 697.333312988281px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;git init&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;git remote add production root@&amp;lt;your_ip_or_domain&amp;gt;:/home/git/flask_project.git&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;blockquote style=&quot;background-color: white; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; box-sizing: border-box; color: #6f6f6f; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 18.75px; margin: 0px 0px 21px; padding: 10.5px 21px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box;&quot;&gt;Make sure to update the IP or domain name.&lt;/div&gt;&lt;/blockquote&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Make some changes to your code in the&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;app.py&lt;/em&gt;&amp;nbsp;file:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 546px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;python&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nd&quot; style=&quot;box-sizing: border-box;&quot;&gt;@app.route&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&#39;/data&#39;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important; font-weight: bold !important;&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;():&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot; style=&quot;box-sizing: border-box; font-weight: bold !important;&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;first_names&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Jacob&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Julie&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Jennifer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;],&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;        &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;last_names&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Connor&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Johnson&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Cloud&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;Ray&quot;&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(203, 75, 22) !important;&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;jsonify&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot; style=&quot;box-sizing: border-box;&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Commit your local changes, then push:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 258.666656494141px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;git add -A&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;git commit -am &lt;span class=&quot;s2&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152) !important;&quot;&gt;&quot;initial&quot;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;git push production master&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;SSH into your server and restart gunicorn via Supervisor:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 377.333343505859px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;sudo supervisorctl restart flask_project&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Check out your changes at&amp;nbsp;&lt;a href=&quot;http://your_domain_name_or_ip_address/data&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;http://your_domain_name_or_ip_address/data&lt;/a&gt;.&lt;/div&gt;&lt;h2 id=&quot;part-4--automating&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Part 4 – Automating&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Do you really want to manually configure a server? Sure, it’s great for learning, but it’s super tedious, as you can tell. Fortunately, we’ve automated the process with&amp;nbsp;&lt;a href=&quot;http://www.fabfile.org/&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;Fabric&lt;/a&gt;. Along with setting up nginx, gunicorn, Supervisor, and Git, the script creates a basic Flask app, which is specific to the project that we’ve been working with. You can easily customize this to meet your own specific needs.&lt;/div&gt;&lt;blockquote style=&quot;background-color: white; border-left-color: rgb(221, 221, 221); border-left-style: solid; border-left-width: 1px; box-sizing: border-box; color: #6f6f6f; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 18.75px; margin: 0px 0px 21px; padding: 10.5px 21px;&quot;&gt;&lt;div style=&quot;box-sizing: border-box;&quot;&gt;You should remove the username and password from the file and either place them in a separate config file that stays out of version control or set up SSH keys on the remote server so that you do not need a password to login. Also, be sure to update the&amp;nbsp;&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 16.6666660308838px; padding: 2px 4px;&quot;&gt;env.hosts&lt;/code&gt;&amp;nbsp;variable to your IP or domain name.&lt;/div&gt;&lt;/blockquote&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Setup&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;To test this script (&lt;em style=&quot;box-sizing: border-box;&quot;&gt;fabfile.py&lt;/em&gt;) clone the&amp;nbsp;&lt;a href=&quot;https://github.com/realpython/flask-deploy&quot; style=&quot;background: transparent; box-sizing: border-box; color: #008cba; text-decoration: none;&quot;&gt;repo&lt;/a&gt;&amp;nbsp;and start with a clean, freshly provisioned server with Ubuntu 14.04. Then navigate to the “flask-deploy” directory. To set up the basic configuration on the remote server as well as your app, run the following command:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 124px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;fab create&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Your app should now be live. Test this out in your browser.&lt;/div&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Deployment&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Want to set up deployment with Git Hooks? Initialize a local repo within your Flask project directory (if necessary). Then make some local changes to your Flask app, and run the following command to deploy:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 124px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;fab deploy&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Check your app again in the browser. Make sure your changes show up.&lt;/div&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Status Check&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Finally, you can check that the Supervisor process is running correctly, to ensure that your app is live, with the following command:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 124px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;fab status&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Again, this script is specific to your project at hand. You can customize this to your own needs by updating the config section and altering the tasks as necessary.&lt;/div&gt;&lt;h3 style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 26px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Rollback&lt;/h3&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;To err is human…&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Things are bound to go wrong from time to time once you have code on production. Everything may work well on your local development environment only to crash in production. So it’s important to have a strategy in place to quickly revert a Git commit. Take a quick look at the&lt;code style=&quot;background-color: #f9f2f4; border-radius: 0px; box-sizing: border-box; color: #c7254e; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14.6666669845581px; padding: 2px 4px;&quot;&gt;rollback&lt;/code&gt;&amp;nbsp;task from the&amp;nbsp;&lt;em style=&quot;box-sizing: border-box;&quot;&gt;fabfile.py&lt;/em&gt;, which allows you to revert changes quickly to get a working app back up.&lt;/div&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Test it out by purposely breaking your code and then deploying to production, and then run:&lt;/div&gt;&lt;figure class=&quot;code&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none rgb(255, 255, 255); border-radius: 5px; border: 1px solid rgb(221, 221, 221); box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin: 0px 0px 1.5em; padding: 0px;&quot;&gt;&lt;figcaption style=&quot;background-color: whitesmoke; border-radius: 5px; box-sizing: border-box; color: #333333; padding: 10px 15px; position: relative;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-weight: bold; line-height: 1.1;&quot;&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot; style=&quot;background: url(https://realpython.com/images/noise.png?1404179312) 0% 0% rgb(252, 252, 252); border-radius: 0px 0px 5px 5px; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-top-width: 1px; box-sizing: border-box; margin-bottom: 0px; overflow-x: auto; overflow-y: hidden;&quot;&gt;&lt;table style=&quot;background-color: transparent; border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; font-size: 12px;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;box-sizing: border-box; padding: 0px; width: 140.66667175293px;&quot;&gt;&lt;pre style=&quot;-webkit-box-shadow: none; background: none; border-radius: 0px; border: none; box-shadow: none; box-sizing: border-box; color: #333333; font-family: Menlo, Monaco, Consolas, &#39;Courier New&#39;, monospace; font-size: 14px; line-height: 1.42857143; overflow: auto; padding: 0px; word-break: break-all; word-wrap: break-word;&quot;&gt;&lt;code class=&quot;sh&quot; style=&quot;background: rgb(0, 0, 0); border-radius: 0px; box-sizing: border-box; color: rgb(88, 110, 117) !important; display: block; font-family: Menlo, Monaco, &#39;Andale Mono&#39;, &#39;lucida console&#39;, &#39;Courier New&#39;, monospace !important; font-size: inherit; line-height: 1.45em; overflow-x: auto; overflow-y: hidden; padding: 0.8em;&quot;&gt;&lt;span class=&quot;line&quot; style=&quot;box-sizing: border-box;&quot;&gt;&lt;span class=&quot;nv&quot; style=&quot;box-sizing: border-box; color: rgb(38, 139, 210) !important;&quot;&gt;$ &lt;/span&gt;fab rollback&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;You can then update your code locally to fix the bugs, and then re-deploy.&lt;/div&gt;&lt;h2 id=&quot;example-video&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Example Video&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Just press play…&lt;/div&gt;&lt;div class=&quot;embed-video-container&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;iframe allowfullscreen=&quot;&quot; src=&quot;https://www.youtube.com/embed/VmcGuKPpWH8&quot; style=&quot;box-sizing: border-box; height: 345px; width: 420px;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;h2 id=&quot;conclusion-and-next-steps&quot; style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: &#39;Open Sans&#39;, &#39;Helvetica Neue&#39;, Helvetica, Arial, sans-serif; font-size: 32px; line-height: 1.1; margin-bottom: 12px; margin-top: 32px;&quot;&gt;Conclusion and Next Steps&lt;/h2&gt;&lt;div style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px;&quot;&gt;Want to take this workflow to the next level?&lt;/div&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Part.1.-.Setup&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Add.a.new.User&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Install.the.Requirements&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Set.up.Flask&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Configure.nginx&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Profit.&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Part.2.-.Supervisor&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Configure.Supervisor&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Profit.&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Part.3.-.Deployment&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Configure.Git&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Configure.the.Post-Receive.Hook&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Profit.&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Part.4.-.Automating&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Setup&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Deployment&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Status.Check&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Rollback&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Example.Video&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;Conclusion.and.Next.Steps&quot; style=&quot;background: rgb(255, 255, 255); box-sizing: border-box; color: #008cba; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/a&gt;&lt;span style=&quot;background-color: white; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;ol style=&quot;background-color: white; box-sizing: border-box; color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 15.2380952835083px; margin-bottom: 10.5px; margin-top: 0px;&quot;&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Add a pre-production (staging) server into the mix for testing purposes. Deploy to this server first, which should be an exact copy of your production environment, to test before deploying to production.&lt;/li&gt;&lt;li style=&quot;box-sizing: border-box;&quot;&gt;Utilize Continuous Integration and Delivery to further eliminate bugs and regressions with automated testing and decrease the time it takes to deploy your app.&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #222222; font-family: proxima-nova, Helvetica, Arial, sans-serif;&quot;&gt;&lt;span style=&quot;line-height: 15.2380952835083px;&quot;&gt;Source:&amp;nbsp;&lt;a href=&quot;https://realpython.com/blog/python/kickstarting-flask-on-ubuntu-setup-and-deployment/&quot;&gt;https://realpython.com/blog/python/kickstarting-flask-on-ubuntu-setup-and-deployment/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/12/kickstarting-flask-on-ubuntu-setup-and.html</link><author>noreply@blogger.com (MathBee)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/VmcGuKPpWH8/default.jpg" height="72" width="72"/><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-886894211604943192</guid><pubDate>Tue, 09 Dec 2014 03:51:00 +0000</pubDate><atom:updated>2014-12-09T11:51:23.493+08:00</atom:updated><title>Using nginx as HTTP load balancer</title><description>&lt;center style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;h4&gt;Introduction&lt;/h4&gt;&lt;/center&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;Load balancing across multiple application instances is a commonly used technique for optimizing resource utilization, maximizing throughput, reducing latency, and ensuring fault-tolerant configurations.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;It is possible to use nginx as a very efficient HTTP load balancer to distribute traffic to several application servers and to improve performance, scalability and reliability of web applications with nginx.&lt;/div&gt;&lt;center style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;h4&gt;Load balancing methods&lt;/h4&gt;&lt;/center&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;The following load balancing mechanisms (or methods) are supported in nginx:&lt;/div&gt;&lt;ul style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; margin: 0.5em 0px 1em 1em; padding: 0px 0.5em;&quot;&gt;&lt;li style=&quot;padding: 0.5em 0px 0px 1px; text-align: justify;&quot;&gt;round-robin&amp;nbsp;— requests to the application servers are distributed in a round-robin fashion,&lt;/li&gt;&lt;li style=&quot;padding: 0.5em 0px 0px 1px; text-align: justify;&quot;&gt;least-connected&amp;nbsp;— next request is assigned to the server with the least number of active connections,&lt;/li&gt;&lt;li style=&quot;padding: 0.5em 0px 0px 1px; text-align: justify;&quot;&gt;ip-hash&amp;nbsp;— a hash-function is used to determine what server should be selected for the next request (based on the client’s IP address).&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;&lt;/div&gt;&lt;center style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;h4&gt;Default load balancing configuration&lt;/h4&gt;&lt;/center&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;The simplest configuration for load balancing with nginx may look like the following:&lt;/div&gt;&lt;blockquote class=&quot;example&quot; style=&quot;background-color: white; border-left-color: rgb(187, 187, 187); border-left-style: solid; border-left-width: 1px; font-family: sans-serif; line-height: 1em; margin: 1em 0px 1em 1em; padding: 0.5em;&quot;&gt;&lt;pre style=&quot;padding: 0px;&quot;&gt;http {&lt;br /&gt;    upstream myapp1 {&lt;br /&gt;        server srv1.example.com;&lt;br /&gt;        server srv2.example.com;&lt;br /&gt;        server srv3.example.com;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    server {&lt;br /&gt;        listen 80;&lt;br /&gt;&lt;br /&gt;        location / {&lt;br /&gt;            proxy_pass http://myapp1;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;In the example above, there are 3 instances of the same application running on srv1-srv3. When the load balancing method is not specifically configured, it defaults to round-robin. All requests are&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass&quot;&gt;proxied&lt;/a&gt;&amp;nbsp;to the server group myapp1, and nginx applies HTTP load balancing to distribute the requests.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;Reverse proxy implementation in nginx includes load balancing for HTTP, HTTPS, FastCGI, uwsgi, SCGI, and memcached.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;To configure load balancing for HTTPS instead of HTTP, just use “https” as the protocol.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;When setting up load balancing for FastCGI, uwsgi, SCGI, or memcached, use&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_pass&quot;&gt;fastcgi_pass&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_uwsgi_module.html#uwsgi_pass&quot;&gt;uwsgi_pass&lt;/a&gt;,&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_scgi_module.html#scgi_pass&quot;&gt;scgi_pass&lt;/a&gt;, and&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_memcached_module.html#memcached_pass&quot;&gt;memcached_pass&lt;/a&gt;&amp;nbsp;directives respectively.&lt;/div&gt;&lt;center style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;h4&gt;Least connected load balancing&lt;/h4&gt;&lt;/center&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;Another load balancing discipline is least-connected. Least-connected allows controlling the load on application instances more fairly in a situation when some of the requests take longer to complete.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;With the least-connected load balancing, nginx will try not to overload a busy application server with excessive requests, distributing the new requests to a less busy server instead.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;Least-connected load balancing in nginx is activated when the&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#least_conn&quot;&gt;least_conn&lt;/a&gt;&amp;nbsp;directive is used as part of the server group configuration:&lt;/div&gt;&lt;blockquote class=&quot;example&quot; style=&quot;background-color: white; border-left-color: rgb(187, 187, 187); border-left-style: solid; border-left-width: 1px; font-family: sans-serif; line-height: 1em; margin: 1em 0px 1em 1em; padding: 0.5em;&quot;&gt;&lt;pre style=&quot;padding: 0px;&quot;&gt;    upstream myapp1 {&lt;br /&gt;        least_conn;&lt;br /&gt;        server srv1.example.com;&lt;br /&gt;        server srv2.example.com;&lt;br /&gt;        server srv3.example.com;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;&lt;/div&gt;&lt;center style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;h4&gt;Session persistence&lt;/h4&gt;&lt;/center&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;Please note that with round-robin or least-connected load balancing, each subsequent client’s request can be potentially distributed to a different server. There is no guarantee that the same client will be always directed to the same server.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;If there is the need to tie a client to a particular application server&amp;nbsp;— in other words, make the client’s session “sticky” or “persistent” in terms of always trying to select a particular server&amp;nbsp;— the ip-hash load balancing mechanism can be used.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;With ip-hash, the client’s IP address is used as a hashing key to determine what server in a server group should be selected for the client’s requests. This method ensures that the requests from the same client will always be directed to the same server except when this server is unavailable.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;To configure ip-hash load balancing, just add the&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#ip_hash&quot;&gt;ip_hash&lt;/a&gt;&amp;nbsp;directive to the server (upstream) group configuration:&lt;/div&gt;&lt;blockquote class=&quot;example&quot; style=&quot;background-color: white; border-left-color: rgb(187, 187, 187); border-left-style: solid; border-left-width: 1px; font-family: sans-serif; line-height: 1em; margin: 1em 0px 1em 1em; padding: 0.5em;&quot;&gt;&lt;pre style=&quot;padding: 0px;&quot;&gt;upstream myapp1 {&lt;br /&gt;    ip_hash;&lt;br /&gt;    server srv1.example.com;&lt;br /&gt;    server srv2.example.com;&lt;br /&gt;    server srv3.example.com;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;&lt;/div&gt;&lt;center style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;h4&gt;Weighted load balancing&lt;/h4&gt;&lt;/center&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;It is also possible to influence nginx load balancing algorithms even further by using server weights.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;In the examples above, the server weights are not configured which means that all specified servers are treated as equally qualified for a particular load balancing method.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;With the round-robin in particular it also means a more or less equal distribution of requests across the servers&amp;nbsp;— provided there are enough requests, and when the requests are processed in a uniform manner and completed fast enough.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;When the&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server&quot;&gt;weight&lt;/a&gt;&amp;nbsp;parameter is specified for a server, the weight is accounted as part of the load balancing decision.&lt;/div&gt;&lt;blockquote class=&quot;example&quot; style=&quot;background-color: white; border-left-color: rgb(187, 187, 187); border-left-style: solid; border-left-width: 1px; font-family: sans-serif; line-height: 1em; margin: 1em 0px 1em 1em; padding: 0.5em;&quot;&gt;&lt;pre style=&quot;padding: 0px;&quot;&gt;    upstream myapp1 {&lt;br /&gt;        server srv1.example.com weight=3;&lt;br /&gt;        server srv2.example.com;&lt;br /&gt;        server srv3.example.com;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;With this configuration, every 5 new requests will be distributed across the application instances as the following: 3 requests will be directed to srv1, one request will go to srv2, and another one&amp;nbsp;— to srv3.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;It is similarly possible to use weights with the least-connected and ip-hash load balancing in the recent versions of nginx.&lt;/div&gt;&lt;center style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;h4&gt;Health checks&lt;/h4&gt;&lt;/center&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;Reverse proxy implementation in nginx includes in-band (or passive) server health checks. If the response from a particular server fails with an error, nginx will mark this server as failed, and will try to avoid selecting this server for subsequent inbound requests for a while.&lt;/div&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;The&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server&quot;&gt;max_fails&lt;/a&gt;&amp;nbsp;directive sets the number of consecutive unsuccessful attempts to communicate with the server that should happen during&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server&quot;&gt;fail_timeout&lt;/a&gt;. By default,&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server&quot;&gt;max_fails&lt;/a&gt;&amp;nbsp;is set to 1. When it is set to 0, health checks are disabled for this server. The&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server&quot;&gt;fail_timeout&lt;/a&gt;&amp;nbsp;parameter also defines how long the server will be marked as failed. After&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server&quot;&gt;fail_timeout&lt;/a&gt;&amp;nbsp;interval following the server failure, nginx will start to gracefully probe the server with the live client’s requests. If the probes have been successful, the server is marked as a live one.&lt;/div&gt;&lt;center style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;h4&gt;Further reading&lt;/h4&gt;&lt;/center&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;In addition, there are more directives and parameters that control server load balancing in nginx, e.g.&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream&quot;&gt;proxy_next_upstream&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server&quot;&gt;backup&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#server&quot;&gt;down&lt;/a&gt;, and&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive&quot;&gt;keepalive&lt;/a&gt;. For more information please check our&amp;nbsp;&lt;a href=&quot;http://nginx.org/en/docs/&quot;&gt;reference documentation&lt;/a&gt;.&lt;/div&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;nginx_load_balancing_methods&quot; style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;nginx_load_balancing_configuration&quot; style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;nginx_load_balancing_with_least_connected&quot; style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;nginx_load_balancing_with_ip_hash&quot; style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;nginx_weighted_load_balancing&quot; style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;nginx_load_balancing_health_checks&quot; style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.blogger.com/null&quot; name=&quot;nginx_load_balancing_additional_information&quot; style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px;&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style=&quot;background-color: white; font-family: sans-serif; line-height: 22.3999996185303px; text-align: justify;&quot;&gt;Last but not least,&amp;nbsp;&lt;a href=&quot;http://nginx.com/products/application-load-balancing/&quot;&gt;application load balancing&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://nginx.com/products/application-health-checks/&quot;&gt;application health checks&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;http://nginx.com/products/live-activity-monitoring/&quot;&gt;activity monitoring&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;http://nginx.com/products/on-the-fly-reconfiguration/&quot;&gt;on-the-fly reconfiguration&lt;/a&gt;&amp;nbsp;of server groups are available as part of our paid NGINX Plus subscriptions.&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/12/using-nginx-as-http-load-balancer.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-7343969955898041560</guid><pubDate>Tue, 09 Dec 2014 03:49:00 +0000</pubDate><atom:updated>2014-12-09T11:49:51.179+08:00</atom:updated><title>Load Balancing and Reverse Proxying with Nginx</title><description>&lt;br /&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;a class=&quot;fancybox&quot; href=&quot;http://d1u2s20mo6at4b.cloudfront.net/wp-content/uploads/NginxLogo.gif&quot; rel=&quot;fancybox&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;img alt=&quot;nginx&quot; class=&quot;alignright size-full wp-image-98663&quot; height=&quot;32&quot; scale=&quot;0&quot; src=&quot;http://d1u2s20mo6at4b.cloudfront.net/wp-content/uploads/NginxLogo.gif&quot; style=&quot;border: 0px; box-sizing: border-box; display: inline; float: right; height: auto; margin-left: 1.5em; max-width: 100%;&quot; width=&quot;121&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;http://nginx.org/&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Nginx&lt;/a&gt;&amp;nbsp;is a modern, open-source, high-performance web server. It is capable of handling a huge number of concurrent connections easily (see the&amp;nbsp;&lt;a href=&quot;http://www.kegel.com/c10k.html&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;C10K problem&lt;/a&gt;). Over a year ago, I wrote about&amp;nbsp;&lt;a href=&quot;http://spin.atomicobject.com/2012/02/28/load-balancing-and-reverse-proxying-with-nginx/&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;using nginx as a load balancer and remote proxy&lt;/a&gt;. Since then, my understanding of nginx and best practices in its configuration have progressed significantly. I’ve decided to refresh my blog post to provide some of this additional knowledge.&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;As I explained in my previous post, nginx relies on a&amp;nbsp;&lt;a href=&quot;http://www.aosabook.org/en/nginx.html&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;non-blocking I/O, event-driven model&lt;/a&gt;, which allows it to easily handle a large number of incoming concurrent client connections with ease. This makes it an excellent choice as a&lt;a href=&quot;http://en.wikipedia.org/wiki/Load_balancing_(computing)&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;load balancer&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Reverse_proxy&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;reverse proxy&lt;/a&gt;. In contrast, the traditional&amp;nbsp;&lt;a href=&quot;https://httpd.apache.org/&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Apache HTTP&lt;/a&gt;&amp;nbsp;model relies on a limited number of synchronous threads which may block on I/O.&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;Nginx running on a single server handles incoming client requests and distributes them to a pool of upstream application servers that actually fulfill the requests. The pool of application servers can be easily scaled up or down to handle changes in traffic levels. This flexibility provides a way to scale the capacity of almost any web application quite easily.&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;Following are some specific scenarios and nginx configuration examples that I have used when setting up and maintaining applications and network infrastructures for both Atomic Object and our clients. I lead up to a fairly practical configuration implementation that I’ve used recently.&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;span id=&quot;more-98658&quot; style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;h2 style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; clear: both; color: #4a4a4a; font-family: ff-din-web, sans-serif; font-size: 22px; margin: 0px; outline: 0px; padding: 1rem 0px 0.5rem; vertical-align: baseline;&quot;&gt;Simple Scenario&lt;/h2&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Situation&lt;/strong&gt;: We have a&amp;nbsp;&lt;a href=&quot;http://jruby.org/&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;JRuby&lt;/a&gt;&amp;nbsp;application running on&amp;nbsp;&lt;a href=&quot;http://tomcat.apache.org/&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Apache Tomcat&lt;/a&gt;. The application gets a significant amount of traffic and is no longer performing as well as required. We have hit the limit of how much additional RAM/CPU resources we can easily add to the server. Instead, we decide to scale horizontally and add more servers.&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;First, we setup a new nginx server to a accept the connections, and distribute them to our Tomcat application servers.&lt;/div&gt;&lt;div class=&quot;wp_syntax&quot; style=&quot;background-color: #f9f9f9; border: 1px solid silver; box-sizing: border-box; color: #110000; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; margin: 0px 0px 1.5em; outline: 0px; overflow-x: auto; overflow-y: hidden; padding: 0px 0px 1.5rem; vertical-align: baseline; width: 689.03125px;&quot;&gt;&lt;table style=&quot;border-collapse: collapse !important; border-spacing: 0px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px !important; outline: 0px; padding: 0px !important; vertical-align: baseline; width: 687.333312988281px;&quot;&gt;&lt;tbody style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;tr style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;background-color: #eeeeee; background-image: linear-gradient(transparent 50%, rgba(255, 255, 255, 0.901961) 50%); background-size: 1px 32px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px !important; vertical-align: top !important; width: 687.333312988281px;&quot;&gt;&lt;pre class=&quot;c&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; background: transparent !important; border-radius: 0px !important; border: none !important; box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; box-sizing: border-box; clear: none !important; float: none !important; font-size: 12px !important; font-style: inherit; font-weight: inherit; line-height: 16px !important; max-width: 100%; outline: 0px; overflow: visible !important; padding: 0px 4px !important; vertical-align: baseline; width: auto !important; word-wrap: break-word;&quot;&gt;upstream jruby_application  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  server 10.0.0.2&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;8080&lt;/span&gt; max_fails&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;1&lt;/span&gt; fail_timeout&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;10s&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  server 10.0.0.3&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;8080&lt;/span&gt; max_fails&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;1&lt;/span&gt; fail_timeout&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;10s&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;# and so on: server 10.0.0.x;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;server &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  listen &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;80&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  root &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;www&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;html&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  try_files &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;maintenance.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri $uri&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;index.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; @proxy&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  location @proxy &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    proxy_pass  http&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jruby_application;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Explanation&lt;/strong&gt;: We set nginx to listen on port 80. When a request comes in, nginx first checks to see if the&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;/var/www/html/maintenance.html&lt;/code&gt;&amp;nbsp;file exists. If it does, it serves it. Otherwise, it continues down the list of checks so see if the request can be handled locally. If the request cannot be served locally, nginx passes it to the&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;@proxy&lt;/code&gt;&amp;nbsp;location block, which will proxy the request to the upstream JRuby applications running on port 8080.&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;This is extremely powerful as it allows nginx to intercept certain requests before they are proxied to upstream applications. This is useful for static assets such as images and files. Additionally, the check for a maintenance page allows us to selectively put the entire site in maintenance mode simply by creating a file.&lt;/div&gt;&lt;h2 style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; clear: both; color: #4a4a4a; font-family: ff-din-web, sans-serif; font-size: 22px; margin: 0px; outline: 0px; padding: 1rem 0px 0.5rem; vertical-align: baseline;&quot;&gt;Scenario with HTTP Headers&lt;/h2&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Situation&lt;/strong&gt;: Our new cluster of servers has been running great. However, we notice that the IP addresses of clients aren’t being properly passed to the JRuby application. Instead, all clients have an IP address of&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;10.0.0.1&lt;/code&gt;.&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;Fortunately, all that we need to do is to tell nginx to set or pass on certain HTTP headers to the upstream JRuby application.&lt;/div&gt;&lt;div class=&quot;wp_syntax&quot; style=&quot;background-color: #f9f9f9; border: 1px solid silver; box-sizing: border-box; color: #110000; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; margin: 0px 0px 1.5em; outline: 0px; overflow-x: auto; overflow-y: hidden; padding: 0px 0px 1.5rem; vertical-align: baseline; width: 689.03125px;&quot;&gt;&lt;table style=&quot;border-collapse: collapse !important; border-spacing: 0px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px !important; outline: 0px; padding: 0px !important; vertical-align: baseline; width: 687.333312988281px;&quot;&gt;&lt;tbody style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;tr style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;background-color: #eeeeee; background-image: linear-gradient(transparent 50%, rgba(255, 255, 255, 0.901961) 50%); background-size: 1px 32px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px !important; vertical-align: top !important; width: 687.333312988281px;&quot;&gt;&lt;pre class=&quot;c&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; background: transparent !important; border-radius: 0px !important; border: none !important; box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; box-sizing: border-box; clear: none !important; float: none !important; font-size: 12px !important; font-style: inherit; font-weight: inherit; line-height: 16px !important; max-width: 100%; outline: 0px; overflow: visible !important; padding: 0px 4px !important; vertical-align: baseline; width: auto !important; word-wrap: break-word;&quot;&gt;server &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  listen &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;80&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  root &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;www&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;html&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  try_files &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;maintenance.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri $uri&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;index.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; @proxy&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  location @proxy &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_set_header Host $host&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Real&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;IP $remote_addr&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Forwarded&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;For $proxy_add_x_forwarded_for&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_pass  http&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jruby_application;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Explanation&lt;/strong&gt;: By adding some specific HTTP headers via the&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;proxy_set_header&lt;/code&gt;directive, we can ensure that the JRuby application has access to the correct HTTP headers from the client. In addition, we can set certain headers based on characteristics of the client connection. In this instance,&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;X-Real-IP&lt;/code&gt;&amp;nbsp;is set to the remote address of the client. However, the client itself may just be a proxy server forwarding a request on behalf of a client (common with certain CDN’s).&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;X-Forwarded-For&lt;/code&gt;&amp;nbsp;is set to the ultimate client IP address (end user) based on the HTTP headers provided with the request.&lt;/div&gt;&lt;h2 style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; clear: both; color: #4a4a4a; font-family: ff-din-web, sans-serif; font-size: 22px; margin: 0px; outline: 0px; padding: 1rem 0px 0.5rem; vertical-align: baseline;&quot;&gt;Scenario with SSL/HTTPS&lt;/h2&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Situation&lt;/strong&gt;: Our JRuby application now needs to be able to secure client requests. It would be a pain to setup SSL on Apache Tomcat, so we decide to use nginx as the SSL endpoint. In our current setup, all connections to upstream JRuby application servers are on a private network, and so do not need to be separately secured.&lt;/div&gt;&lt;div class=&quot;wp_syntax&quot; style=&quot;background-color: #f9f9f9; border: 1px solid silver; box-sizing: border-box; color: #110000; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; margin: 0px 0px 1.5em; outline: 0px; overflow-x: auto; overflow-y: hidden; padding: 0px 0px 1.5rem; vertical-align: baseline; width: 689.03125px;&quot;&gt;&lt;table style=&quot;border-collapse: collapse !important; border-spacing: 0px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px !important; outline: 0px; padding: 0px !important; vertical-align: baseline; width: 687.333312988281px;&quot;&gt;&lt;tbody style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;tr style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;background-color: #eeeeee; background-image: linear-gradient(transparent 50%, rgba(255, 255, 255, 0.901961) 50%); background-size: 1px 32px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px !important; vertical-align: top !important; width: 687.333312988281px;&quot;&gt;&lt;pre class=&quot;c&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; background: transparent !important; border-radius: 0px !important; border: none !important; box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; box-sizing: border-box; clear: none !important; float: none !important; font-size: 12px !important; font-style: inherit; font-weight: inherit; line-height: 16px !important; max-width: 100%; outline: 0px; overflow: visible !important; padding: 0px 4px !important; vertical-align: baseline; width: auto !important; word-wrap: break-word;&quot;&gt;server &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  listen &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;443&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  server_name jrubyapp.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;example&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  root &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;www&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;html&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  try_files &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;maintenance.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri $uri&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;index.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; @proxy&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  ssl on&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  ssl_certificate cert.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;crt&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;   &lt;br /&gt;  ssl_certificate_key cert.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&lt;br /&gt;  location @proxy &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_set_header Host $host&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Real&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;IP $remote_addr&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Forwarded&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;For $proxy_add_x_forwarded_for&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Forwarded&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Proto https&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_pass  http&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jruby_application;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Explanation&lt;/strong&gt;: We set nginx to listen on port 443 (HTTPS), specify that nginx should enable the SSL engine, and use the provided SSL certificate and SSL certificate key. Nginx does not have a separate directive for providing a SSL chain certificate (such as with Apache HTTP), so any chain certificates need to be appended to the primary certificate (e.g.&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;cat newcert.crt chain.crt &amp;gt; cert.crt&lt;/code&gt;). Additionally, we set the&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;X-Forwarded-Proto&lt;/code&gt;&amp;nbsp;HTTP header so that the JRuby application can detect that the client connected securely over HTTPS.&lt;/div&gt;&lt;h2 style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; clear: both; color: #4a4a4a; font-family: ff-din-web, sans-serif; font-size: 22px; margin: 0px; outline: 0px; padding: 1rem 0px 0.5rem; vertical-align: baseline;&quot;&gt;Scenario Redirecting all Traffic to HTTPS&lt;/h2&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Situation&lt;/strong&gt;: We decide that all traffic to our JRuby application should be secured with SSL. This tends to be for non-public-facing websites such as particular client application instances. While it would be better that the connections were originally made with SSL, we can provide a redirect as a convenience to users where appropriate.&lt;/div&gt;&lt;div class=&quot;wp_syntax&quot; style=&quot;background-color: #f9f9f9; border: 1px solid silver; box-sizing: border-box; color: #110000; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; margin: 0px 0px 1.5em; outline: 0px; overflow-x: auto; overflow-y: hidden; padding: 0px 0px 1.5rem; vertical-align: baseline; width: 689.03125px;&quot;&gt;&lt;table style=&quot;border-collapse: collapse !important; border-spacing: 0px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px !important; outline: 0px; padding: 0px !important; vertical-align: baseline; width: 687.333312988281px;&quot;&gt;&lt;tbody style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;tr style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;background-color: #eeeeee; background-image: linear-gradient(transparent 50%, rgba(255, 255, 255, 0.901961) 50%); background-size: 1px 32px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px !important; vertical-align: top !important; width: 687.333312988281px;&quot;&gt;&lt;pre class=&quot;c&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; background: transparent !important; border-radius: 0px !important; border: none !important; box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; box-sizing: border-box; clear: none !important; float: none !important; font-size: 12px !important; font-style: inherit; font-weight: inherit; line-height: 16px !important; max-width: 100%; outline: 0px; overflow: visible !important; padding: 0px 4px !important; vertical-align: baseline; width: auto !important; word-wrap: break-word;&quot;&gt;server &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  listen &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;80&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  root &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;www&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;html&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  try_files &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;maintenance.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri $uri&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;index.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; @secure&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  location @secure &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    rewrite &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;^&lt;/span&gt; https&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jrubyapp.example.com permanent;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;server &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  listen &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;443&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  server_name jrubyapp.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;example&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  root &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;www&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;html&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  try_files &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;maintenance.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri $uri&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;index.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; @proxy&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  ssl on&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  ssl_certificate cert.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;crt&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;   &lt;br /&gt;  ssl_certificate_key cert.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&lt;br /&gt;  location @proxy &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_set_header Host $host&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Real&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;IP $remote_addr&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Forwarded&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;For $proxy_add_x_forwarded_for&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Forwarded&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Proto https&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_pass  http&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jruby_application;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Explanation&lt;/strong&gt;: We set nginx to listen on both port 80 (HTTP) and port 443 (HTTPS). On port 80, nginx first checks for the&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;/var/www/html/maintenance.html&lt;/code&gt;&amp;nbsp;page, and then checks if it can otherwise handle the request locally. If it cannot, it returns a redirect to HTTPS. The&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;permanent&lt;/code&gt;&amp;nbsp;keyword tells nginx to respond with a&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/HTTP_301&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;HTTP 301&lt;/a&gt;(moved permanently) as opposed to a&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/HTTP_302&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;HTTP 302&lt;/a&gt;&amp;nbsp;(moved temporarily). Note that the server block for port 80 has no means of actually proxying the request.&lt;/div&gt;&lt;h2 style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; clear: both; color: #4a4a4a; font-family: ff-din-web, sans-serif; font-size: 22px; margin: 0px; outline: 0px; padding: 1rem 0px 0.5rem; vertical-align: baseline;&quot;&gt;Scenario with Proxy Redirect&lt;/h2&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Situation&lt;/strong&gt;: Our upstream JRuby application does not always respond to clients with the appropriate URI. For instance, the JRuby application occasionally responds with a redirect, but specifies a protocol of HTTP instead of HTTPS as the JRuby application itself is running as HTTP (nginx is handling the SSL termination). We can intercept any of these responses and ensure that the client is redirected properly.&lt;/div&gt;&lt;div class=&quot;wp_syntax&quot; style=&quot;background-color: #f9f9f9; border: 1px solid silver; box-sizing: border-box; color: #110000; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; margin: 0px 0px 1.5em; outline: 0px; overflow-x: auto; overflow-y: hidden; padding: 0px 0px 1.5rem; vertical-align: baseline; width: 689.03125px;&quot;&gt;&lt;table style=&quot;border-collapse: collapse !important; border-spacing: 0px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px !important; outline: 0px; padding: 0px !important; vertical-align: baseline; width: 687.333312988281px;&quot;&gt;&lt;tbody style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;tr style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;background-color: #eeeeee; background-image: linear-gradient(transparent 50%, rgba(255, 255, 255, 0.901961) 50%); background-size: 1px 32px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px !important; vertical-align: top !important; width: 687.333312988281px;&quot;&gt;&lt;pre class=&quot;c&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; background: transparent !important; border-radius: 0px !important; border: none !important; box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; box-sizing: border-box; clear: none !important; float: none !important; font-size: 12px !important; font-style: inherit; font-weight: inherit; line-height: 16px !important; max-width: 100%; outline: 0px; overflow: visible !important; padding: 0px 4px !important; vertical-align: baseline; width: auto !important; word-wrap: break-word;&quot;&gt;server &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  listen &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;443&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  server_name jrubyapp.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;example&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  root &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;www&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;html&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  try_files &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;maintenance.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri $uri&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;index.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; @proxy&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  ssl on&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  ssl_certificate cert.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;crt&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;   &lt;br /&gt;  ssl_certificate_key cert.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt; &lt;br /&gt;&amp;nbsp;&lt;br /&gt;  location @proxy &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_set_header Host $host&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Real&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;IP $remote_addr&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Forwarded&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;For $proxy_add_x_forwarded_for&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Forwarded&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Proto https&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_pass  http&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jruby_application;&lt;/span&gt;&lt;br /&gt;    proxy_redirect http&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jrubyapp.example.com https://jrubyapp.example.com;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Explanation&lt;/strong&gt;: The&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;proxy_redirect&lt;/code&gt;&amp;nbsp;directive tells nginx to look for any instances of&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;http://jrubyapp.example.com&lt;/code&gt;&amp;nbsp;in the HTTP headers of responses from the upstream JRuby application. If such an instance is found, it is dynamically rewritten to&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;https://jrubyapp.example.com&lt;/code&gt;&amp;nbsp;before the response is sent to the client. In this way, we ensure that any redirects or callbacks generated by the JRuby application are properly constructed before responding to a client.&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;Failure to handle cases such as these can result in nasty redirect loops or cause clients to attempt to connect with HTTP to HTTPS ports, or vice versa. Failing to setup proper&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;proxy_redirect&lt;/code&gt;&amp;nbsp;directives when they are needed is one of the most common instances of ‘under-configuring’ nginx.&lt;/div&gt;&lt;h2 style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; clear: both; color: #4a4a4a; font-family: ff-din-web, sans-serif; font-size: 22px; margin: 0px; outline: 0px; padding: 1rem 0px 0.5rem; vertical-align: baseline;&quot;&gt;The Final Configuration&lt;/h2&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Situation&lt;/strong&gt;: After several iterations, we finally have a nginx configuration to load balance and reverse proxy for our JRuby application. Our nginx server can handle serving assets locally, display a maintenance pages, proxy to upstreams, forward HTTP headers, and handle both HTTP and HTTPS requests.&lt;/div&gt;&lt;div class=&quot;wp_syntax&quot; style=&quot;background-color: #f9f9f9; border: 1px solid silver; box-sizing: border-box; color: #110000; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; margin: 0px 0px 1.5em; outline: 0px; overflow-x: auto; overflow-y: hidden; padding: 0px 0px 1.5rem; vertical-align: baseline; width: 689.03125px;&quot;&gt;&lt;table style=&quot;border-collapse: collapse !important; border-spacing: 0px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px !important; outline: 0px; padding: 0px !important; vertical-align: baseline; width: 687.333312988281px;&quot;&gt;&lt;tbody style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;tr style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;td class=&quot;code&quot; style=&quot;background-color: #eeeeee; background-image: linear-gradient(transparent 50%, rgba(255, 255, 255, 0.901961) 50%); background-size: 1px 32px; border: none !important; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px !important; vertical-align: top !important; width: 687.333312988281px;&quot;&gt;&lt;pre class=&quot;c&quot; style=&quot;-webkit-box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; background: transparent !important; border-radius: 0px !important; border: none !important; box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px !important; box-sizing: border-box; clear: none !important; float: none !important; font-size: 12px !important; font-style: inherit; font-weight: inherit; line-height: 16px !important; max-width: 100%; outline: 0px; overflow: visible !important; padding: 0px 4px !important; vertical-align: baseline; width: auto !important; word-wrap: break-word;&quot;&gt;upstream jruby_application  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  server 10.0.0.2&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;8080&lt;/span&gt; max_fails&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;1&lt;/span&gt; fail_timeout&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;10s&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  server 10.0.0.3&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;8080&lt;/span&gt; max_fails&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;1&lt;/span&gt; fail_timeout&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;10s&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  server 10.0.0.4&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;8080&lt;/span&gt; max_fails&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;1&lt;/span&gt; fail_timeout&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;=&lt;/span&gt;10s&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;# and so on: server 10.0.0.x;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;server &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  listen &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;80&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  access_log  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #000066; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;nginx&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;jrubyapp.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;example&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;access&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #000066; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  error_log  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #000066; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;nginx&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;jrubyapp.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;example&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;error&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #000066; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  root &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;www&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;html&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  try_files &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;maintenance.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri $uri&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;index.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; @secure&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  location @secure &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    rewrite &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;^&lt;/span&gt; https&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jrubyapp.example.com permanent;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;server &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  listen &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #0000dd; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;443&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  server_name jrubyapp.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;example&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com&lt;/span&gt; someotherurl.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  access_log  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #000066; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;nginx&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;jrubyapp.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;example&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;ssl&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;access&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #000066; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  error_log  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #000066; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;nginx&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;jrubyapp.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;example&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;ssl&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;error&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #000066; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  root &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;var&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;www&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;html&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  try_files &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;maintenance.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri $uri&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;/&lt;/span&gt;index.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; $uri.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;html&lt;/span&gt; @proxy&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #b1b100; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;(&lt;/span&gt;$host &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;!=&lt;/span&gt; &lt;span style=&quot;border: 0px; box-sizing: border-box; color: red; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&#39;jrubyapp.example.com&#39;&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    rewrite &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;^/&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;(&lt;/span&gt;.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;)&lt;/span&gt;$ https&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jrubyapp.example.com/$1 permanent;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  ssl on&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  ssl_certificate cert.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;crt&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  ssl_certificate_key cert.&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #202020; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;  location @proxy &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_set_header Host $host&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Real&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;IP $remote_addr&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Forwarded&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;For $proxy_add_x_forwarded_for&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    proxy_set_header X&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Forwarded&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;-&lt;/span&gt;Proto https&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;    proxy_pass  http&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jruby_application;&lt;/span&gt;&lt;br /&gt;    proxy_redirect http&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #666666; font-family: inherit; font-style: italic; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;//jrubyapp.example.com https://jrubyapp.example.com;&lt;/span&gt;&lt;br /&gt;  &lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;   client_max_body_size 64M&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #339933; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; color: #009900; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;strong style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Explanation&lt;/strong&gt;: The above configuration is nearly identical to the one that has been built up through each of the scenarios. Notably, we’ve added a&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;client_max_body_size&lt;/code&gt;&amp;nbsp;directive to allow clients to upload large files through the proxy,&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;access_log&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code style=&quot;border: 0px; box-sizing: border-box; display: inline; font-family: Monaco, Consolas, &#39;Andale Mono&#39;, &#39;DejaVu Sans Mono&#39;, monospace; font-size: 15px; font-stretch: normal; height: auto; line-height: normal; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;error_log&lt;/code&gt;&amp;nbsp;directives so that we can properly log access requests and aerrors, and a check to be sure that a client is using the correct ‘canonical url’ when accessing the application.&lt;/div&gt;&lt;h2 style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; clear: both; color: #4a4a4a; font-family: ff-din-web, sans-serif; font-size: 22px; margin: 0px; outline: 0px; padding: 1rem 0px 0.5rem; vertical-align: baseline;&quot;&gt;Additional Resources&lt;/h2&gt;&lt;ul style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; list-style: none; margin: 0px 0px 1.5em 3em; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;li style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; overflow: visible; padding: 0px 0px 1em 1em; position: relative; vertical-align: baseline;&quot;&gt;The&amp;nbsp;&lt;a href=&quot;http://wiki.nginx.org/Main&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;nginx wiki&lt;/a&gt;&amp;nbsp;is great, and the following pages can be helpful references for the above configuration:&lt;ul style=&quot;border: 0px; box-sizing: border-box; font-style: inherit; list-style: none; margin: 0px 0px 0px 1.5em; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;li style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; overflow: visible; padding: 0px 0px 1em 1em; position: relative; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://wiki.nginx.org/HttpCoreModule&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;HTTP Core Module&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; overflow: visible; padding: 0px 0px 1em 1em; position: relative; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://wiki.nginx.org/HttpProxyModule&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;HTTP Proxy Module&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; overflow: visible; padding: 0px 0px 1em 1em; position: relative; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://wiki.nginx.org/HttpSslModule&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;HTTP SSL Module&lt;/a&gt;&lt;/li&gt;&lt;li style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; overflow: visible; padding: 0px 0px 1em 1em; position: relative; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://wiki.nginx.org/HttpRewriteModule&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;HTTP Rewrite Module&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; overflow: visible; padding: 0px 0px 1em 1em; position: relative; vertical-align: baseline;&quot;&gt;The&amp;nbsp;&lt;a href=&quot;http://en.wikipedia.org/wiki/Reactor_pattern&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Reactor Pattern&lt;/a&gt;: The design pattern that nginx uses for event handling concurrently.&lt;/li&gt;&lt;li style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; overflow: visible; padding: 0px 0px 1em 1em; position: relative; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;http://blog.martinfjordvald.com/2011/02/nginx-primer-2-from-apache-to-nginx/&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;Moving from Apache to nginx&lt;/a&gt;: Some syntax hints, and processing differences.&lt;/li&gt;&lt;li style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-size: 17.3333339691162px; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; overflow: visible; padding: 0px 0px 1em 1em; position: relative; vertical-align: baseline;&quot;&gt;Why&amp;nbsp;&lt;a href=&quot;http://www.ichilton.co.uk/blog/web/nginx-and-why-you-should-be-running-it-instead-of-or-at-least-in-front-of-apache-380.html&quot; style=&quot;border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; text-decoration: none; vertical-align: baseline;&quot;&gt;running nginx in front of Apache is a good idea&lt;/a&gt;: Considerations for splitting the handling of requests between nginx and Apache.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;color: #4a4a4a; font-family: Merriweather, serif;&quot;&gt;&lt;span style=&quot;font-size: 17px; line-height: 30px;&quot;&gt;Source:&amp;nbsp;&lt;a href=&quot;http://spin.atomicobject.com/2013/07/08/nginx-load-balancing-reverse-proxy-updated/&quot;&gt;http://spin.atomicobject.com/2013/07/08/nginx-load-balancing-reverse-proxy-updated/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #f9f9f9; border: 0px; box-sizing: border-box; color: #4a4a4a; font-family: Merriweather, serif; font-size: 17px; line-height: 30px; outline: 0px; padding: 0px 0px 1.5rem; vertical-align: baseline;&quot;&gt;&lt;br /&gt;&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/12/load-balancing-and-reverse-proxying.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-1576160063791077932</guid><pubDate>Fri, 23 May 2014 04:11:00 +0000</pubDate><atom:updated>2014-05-23T12:11:17.159+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Java</category><title>Eclipse jsp the function fn:replace undefined</title><description>I am using maven2 and Eclipse Kepler. And when I run &quot;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;maven clean&lt;/span&gt;&quot;, the code compiles successfully and shows the message &quot;BUILD SUCCESS&quot;. But I get the red squiggly underlines under &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;fn:replace&lt;/span&gt; call in one .jsp file.&lt;br /&gt;&lt;br /&gt;I checked the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;pom.xml&lt;/span&gt; file, and found it include the reference to JSTL as below:&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;groupId&amp;gt;javax.servlet&amp;lt;/groupId&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;artifactId&amp;gt;jstl&amp;lt;/artifactId&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;version&amp;gt;1.2&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;After Google the Internet, I found the solution, which is to include the following line in the .jsp file&lt;br /&gt;&amp;lt;%@ taglib prefix=&quot;fn&quot; uri=&quot;http://java.sun.com/jsp/jstl/functions&quot; %&amp;gt;&lt;br /&gt;&lt;br /&gt;and run clean project, then the error is fixed.</description><link>http://lifeeditor.blogspot.com/2014/05/eclipse-jsp-function-fnreplace-undefined.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-7222414532852764963</guid><pubDate>Tue, 20 May 2014 07:26:00 +0000</pubDate><atom:updated>2014-05-20T15:26:52.009+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Cloud Computing</category><title>Creation of Amazon EC2 Key Pairs</title><description>You can use both Amazon EC2 console and command line &quot;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;ec2-create-keypair&lt;/span&gt;&quot; to create a Key pair.&lt;br /&gt;&lt;br /&gt;The details is in Amazon AWS web site: &lt;a href=&quot;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html&quot; target=&quot;_blank&quot;&gt;http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html&lt;/a&gt;</description><link>http://lifeeditor.blogspot.com/2014/05/creation-of-amazon-ec2-key-pairs.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-6850684015151131650</guid><pubDate>Tue, 20 May 2014 07:21:00 +0000</pubDate><atom:updated>2014-05-24T18:03:42.503+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Cloud Computing</category><title>Amazon EC2 command  ec2-run-instances error client.invalidamiid.notfount</title><description>&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;I was using the command-line&lt;/span&gt; ec2-run-instances &lt;span style=&quot;font-size: small;&quot;&gt;to create an EC2 instance. However I kept getting the following error message:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;i&gt;Client.InvalidAMIID.NotFound: The image id &#39;[ami-xxxxxxxx]&#39;&amp;nbsp;&lt;/i&gt;&lt;/pre&gt;&lt;pre&gt;&lt;i&gt;does not exist Error starting (256):&lt;/i&gt;&lt;/pre&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;&lt;pre&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;The solution is that I need specify the region using the option --region&lt;/span&gt;&lt;/span&gt; &lt;i&gt;--region ap-southeast-1 &lt;/i&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;One example is &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAAgCAIAAAANLF6zAAAFDklEQVR4nO2aUZLbMAxDc/9T+Wj7tZmMSYIAJSfeLN5Hx6tQIAirSjvt42GMMcYYY4wxxhhjjDHGGGOMMebLOF5YUYjP30obFx/CrrjWX+IV3M3P3ZDyUd9vWi+dkyMgbSF9Xsp7/FQt7pPDFu7wZsGRThdJt6B+oC+0fq1r91SfSiIb+eBRwGNKIawn9qn8W7aYuc8421EvCH5LWq+eE/X17T2HW07O235fpPq3+s24hY0TDXSOX6KfXee80ifr8camKP2xdUMauoIPnu+9rRfVPpX/G/iyccaoObT16sWkNt14pLdw9UH6Jwd115gDneMFrKOew6q+2qvWUI2rT08F6sBpatX664qkU/kBLarFymc65rp+NUjrh9QBNdVQ1TPuW7Ugc2Dq23xU/cH6yryt/1af7AvqqwJgEmwH9fxoWJzRYeoXdXDOZH2VjzovOcK4vvIZrYLFVl+y+iwDVlX/bT3jjcmH3UxSpbz+/AhBx9Bxd2zpCp+MJVxczS75AX1PpL1W8kn1pRzAXOmYVYurnxnSvTHeVLzKM64wfav6XTrtCGl96iTuIhVOxUeWs+on6lTGWsOpE/Cc+q98xtzUAAdzVbZXdMZzxcpUqp23kgL6fDgIqojY2A6WbgcZHeJ5ip+me6u+6nPrTSquarBPJgRAmvMgB6ZL+iP4CChE/yueq5zBlgrsJ8ardpFyYJTT+qgj1TOZk0jb25xJwUrnCERNpmm7F/gnUfe2tpkR8FwxN9Vn1OFjb4urje1evEINiEOJqTHN2kSwOeyb35haqrYzs6y8m135jHMj6wc5SF3UHHb5HORJFpB9n78y0/FOwIzSaGpWK5mTSNvbnEnBSkfNpGraZoXb8agKpM/qo8EZGM8I/LT+26azHJh6qmXaA6hIL4AMZWWwtsXYT4wCW1opHvgk88FN9+qnxeP8B3uveGbGTJ/jCLw4qGRyk3xe9DzgNTo+/9MW7Of4ZazTzlvpV8/8yClq/oO5KttjHXVY4GdlrnZl5ZkaSQ3iuReLSOvACWky9dO2YIJLa7D+qSzVx+3ip+1QbURA/DQR459pwefQWhr7rPTV9Xbeyk9qj+xChnN6wPXVvMDnSv0AXudURvqJ6wMdJod0/cGdExU1f2mu08NpqNQ88CP5TNUY8WouMG9bfwRSHXW6r2LL8OBgGWOMMeYM+JPRB6WMMcYYY4wxxtwP/52P5J+ndNtzckNLxhjDMrhYd916f+j2vOfXz0Wkk74hgcE5/D8vxRjzhai32K5bz7fnPaney9XvS9L3P9gbY74B6T8AH4H0o2oLo7OFV1nV5yPLZDaXZDXqnFwNdFp9MCy2NOuL/VRb8MhMpTHGfIx4wcX7l7zO0jJ8oacbpduz8s/PFWckfbbmJZ12RtwC5zDzBvpGe6d2zLwrfat5cUdjjPkbpFdbWw9EpAt9aJr2mX5hRJ/tFwkYStIBPskWWAcskj6Z99XmSc7V+scMthhjzI04XaZ8fbuIC66+PSWf4AspXazqWx2+ryq1y6cU0a48gRRgsMUYY27E+DtDvdyri/6ia7S991M/T7DaYN7WJNlC0tn4XtItb+hLTm2MMX+M45fXH9Vdp0VyvdLZAtO06pt+McRdqc5imJW+pEPmX/V9ZO8lnX2mD4aaDUtuMcYYc0eqb5cPchMbxhhjzLXc6q9TtzJjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY8wn+AFoepItwm/t8gAAAABJRU5ErkJggg==&quot; style=&quot;cursor: move;&quot; /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;/pre&gt;</description><link>http://lifeeditor.blogspot.com/2014/05/aws-ec2-run-instances-error.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-574739659123447910</guid><pubDate>Thu, 15 May 2014 10:26:00 +0000</pubDate><atom:updated>2014-05-15T18:26:27.223+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Machine Learning</category><title>Design Patterns for Large-Scale Real-Time Learning </title><description>A presentation slides from Sean Owen&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://qconlondon.com/dl/qcon-london-2014/slides/SeanOwen_DesignPatternsForLargeScaleRealTimeLearning.pdf&quot; target=&quot;_blank&quot;&gt;http://qconlondon.com/dl/qcon-london-2014/slides/SeanOwen_DesignPatternsForLargeScaleRealTimeLearning.pdf&lt;/a&gt;</description><link>http://lifeeditor.blogspot.com/2014/05/design-patterns-for-large-scale-real.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-7714532938825727268</guid><pubDate>Thu, 15 May 2014 10:17:00 +0000</pubDate><atom:updated>2014-05-15T18:17:15.822+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Big Data</category><title>Lambda Architecture</title><description>The Lambda Architecture is proposed by Nathan Marz, which is a generic, scalable and fault-tolerant data processing architecture.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;There are some useful resources online: &lt;br /&gt;1. The first Lambda Architecture post wrote by Nathan Marz&lt;br /&gt;&lt;a href=&quot;http://www.databasetube.com/database/big-data-lambda-architecture/&quot; target=&quot;_blank&quot;&gt;http://www.databasetube.com/database/big-data-lambda-architecture/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;2. An simple introduction.&lt;br /&gt;&lt;a href=&quot;http://lambda-architecture.net/&quot; target=&quot;_blank&quot;&gt;http://lambda-architecture.net/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;3. Lambda Architecture: A state of the art&lt;br /&gt;&lt;a href=&quot;http://www.datasalt.com/2014/01/lambda-architecture-a-state-of-the-art/&quot; target=&quot;_blank&quot;&gt;http://www.datasalt.com/2014/01/lambda-architecture-a-state-of-the-art/&lt;/a&gt;&lt;br /&gt;</description><link>http://lifeeditor.blogspot.com/2014/05/lambda-architecture.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-150661528092605528</guid><pubDate>Mon, 28 Apr 2014 09:43:00 +0000</pubDate><atom:updated>2014-05-05T17:44:35.273+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Smart Grid</category><title>DLMS/COSEM</title><description>DLMS or Device Language Message Specification and COSEM or Companion  Specification for Energy Meeting is a specification that specifies an  interface model and communication protocols for data exchange with  metering equipment. And DLMS/COSEM has been adopted by the IEC TC13 WG14  into the IEC 62056 series of standards.&lt;br /&gt; COSEM specifies the interface model, which provides a view of the  functionality of the meter as it is available at its interface(s). The  interface consists of attributes and methods, where the attributes  values represent all the data in meters and the methods describe the  allowable operations to be performed on the attributes.&lt;br /&gt; DLMS is an application layer protocol that defines how the data can be accessed and transported.&lt;br /&gt; The DLMS/COSEM specification is document in 4 “books”.&lt;br /&gt; &lt;ul&gt;&lt;li&gt;The Blue book “COSEM – Identification System and Interface Classes” specifies the interface model&lt;/li&gt;&lt;li&gt;The Green book “DLMS/COSEM – Architecture and Protocols” specifies  the architecture and the protocols with DLMS on top, for the various  media specific communication profiles. The communication media includes  RS-232, RS-485, PSTN, GSM, GPRS, IPv4 PPP and PLC.&lt;/li&gt;&lt;li&gt;The Yellow book specifies conformance test plans for COSEM object interface model.&lt;/li&gt;&lt;li&gt;The White book is a glossary of terms.&lt;/li&gt;&lt;/ul&gt;</description><link>http://lifeeditor.blogspot.com/2014/04/dlmscosem.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-3316938665334971269</guid><pubDate>Fri, 25 Apr 2014 09:42:00 +0000</pubDate><atom:updated>2014-05-05T17:43:21.938+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">programming</category><title>Two good web sites for preparing programmer’s interview</title><description>&lt;div class=&quot;entry-content clear&quot;&gt;   1. Leetcode: &lt;a href=&quot;http://discuss.leetcode.com/&quot; rel=&quot;nofollow&quot;&gt;http://discuss.leetcode.com/&lt;/a&gt;&lt;br /&gt; 2. GeeksforGeeks: &lt;a href=&quot;http://www.geeksforgeeks.org/&quot; rel=&quot;nofollow&quot;&gt;http://www.geeksforgeeks.org/&lt;/a&gt;&lt;br /&gt;      &lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/04/two-good-web-sites-for-preparing.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7368492749480468247.post-8039696039206833749</guid><pubDate>Wed, 23 Apr 2014 10:05:00 +0000</pubDate><atom:updated>2014-05-05T18:09:12.468+08:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Web Development</category><title>Edit The Opencart Footer Area</title><description>&lt;div class=&quot;entry-content clear&quot;&gt;Firstly, in order to remove the “Powered by Opencart” text from  the OpenCart Footer, you need open the file at: catalog/view/theme/[Your  Theme]/template/common/&lt;span class=&quot;skimlinks-unlinked&quot;&gt;footer.tpl&lt;/span&gt;.&lt;br /&gt;&lt;a href=&quot;https://www.blogger.com/blogger.g?blogID=7368492749480468247&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.blogger.com/blogger.g?blogID=7368492749480468247&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.blogger.com/blogger.g?blogID=7368492749480468247&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.blogger.com/blogger.g?blogID=7368492749480468247&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;/a&gt;&lt;a href=&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAq8AAABJCAIAAACcgVh8AAAgAElEQVR4nO2df1BUV7bvV9Wp6q6uZqKHKpCagBCYyB0dHkYppIDE4KDcSC5Kca/c8OwyQROuV0MSntEnzyt58UdE7VgWmMdMhDExPiTiBaM8fwzpIoxighe7CAZUZOxn0RPojLTv0kVNd52q/f7Y55ze51f3AZofhv35j6b7nH32WWft71577XUAUSgUCoVCmdvATDeAQqFQKBTKDEPVAIVCoVAocx2qBigUCoVCmetQNUChUCgUylyHqgEKhUKhUOY6VA1QKBQKhTLXoWqAQqFQKJS5zhSqgXvNViCwNt+bunMpGbrTEuU/eVTLnaHpPLtOnN0XY40MG73KPjQ6OmRfFc0azAkt3c6ZblcI+Blf2lOBvdlqBkhI3+r0cc7ulgSzAd+Llspi/1ORXDwbnwo/g4UJ4VlbaziNf4+N3F5qZEqrbdPaKAVSR7d8Wt0cZdLMEiuaDUxtbMAz4rpat9esUAM9LdWskQljf331h+EpPfuVT3ebFGrgatV2A0Dkc2t7Rsam7ux6EF1zifWq6FPSN1fNbKtCwgxd2lh1yWoGmF+vLJ1Cw3oasFqWAwAAU9XST94LhJBnxHnIkjn71cDgrcZwMNVc69f6wu2z+xmIsw081n3I4e3pCQCGtds/Ce2T7/W4vzzwBkPVwFOIzIqGf7iaYDYYzJGftPTMbMOmn2lYKfjRsiRSVQ2w0Rk3xvEkT4x7yzXUQEySxeHTmnVME46OL2PMBgAormx5PHAjI5oFgOUW68y2KiTM0KXxaiBjw76pNqxZzo0z+1gjg5878l7g/2J9NsvVQGNFoYld/VDz/2P7C5bGZ5U9GccheTVg+fDLkD/5QjCSqoGnC7kVCWog5ssOx0y2ayaYBjUwVJwcNf0rBQIqamCWwR1+Lb3W9gD/0VK5paymbdrbgHsp5I5sNlzaXObHTclpbbzg5qyWleK90K0GtAxjigyG5FH+wnn55fVa/x4b6VoMUHG6awqbMB6oGngamW1WNLNQNTCzcLcarUVldThu6ehqys3d6ZyBiMVUOPdZcmlzFm/TgX/dfbIVIYTvRWHp70eF/81+NfDQVmuC8MZbg1pfaK8pY4xLb8/0Yp8IVQNPI7PNimaWSakBZ29HSW6x5rIeD1UDWvztk3eLPm5o9yKEEGr7dPeWii/cMzNehty5B7m0oTv/Jze3pKN3skmF+ixwDjK0q6DgbFsPhxBCf6vb+V//Z53NS/x71qsBrmZrVnhCoaYWQI9LM+KWFuyfPV6cqoGnkFlnRTPLBNWAy2F/Z326ASAm6XXZE+se7CnfmDvfbACAMDYyd+ObKxbOI9WA2+X4+tKZkrzfRrIv3ZMn//sfJz2Zul6P83iZJYYNAwAAQ9ySl85d75N+RaYGONdf7jf94cSG7LS/S3+LdIVks2UUV7aQjbE23xu+32HJTg0zMgBM/LJ1HfenKmWN87kbq8sTI+YDAGMMW5yW3y4ZQb3tDcdTE2MY/vLTqs53CEMuvnDAq/Wcb7hK6KgwNv6Y2tcI/OKJ7GGDeX5atkW8WFmfOHvb1y2L17lm/+TRd6ueiwQwpK9/x+5wTaBn1CzQ6+iznzlx+Ldpi1/afEzZyOLKltGhPuEu+2+cs7c9Py3RAMAYwzLXv+/wkONmEMNQbRthHjA/Im7DWxsXLcx/hBDyJ/dhk/a2NxyNZ8MYI7vvzA3h17J7+pIwqIcSQg2MNgkGFsbG/PeaK8EM408an9/Bol/488/iYedHJJZXN5JakPM5t6YngLapcL7+LNZUWNGo1f7HA7Y4YPafvY3/JHqVvC9DRJNg04HG+/aOE5W705bEvVXZgohEV/ExUR5N/LD/9lVLdho2A4N5fu7GHTItS6gBruN8Fb6DBvP8wrKTo0gCaVH4oSYdSAALmbwxI4SG73fu2JgbyYbhs6dmWy533hXvDdEnUS13hvquN+WmJRoA8KPaNzSK9HnsgEIziIUH7mqifyQtZIxh60qODfs4hLztDUdFk36/+pK8CwRkVoQQ8oy4Or5u2v3WhriIvxN8oP9BUDwvvCP1epxHS/LxjYhJzLzUJUs44HraGoVuhDA2Mp9vp7pJyCCcTABvHxrGrQbcgz3lG9cYANjolDOtdllH910/E2tkzBHJ+F+eEcfeglR8VYIaIL0Mb0Yuh70oJRYAFqZt6Xe5xaO5HJ3ZC+elFux1KmwaIYT3rS1Me/PhiAchrqft81gjAxDVItmnIFEDpB2T9jo6ZM+MMDPG2KYuB0JcT9tnUQCMMalzyP8gO3u/XsaaAGD7B0f3WeudIx7O5/68vIgBCDiJmTijQ9/nJS5gjAtOfHXLi5Bn5E7OL3/BGJ8XVoJHrZZMxhh7qtXuRcjrce4tSAVgSj6+jH/u9Th35y0DgP/yj9sP7drX1e/k/L0ki8GqR1Bwt8SmFOEB29lrS40wM8bYy0IPi31SYCneWvFZb1dzFABA9NW7P+m4Pm/HxZMp0SyA4dWSg3cH3cF/gRDStkDSGZHpii7HzcwIMwDkv7f333ZVOUY8CHmbDrzBAJgjMj87ffzo6T+6PV6hAyHDYhXnCnoMQ8boUGeSkVmc9faDEQ9CyOWwb1uTTMhZ79f8PpdFxSUbP2u1N1cWA0B0SslPCHE+5441yQDmsuqvPD7O6/nx3exfAZjF9f5QgfsqcsnaD/bsaetxcAg5ur5azJoU59IKral+7r3ZcMgMAGB6KW8LPqxw+ZBpsYpdxvmc21f+OoBw7L9WY5I/yBJs1aWMMbVPcKmcz9PK710yHjl3y0N83nJkK2OM/byt5yIx9gse1mtvPRVrZABgy0f/7vY7GW9n07F5YN7LB1S4lo+3GgCS12yzO1wIcY6e1oxoljGyx5rtYpME37Loo6pD9a12L0LuQfsrCeEADJkug3d7rtx02OXxIuS11e01A5jYjG5/sDqQhUzGmBFC9uZjrJFZkJgj3p3X0xMADFs/bhHGFd7IASL3Vh6sarCRRxOn0aTHfjjiEW+so+ePy1iTlsdGwS1cT1eLZoZb2ObxcV6P442UWADItHx4fM+uP9oHvIK/AjBZm7v1WJFUPpIzIhfegxO5JP/gh/8mPC9NsUYGwPxh3We73js64HJr3E18Rb84fO5bwktPwMkE8fYhYRxqwDPiOFryqgGAjU46LgSBScZGujMUDoXzPVwnjQ14PW5h459/xj94qzEcAOT7hR7mRKRqLeq015TJBvXa0tUgn7HJ3ZZnxFm3c4Psh40VhQBApCxxVksqAJTVtBOH4g6/9gIAbDpwQTQfPImRukXVSZUEfYsmo4cKVwCAuBH2yaP2eOLnbTVlDDAVpzvFH+CMGNK+e88fBoCo5E3Egj1XszUraC8hhBB6XJb1vMwou05XAECqxSr6DtwnOaW1HEJjIz2ro1k2OvfBONY7vO0Nx5OiWcYYtq7kqMPvWVQIaoFu1wAWQLLNCxcOWABgReEh4vF6lL9wHgDsrvtW/OjH7guRAIwxXVx60GcYEvBAe/h8r/gJ53MUJKy65/+z9wUA8THpaalmjcbcsjoOcRcObAIAYof9w9WsibhZoTItvpFSt4Xqy/MBYHVpLfnF8agB8fPIC90/Si9fPigGhLNaUuMySrUjTMPFyVGKOgRj+wuWSnsPIYTaa8qEGAPn7O/akBwlM358i2Wne2irTRVGPsfN+nAAE5vVT1i1s/tCFAAhzUU1IBEx+HkhU9axjyLs80lZVrzsxmlbCEKTMGasU2U+dnSoa4XcaeNdYKZDjf7cuscDtjg1jy1bdB8buZ0a8dt+zcc/iIXr7GrVFj66WT8PAGDRt4S/wn2lsbFZxYo4n6ertS5KYdu4M03sii7i4Ph5WZSzm7gRuGFMVYvY6/wFivdXcOP+ntTjZPR4+8mjSw14Pc7jZUWskQlj4482tHk0To+jTFHJxVJJr5o3oFx3HK3ISwIAMjzY3WwtKq/XulbHN5+zRuPqkmrRGHEDpCOBitvCzy2pBnD0ifQR+FAyM8Jfk17IVGVFCPIovv0R70nwWCtMzQcLE8IVs3DsFEy1tof4b+z0ZUOjzl7CDcAzEv8JbtbPAyD3fan1ybjhfJ42ISJaVHZcObHQaYEo4CVLBZAus9RpGCS4i8SAimobVRfdcRUU8vYJO+LMVaHe+qyaN6DTMCbwOT6yzhBa0GowWnUI8FgiHZ+Gt6RkkXJWaQnCGElGy8aslrX1N3G8lxcZit0Nw8VSYaGaN6Ds5xun9hjAsL3qqvgdpY0FTsuYsDHjUWdxXoV0dsWPPYTEx0eT3UTlnX1cmhEHxHQFIXT77P7XtNd3glm43q5WbWGA/lfd2KxdzULz4DqeF6U/fLInN8lgTiAq68h7UoeT0eXtJ09wNeD45nPWyBjMMQfrLgfMceNFrnRugXSrARweJIXh49KMDH2lRbwD9vbdb22INBsmpgbwc0LoRPUp4HSqARz5mCesN8sQ4wSqiI2ZjBrADdBAPl6G5PJxkkSM2cAY2c+/8a+96bZAhEKtBnQahpRRqyUTAACYmMTUAyfOKQIe6r7+oa3WBACwuGvqM5ynWQ30t1QxAKS0DcDts/uZgN/UrkMgH5/6r9W8Ip38qVkCHy0T7/LjAVuGP1TAz+2Um9Cw5YuDq0414D+rz9PdcakkLwvnl0y9GuD9s3LTJj4g4Wp0qgF8p0iRF8RjB7NwvV0dEjWgbUWhVQN+PCPOS3XHspbFM9KeDOpkdHr7yRNCNTCkUHCSz4OqAUEB8Wkdg7caVwbL9nT2duzYmDvfbF6ebbnU0d14YBPI52261MDYSN/6xAV4fVFcXGejV8uKFU6nGhADLarJOILpBxk5JqMG8NcUMwk5P281oNMwFPDJX/hxZYzs25XniHCiuq8X8h6mIyl9mtWAP4oefGvPWEXe4oBWF6gOgXR8GttfsFK2R1HNEuRB78aK14jMMn51Rmnh2PLFPtStBri7nZct2anPmJ/5+4072u0DhyzLQSgTKT1paNWAln8WMwdl3wyuBjjfg5wIM+mx10rTFGQEs3C9XR0KNRDAikKsBjif+3Ld4dTEmGfY+B2VpwZcXcsByIl+UCej09tPnhCuFPxUkhINAJYDF6Sf61cDyFZdCvwaHlezdX2A3cZIqMQuJF8gpP6c6FIDCCHO99fKjS9i920wz88vOaqMV+tTA6FZ3L1qLYHgsYEg7nXysYGgm9B+3isFSJ9haF2Ws7/7YMmrBgCQpC6rG78wgQ7wzIc4b2Da1IAwDAR3Z08etcdL07xlBK5DIOTxmGqu9T8esK1VTCdU1QAZVOB8/etTLMTR+9ONDKhFg7Dlv/DaYWyL+tQAd7FyC874uyWkzao9QVOhBnj/rIjd8geMXGL5UXK04GoASTy2ivaSEczC9Xb15NVAQCsKpRrgfM4tfHrjEWEmM24no9PbT55QZhFqrEuNQw2IC0sHa3+XlfVuwEUCPnGGXLWahBoYPbZ5Vd57fwjs5qczNiBE1bTKsPOXH7iK1mTUgJCVE8SDT1oNhDKLEIVeDegyDBKr5eUvrj8kP+k8XcFIQlbqxi8884Eq84eKGckbCJgYyBO0Gkxt6erA+QdCVuC2I6V5yp7UUAN8UMHEZv2u+t13JSkL/GK2YhDlF7PFoUuPGsCZX7JbPF1qgO8ZRS1nPi5NXOA41IDgscN/33w6I9j9DWbhert68mogoBWFUg3gNFJpXuQEnIwubz95QrnD8PFA2/NGBiDqguRVdeNQA0gwWaPxGa1tIdIjSJK3cQbpBNTAT3evRgOsKNznDDgaTacaEJ8BnK4vMjpk35Dz9hCfZQrhCQXSty1wFyv/xdrEJ51NRg3gPQUAUCBN5OR8zn9Zub7nP/+G/5yEGgjxDkP+SkKqBnQaBonVsjw2ZYtTUmqpJUpydi3jH7NaMgDg+awy0qtyPue/Zv/THaHDQ8IUqwGJuxf2FOjJhQxSDSZoHQLkH5+Y2JQtyh2KWmpAXKZ8JiKzW6pFhER3ST45/tAc8bIinBtIDQjfIfdc8LtypkENCPmSEv+MPyS3DY9LDYhZF0ajKUBERyCIhevs6kmqgWBWFEo1oIi7iBtGxudk9Hj7yRPi6kM4em+OSG66cdeLkNfjOr1v+y9ZE0hCJejB9S/CAQBM+774kyzqi7eyaEXIyS/isSo25Q2Hx8v5PK11H61duQwAkvL2iCdyOb5ZBADAvHGgUTgR11G3B+dxnL1xF48lwgKYH8YYtjAuLndjeZ9gl56Ru/kJ4QCwonCfSwjjuAc7V7AmANj4wbkA4euJgbcmAxher/gM704esF/NSlyO3wss7NyF5DXbuvqdHEJej+tM5basgg9waQvO5/lsZz4AmNgVHUJ+O+dzHyxcAQBRyRsf+I0Pu0L5VTi7ryRHmAHM2yrPOP2759M/ON3OKfpE/3iJpqr6EELI+4VwyX/qd+JGej2u3XlJsksmbtxZYaM5d7fts3AAgHnHmjr1G4YM7A4S0ouu9zg4hDwjzqqtr5gjMu3898WzqBg/LqEBwGQUVjhGPHhTXPHK5eS+9lDg/eaTHQDAGGMbv3vAPxU+z8n3cgEgPGHtLf8dUTcM7c95jU5UHHlQtiYZgNlSeZHYl6tebwBXg7E2ywqI+QlahwAfHo9PyokU53PvESzhrkuuPnHQW20tmbtSs8MMkJD+urgJHhfeuOgfVrne1pPzAADMhxpuCgpV7OfnL/c4OMKcsDP0elyn9+3OTIkFgPydXwi/CmQhkzFmhND3136/wMiw0RmtQr2BopRYALOVMDCXoz3JyMhurqPrfBTfpA6Z/sZZF7JtgQghhEaPl+TI3g8XzML1dLVqC7nOhoMmuVfnHeC8hdmdhJMJbEXuwQ7h4GJnets/3Y2HjHP+58XvSEVbEv1h9pvH8BjxwFZrBgAwH2m8hTt899tFuOLLF9f5LZ16nExQbx8SQl+ZmCwOlZpt6bh/F69XYazN92SFwxRhnLH9BUsDy3/M6ND3m7OX4zpZiWn57b3OsZG+f14WzwCEsTGHz30nqzUWlVw8JC1PBoTE9rjufVCcawQ5WJNKCyMCVnZqxw8xuEZVJF9DMDJfPocevVp3WKhOxcQkphLxc/kas7X5nqKImF//fn/tZLxQnixhSdrvLnUJndx/WKhFiG+oWAxR0SeatfmUTE1lYr2XLLtx+G5qmWVgw1A2qb684M3yj3LTFuNc8TA2MndjeY90kVj1FmBw8ce4iPkAYDDPf2n91sn3khTVR0Cl6/C3tQxD43O+3sD7B/aIRdMS03IbpcXmtNRAS2Wx2qDi/12wOgQ8g7caIxTLDQGMHzM2cnupMUJr5dvZ2y7Wl5TdU6RuPOquxtnd+vfL4hm+VuA7PYPu4R9a05+LBID5EYlNtwYDWMjkjRlJy97h6qJkeVNVnxbMYz8uzYhT89gqagDpsPDAXa3Hqy+3WLVNOpAV6RwyFDcCrM33VMcIhLjWz/fF8w485p3Ks24f13ryf0SaDQCGxLQ3sbXpczIBvH1omIa3Fs1+uCs1O1njM9sqz4iTfs7n+XNfJ663Rd9wNVehhjFeJvNakMHChHBFTSE/QesQUGaIx+9mZbVN+bvpQ8Pss6JZ5GSoGuAjXaqbmnAOiHTzD2WuQA1j/ExcDeBqMLW2h1pfCFqHgDIj9F+ryZPmNs1mZpsVzSonQ9UAv+9F7X5wX+xcpyjpT5krUMMYPxNXA40VhQGzhcb2FywNWv2CMi2MVZesNpkTrv4wzPmcb0irPc5uZp0VzSonQ9WAmMRheLXk6P2/uLDIdbsGTla8aZa8z4Myt6CGMU44Z79tEQAAbNhZ51Ck6QUkUE0hJOzNo0szswN+KX1pwd7/fWDzB0Tx/FnOLLSiWeVkqBpACCGvx3lib8lv4p4V3yg5P+LZ3+aV4NdVUeYs1DB0I0+2gvFklQauKYR01CGgTCc4D85gjiRegf0UMDutaPY4GaoGKBQKhUKZ61A1QKHMLf6DQqH8jAiVZ6BqgEKhUCiUuQ5VAxQKhUKhzHWoGqBQKBQKZa5D1QCFQqFQKHMdqgYoFAqFQpnrUDVAoVAoFMpch6oBCoVCoVDmOlQNUCgUCoUy16FqgEKhUCiUuQ5VAxQKhUKhzHUmogZun93PQJxt4HHIWzMt4Jeu8lib7810eyhTzr1mK3HPl0/RLXd2X4w1Mmz0KvvQ6OiQfVU0azAntHQ7p+ZslJ8r3MXKLQwwqzYfG0XI3nyMNTIJ6Vudvul+PdDYyO2lRqa02qb819CdFvIVVfpfT0WZzUxADYztL1gal1H6lGoBhJDX4+5srYvSpQYe79uQwQCzuqR6yt57NdpUXZ4YMR8ADOb5+SVHnR5vCI/u7O3YsTE3kg0DAMYYtjgtt7Gt5yl67ViocLscdTs3TKkaaKksxs6xxHpV1B/pm6um5mwhZviHqwlmg8Ec+UlLz0y3ZY4jvg0y+urdn6wWPHlhqlr6p7kdgWd9Xo+7s/VUrJGRqYGxkZ7V0SxjDCutujpdLaWEhnGrASwYy2rap6I10wj/yAVTA8O7c1MYMKzd/snUqAGutjQHgCkq/9zt4zwjD95IiX0+qyxESou7UrPDDJC8Zpvd4UIIuRz2bWuSAZgtlRfnoCAQJjRTpQYcHV/GmA3YOT4euJERzQLAcot1as4WYgQ1EPNlh2Om2zLH4b780GIAAIhquTN048w+1sjMRBRzbH/B0vissieBvsMdfu0FDTXA7jtzY8rbSAkp41YDXacrABZ3zbJXRI8fnWpgannyqD0egDGm9glhwL5mKwPRV+/+pOfn9eX5Swv2jyGE0HBxclTF6S7yv4O3GsMBwhMKHESMkfP1Z7EmCPgu+VkOnnZPYJSdajWAEEKIO/xaeq3tAf6jpXJLWU3bFJ6N8jOF8/WmR+Q84J/c4S0pGW3TuzI7NtK1GEDmUpTg0AVdKfh5MF418KQsK14YgZ5qZoUawOOTiV39UPjk0c36eRDVcmdIx6/9CuDJo/Z4iG9/JNHx9eX5qqMmfoBLrE9rHG8WqwHuVqO1qKwOPx2Orqbc3J3Tv9xLedrhfG7r5vw6Wx9CCCFv04F/3VlzZZrNqL2mjDEuvR1s1kfVwM+J8amBxwO2OGD2n709Ra2ZRmaFGsACHMBUc41fFLRVl5ojXtETqyUVQNfpiqjk4mHpF2pLVwOAMsMDP8DStR7ubudlS3ZqmJHB6Qu/UU8v8HZcPJWblmgAAIAwNjIt29Leq5Il53Y5LtUdTopmp8JNzFY18LdP3i36uKEdJ320fbp7S8UXbioF5HgdffbDZUWsMVohecX1cjnT9pAGsFsxKURGyFeC/vafd4qy/ll4rP66O++VL6RP4vGSVw/WXZ6kaXE+9+W6g+VVVzT+/7g0I07PrC90amDo3dzckxc7QpkzRRkn41MDtupSUjCSqdrLLdbh+x14RGGMYakq44S3veF4amIMAwAA8yPi3qk8N6o4DgBEJRdjPxHgCZzwuQSCqgHJ1gP8zJOZtFHJxX8e6ivfmDvfbAAwJKoMn5I2yK5AOCvOG4Co5E1OH+foaoozx13Ul4VOKICxirzFhRWNsi/0X6sxAQAwbxxoIp6xwcKEcMaY1Dkk9gfOYTbvOtHs8ngR4hw9bTmJCxTpBaNWSyZjjP3k4nWPj0PIa289kxxhBjBbm+3il2S3TOEmhktX/poBJiV3t0y7SL4k3Fx87za8tXHRwvxHCjsRboRsDOEjK9K05+X3tNWAs7edPJ2lrGo41KO4kAvGN6/vehMWVYwxbF3JsWEfh5C3veEoTiYNY2Per74kc4tkIw3m+S+tf6fPfwfJ4y+/h7ztDUfj2TBi7ZbraWsUZZys/1ruDHlGXB1fN+1+a0NcxN8Jg7R/bI5KLh6S5LpGKp6m0WObVzEAMUkWh2bXyQZ7ZQBM8sSRWJvvSf+7vM83XFVmiWHDAJiYxNTjgghTnAXfa8lvVR/4YHZL9rAE7BnI/1qb+zrOV+EHP4yNsZQdF/OCZWfBzkf62+C6p+lQcZiRCWPjjza0ecZvqJzP0yaYR+W571S/ozXr83qcx/luB4N5flq2Je/FOLK7vB63vePrw3tLFkdHHmu+p1R4wgUqN3Y9ObxplQEg8rn0M612qglmhHGpgcelGXGpFitpgDjxDQDCE17Ya613ebycz9PWcGSBkWGMscTAhv3Fwgv2hxxC7sGeopRYwow4R09raoQZADJeP+L2J9V77a11UdIku0mfCxM8NsD5PPft7euSo4CYAXg9rkOWTAAwsXFbdlU5Rjwa4yIeYiHTcsTt47we5+68ZQBQUF4ve3zHRnpejjADwHNJS5OWreu4P4zUhj2hAZrzJ4wopIh+AACISVrzZavdi7jOhoNhxgW/v/a9+CWcXjBvYf4jolX4Q4Colh/4Ufv22f0MwOK8CnK6gD8k8x5k3TsBNTA61JlkZBZnvf1gxIP8mY9+J447h7xSz4hjb0EqABh/kdHlcouHcjnsG5KjYlOKegbdSEMN2JutZmCKyk+5PF6EvLa6vWaA2JSSAGJlQnhvNhwyAwBE7q08WNXQ5vFxXo8D23Om5cPje3b90T7gRcjZa0uNMAOYrM3dRCOPsUbmzUMXPD6O87k/Ly9iAKTRIO/Xn+42AQAsKi7Z+FmrvbmyGACiU0p+4q8RYlPecHi8nM/92c4NAJCUVyGM6KRR+Qdp8ZuRS/IPfvhvNknzZEPF6PGSHEMQNSCcjL8LcjUwNtK1GF7o1f455/M0HniDAQAI37B9r93hUlWuxNf8+fB/dXzzKzC8WnLUMeIJ3DoNux2ryFt8+Hyv9g+5B9814gT7F17cUN9q9yLkGXEc2ZzDAMSmbBEWjPxfE3fucb6/lmX/Kibp1bYeh86x3T1492DJqwYANjplPPNpb3vD8aRoFoJ1ha26VPlQD99vT40wM8YFR3jrdZ0qL8LuRewupbIhvrbw32/1+z27x54BLlUAABDqSURBVHXszWxzRKqNmMg5eztKclMYgJikVy933qWBtWlmHGpg+IeWKCKmLYIF7wuvHSZvXufpCgbALCTC4HQ50gU8tNWapD4dDy3hCYVketvgrcalRKw7VOfSv1KAz0jGA/FoFLnE8iPxNcfN+nAAxvg8TvbBOy/IdMvhH+QpAhjO5z75Xj4AyMSEs797V0EqACSv2dbZ5/DKf9WXagyvv/kIIfToZv0CxWEFvO0Nh8KF5zOMZX+ZmPNtv4v8xlVrCQAoMkN58S72T9XmdFCIBi3Pru1Vg4O7l/S8nM9RkLAqgBpA/g6XZUcOFiYsFYcEpRp4PND2vJEhxkWE/T4AY23uIy8kALqv8UfLkkgA06FGf2bWo5v18wAAFn1LTPQvHLCAZGvik7KseOmJHq5mTbJu53y9LwAAmHEOY09LNWs05pbVcWiwMCEcYB62FsQbDwNEognn83Txe24lx/yx+0IkgIld0UU0z1ZdCpOIkGvZzNCdlmhjeuBddMJvJaIBy0fxwvFnVksm+FUdd+HAG/r20WjZ7VBxcnSwPX78b6WiYbQiLwkAckprxbNjccYYYy//MIwQcnZfSPHLhXHgHuwp37hG33zaa289kxLNAhjWbCzH4lib4eLkqKytNZziQwBGmhU7ujtnkbS7vAP2K8tYk9S1YgsEWemC2tIc1UVnZ2970YtJDDDxy9bpV0iUyTMONdBYUWhis/oVVqscL5Hf44hzCMe6aJaNXt0jDDlK1yyku0sER2PFa6TFhOpck1cDstFIeFoAR+zVzojHV8l+AfegPS9xQablyNnKLQyANMKBuk5XyHYEiDy01bKCAqgvz5cFbMSO6Wk7mxIdva3yVFPd4aRoFo9eBnPMsfMd4veHf7gcqyhvIiY01NrwSVBPS5VZqIgiIgxm8gTGyagBfMzYlCK8K1KJRv9zNVuzAID0YoO3GlcSa5/Km9JYUQiKhEqcfbm6tHa8LQ8G7hPJKKgarlAmRny+a53RyFb7KwGoWi82MGUkHH9Onhf/XLaFXbN5sq7W6H+9aKmBe83WoMfUWOvhrJZUACDXuUeH7JkRZhwz6Gq2Juvdtatlt/eWB8/tVXcpfc1WBkCakSeKlS39g10ro5Mns1/A5bC/sz7dABCTtEYt14fraWtckxQDYEhf/47WM0UyeKsxXDHrE65CHjBQzRvAH5L9gCds5ExvbKR7bUqRdiSJc/S0rVsWzwCT9GKRanISJeToVwODhQnhqi5SdYRG6KeSlGhVr+p2DZyq3L38uUhQPNjYO4tPNefrfyXhFVJ/hO5cIVcD/OwZ79AVpqr+WKUyNoDXCASBxTsIc0SmnZ+Hje0vWKa1P41QACp7CxFCYkUzYkokzg8AwLDr5DcBrlp4etW1iHiK+vICkMScRSauBsSuwEvCB06ck4U0tfofr24Qbper2foK6dQUYwk/51ZlCuoETFwNiHg97vaLpzZkL8cZAPrUAJ6Z+f27MjYQuHnTowa6TlfI1qG0fyu/RhzfkgXehHDdM7GJ2fYhhYVqnEHVbsdGuhYH31at7lJ+uns1WiqsER/uCgdgIiJiybSbCSPMpyEpdw9xU5/syU0CYFJySzp0D6iNFYXKECZOSVaWH9CpBpQzPVt1qWqVQymilGHW7fpcZ/spE0avGnh0s34eEWwk0RiheZsgVtydpyp3JEbMj3xu+eG6S99/2xgFwEhjgzhyK8Z7b5/dv0VqZ6E7V+jVAP6m+HnryV1mgNSCvU6P1+tx7i1IBTBsJ+pzYekjHpnzObekxIKwyjj8Q0u8f8Ox5DK18XtYYblEvhDr9Tg2JkcpXScBZ2/5XwuMTExSgT1QRNF7qbrMDExK7g6HSvHEyagBhIQ8OHxVjJF9m0hb0x6NHpdlPQ9CeGZs5HZ2yhZy+V8xlvCNDLqpOkRMRg3wuznM5khL2eHu/u83qUzutdQA6rPVLTAyOH9CSDtQltecYTXQUlmcavmwUchVVK2bqaUGhDwbeczgD++tlSrs4K1TtduhOy3RxtQL/kxMJjJ6cXl1ozSxX8ulyBfdMANtf/gFgCwJd8KETg08yl84L7+8XvapzMHKPg+qBpB8pjf42q9XBt2+SNXANKNXDdSWrpat6ItojND8s4ENSwzcifntqo5GGu9VsZjQnSv0agA/A+T85v/am57lx2kmJjHzrMS18RNT8shCyyHT8uF/y0uuON2p2qSgewsDNBIh1Hv+sJrrRDg6V/RiUlzSmlOBUpO89tYv1yTFJb1YpJ3pM0k1wLfH2d+Ns6XItLUAl4a3UeBwi2yNCWnHBgI2MoR5AxNWA2Jg+Q1BeKkcKoAaQAj91fHti7/8BW7w/IjEo/4k/ODNmx41ULU5nTEuONJgc3u8RGauZGOLlhrAD6ksqWV0qCsr8SVLQSoArCg8pE8OqNttf0sVA0zO5iMDLjfyZ7aS6YFIy6UIbZZNpUYPFWZZSixmRVrGeAntSsFDW61JrTQZDnzKErbQeNTA4wFbHAAOl/Zfq7Eo9kDJmk1XCqYfnWrg4WrWpNzDhgm4ls+HhvBaLLn3XUMN+OO9ZxuPvSLPZAnhuaYqb0AMfzm7WxLMS25oTq/5oUgWHcVvvgGAZ5e9qfXgEgqAs1pSlUIeCavvatn+vBqQxQbcgz1v56Znrt96PWDajrO3fd2yxHUlB3uCuJWJqwGr5eUvrpNN45ctxKy6gKMRjoozH5w+K1tjQmpjCTaVoAHqEDFBNSAkZ5AV48enBkaH7Kui4/7QpicJbsbUwO/e/odj0lmys/tCFACZHhg4b4BMGeF8zrfS0y92O4U9Ozqrcavb7cDV3+VIM2Y4n3NTchRI0gMD5Q1IM664i5VvvVV5kUNjVZtfVqgKvUxFFqHWrA+neMv0FhqPGsCljgEga+vBd7OyArz0jmYRzhS61ED/tRpVwYjB46Wsyg324OJOLWwfpLTE6cqq8d7SjDgAMBqjlGcM3bkmqwZkCZV4kdIc8bKYuli1OR0g6uyNu1pPKQ6didsQRC4feROHE1ZttqrVGCEVwMPVLFtre6g8uLgwqQgwjB4qXCF9gL2XqnckJq0NLMA5n/t3ZQUpa7YFS0jGTEYNLJc5RzwGiIcKPBrhjHfGaHxNIV619hQAhNfflBR8cnZfXP+69W/jbXoQJqgGhDA4ueiDtyfoVQNXrSUApn1f/Cng9vQZVgNq4P0dfiEo/FbyKh28p0BM0cefWS0rRct/YKs1K1J0tVqn3267TleAZP1xSDYfwC2pyEsCYEo+vix+ZG+2pgqpNpzvQc44xArPFO0wxKv7qrM+oZ2SHTFofGpAnOkZMy1WVf1NdxjOLHrUAFezNUs1HI0RSmowOZuP4P33t746scDIkMt1bTVlOGe+qcuBqwu8/o9rwwEYY1KHYnTBOlT1NYmhOpdnpDd34TwAyLQccvHRV67l4+1hRoaNzrhB+BotNQD+twFxD777KjnCLHM3uBkk8yOefX5JWpWQzy8mCixIzMES2DPiPFP5Tvb692v4DdMQk/Tqua87/uIiu8ivAB7drA9Xm/1jnN0tCWYDY2R382WFkNs1cGRzDiPdGnD+wyK1+kgieHR58tGGtABfIscGr8d9V9hlFJtS1Nn3Z3EQGhvpWftcJIBhw65TWtNx7EoS0ouuC31StfUV8v6KtRDOffdAeeXK/E0Brrf15DwAAPOhhpuCA+Vf7GSOSD7T2iVWVUpPymq/H+KKAy5He5KRAYCNH5wTOoTrbDhoAiBVI+fzfLYzHwDmLczudLiQX7LwK1+eEcdH219flhAOwOypE/eGcHfbPgsHUB318XBIEsZGxsX9pry6STQD92CH0LyzQsEPb/unuxl5V3vPf7ARAEzsig5/fEhvvQG36y9X+LoITFH5qT//xRXY48uWq8WKUuIj43LcyktcQK6+e0YcFYUZ83+Zc8+fzvL/3s/+FQDIdrfLCGC3qiiSFXg1QO7IP1GaxwBkWqzC2O9pratgjfM/bfWPlDc+fR8AAMx762x6xvWpqz7Uf63GRJQYkYHDloxxwYmvvvP4OM7naa37KDH6GZCsYSGv50F+QjgArCjc55QLDjzTU80/o9WHZp7gagDH4QPkf+LxclHO60JhPnkFLoQQQqOn9m6ONBvAv2w5dmrXP+Nigqs3HSZTVTlffxYbproVNSTnuiWv7YOf5/Gpgcgla/cQZblyVeJv3pstf1i2IEwxdPonCmK2IwDggobCgj1fvEhEVN8PbbVhggLQ3luIxOOf2FuyODqSEcaAtGyLTHQHy0zEnaO36pFG+UjeYwpqANQ2JfLUlxe8Wf5RbtpiXHcvjI1U9O3oybJ/Ev+blr2pS3IormZrlrKoquwyyRvaf/uqWOZPzZxCgKxbopKLhxRdutxiVdbjwxOs76+dwvtixHde99lOxfOV+FZ/9+iJ4iYq9u91fJX7Qpzyxry8uWpMX/OKK1u0mqdPDaibEL4R5/dtlG6h5NFQA4sOEsmG0lKkZAv5TpB1jmo4MIDdDt46H2U0Kt9prqUGXt95UEw2lNZJlLQEP9GyOmN6drJMWWVizmpJDfyqeqJIqCExLbfpeh/OJxCvSFE2TR6pun12f4R6/hmtTDzzBFcDgd9yjbTz/CcM5+vPTcx7oGbuIT9XUPAZybfU64mUjg59X5AUI85gMG7XX67W7TWrLb/NKcZGuhbrfTPTBOBqtuYShWjmOpzPuTM35ZmIZHLK5RlxCS+nnw3vI9WKzz/KXzgPiHdqTMtbKOXI9gqJ4KQTYtPdrHj1yYTBQTUdu/4oP1uCqoHgb7kO+Qhtq35Xa5/9TKkBchOaDjWA82VUA2KP8hfOY4LVXPt5c/vsfmbKBqHHA7YsvaVm5gQ4PUVtFyVeldf7+uyphN9JJGtkV+MhE1FjFM2QGsAbVWSppqNDXStYk7QA4tOtBm6f3c9oR+woc4EgagALxsAbskMxQg9vT0/A1QNHh7pytGtUTYsa4OrKck3mhJZuJ46emdiMbmLo0qEGcDUkFTUwOvTtImnRtLkG3kVJFmqdPFertpv4OPPoocIcWUrgHAfHcpWPMOd7uG7hPK1tw9PM6JB9VTSbvGZbV7+TQ8jrcdsajiwwMuaI5CtELs6MqAH8vo9niMySAbstJ3EBgHmH5EXDT7UaGNtfsHS6NtdQZilB1EDX6YrAsUSvx/3793IBwMQuu2K/P4GsFoSQuNpXUH7yiOVVLW8eonMFhX+qn88qezjYkWR8hiwPwvk8tk924FXJutZOt8YCM04hZKNTzgjf4Xye7o5LOYkL2OhVumuh/NwYHeorSomd2H6qAODl2PCEgq8aj1gU74Wa4+AUQoM55miDzcVndXkH7O1vrkk28JJ3ViDNoWEioxfvqDwlTeDwfn/l9/MAAEy7P73iCvL+oRC3TvYu79yNO2T1fNyu73Fi8rK83feDZUfONnAl8ukqw0WZpQRWA0/KsuIDTGTV3jA7MdnOZ/mFsfEnidfrTc25gmNvPh5pNgAw8cv+vul6n/i59CW5GK31b66nrXFDdlqkv6BeWMKStIrqL12hzlB7inhgq1tTWBHyHD2cUscYw/6p7OQc1VkBcfa2l+T99ll+oAUAw7NxvynZeyLYC/1mFSrvO549s3BlKu50rmZOnvaaMumbFChzkXG90ZhCoVAoFMrPkCBq4D8olBAxPQZNoVAolAlAYwMUCoVCocx1qBqgUCgUCmWuQ9UAhUKhUChzHaoGKBQKhUKZ61A1QKFQKBTKXIeqAQqFQqFQ5jpUDVAoFAqFMtf5/1Ps7g2gN0cCAAAAAElFTkSuQmCC&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;/a&gt;&lt;img alt=&quot;edit_footer&quot; class=&quot;alignnone  wp-image-1338&quot; src=&quot;http://cartadvisor.com/wp-content/uploads/2012/05/edit_footer-1024x166.png&quot; height=&quot;105&quot; width=&quot;640&quot; /&gt;&lt;br /&gt;And then you simply delete all of the text between the &amp;lt;! and the  -&amp;gt; symbols to remove the comments and OpenCart Powered By text at the  bottom of the pages.&lt;br /&gt;&lt;br /&gt;Secondly, we want to add an image about Paypal payment at the bottom of the OpenCart shop web page.&amp;nbsp; In the same &lt;span class=&quot;skimlinks-unlinked&quot;&gt;footer.tpl&lt;/span&gt;, at the same location of the deleted OpenCart Powered By text, add the following code:&lt;br /&gt;&amp;lt;div align=”center”&amp;gt;&amp;lt;img src=”&lt;a href=&quot;http://vivoharmony.com/image/paypal.jpg&amp;amp;#8221&quot; rel=&quot;nofollow&quot;&gt;http://vivoharmony.com/image/paypal.jpg&amp;amp;#8221&lt;/a&gt;; style=”margin: 15px 15px”&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt;Lastly, we also want to insert the copyright text at the bottom of  the OpenCart shop web page. Thus, after the Paypal image, we add the  following code:&lt;br /&gt;&amp;lt;div align=”center”&amp;gt;&amp;lt;p&amp;gt;Copyright &amp;amp;#169 2014 Vivoharmony. All Rights Reserved. &amp;lt;/p&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;br /&gt;The &amp;amp;#169 is to display the copyright sign “&lt;span style=&quot;color: black; font-family: verdana; font-size: x-small;&quot;&gt;© &lt;/span&gt;” in html.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;/div&gt;</description><link>http://lifeeditor.blogspot.com/2014/04/edit-opencart-footer-area_23.html</link><author>noreply@blogger.com (MathBee)</author><thr:total>0</thr:total><gd:extendedProperty name="commentSource" value="1"/><gd:extendedProperty name="commentModerationMode" value="FILTERED_POSTMOD"/></item></channel></rss>