<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>John Paul Janecek&#39;s Work Site</title>
    <link>https://johnpauljanecek.work/</link>
    
    <atom:link href="https://johnpauljanecek.work/feed.xml" rel="self" type="application/rss+xml"/>
    
    <description>Using python, node and javascript for automating and mining the web</description>
    <pubDate>Wed, 28 Oct 2026 02:04:56 GMT</pubDate>
    <generator>http://hexo.io/</generator>
    
    <item>
      <title>Using namedtuple as a poorman&#39;s parser</title>
      <link>https://johnpauljanecek.work/blog/Named-tupled-as-a-poormans-parser/</link>
      <guid>https://johnpauljanecek.work/blog/Named-tupled-as-a-poormans-parser/</guid>
      <pubDate>Fri, 05 Feb 2016 16:00:00 GMT</pubDate>
      
        
        
      <description>&lt;p&gt;I needed to parse the routing tables, therefore I needed to parse the command &lt;strong&gt;route&lt;/strong&gt; which gives an output similar to som</description>
        
      
      
      
      <content:encoded><![CDATA[<p>I needed to parse the routing tables, therefore I needed to parse the command <strong>route</strong> which gives an output similar to something like this.</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">Kernel IP routing table</span><br><span class="line">Destination     Gateway         Genmask         Flags Metric Ref    Use Iface</span><br><span class="line">default         172.17.0.1      0.0.0.0         UG    0      0        0 eth0</span><br><span class="line">172.17.0.0      *               255.255.0.0     U     0      0        0 eth0</span><br></pre></td></tr></table></figure><p>To get the output of the command we will use subprocess. So our python code will look like this.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> subprocess</span><br><span class="line"></span><br><span class="line">p = subprocess.run(<span class="string">&quot;route&quot;</span>,stdout = subprocess.PIPE)</span><br><span class="line">lines = p.stdout.decode(<span class="string">&quot;utf8&quot;</span>).splitlines()</span><br><span class="line">headers = lines[<span class="number">1</span>].split()</span><br></pre></td></tr></table></figure><p>But how to create a nice datastructure to hold routes ? The answer is <a href="https://docs.python.org/3/library/collections.html#collections.namedtuple">namedtuple</a>.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line">Route = namedtuple(<span class="string">&quot;Route&quot;</span>,headers)</span><br><span class="line">routes = [Route(*line.split()) <span class="keyword">for</span> line <span class="keyword">in</span> lines[<span class="number">2</span>:]]</span><br><span class="line"></span><br><span class="line">route = routes[<span class="number">0</span>]</span><br><span class="line"><span class="built_in">print</span>(route)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;as a tuple %s&quot;</span> % route[<span class="number">0</span>])</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;as a class like structure&quot;</span> % route.Destination)</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;as a dictionary %s&quot;</span> % route._asdict())</span><br></pre></td></tr></table></figure><p>The output is.</p><figure class="highlight shell"><table><tr><td class="code"><pre><span class="line">Route(Destination=&#x27;default&#x27;, Gateway=&#x27;172.17.0.1&#x27;, Genmask=&#x27;0.0.0.0&#x27;, Flags=&#x27;UG&#x27;, Metric=&#x27;0&#x27;, Ref=&#x27;0&#x27;, Use=&#x27;0&#x27;, Iface=&#x27;eth0&#x27;)</span><br><span class="line">as a tuple : default</span><br><span class="line">as a class like structure : default</span><br><span class="line">as a dictionary : OrderedDict([(&#x27;Destination&#x27;, &#x27;default&#x27;), (&#x27;Gateway&#x27;, &#x27;172.17.0.1&#x27;), (&#x27;Genmask&#x27;, &#x27;0.0.0.0&#x27;), (&#x27;Flags&#x27;, &#x27;UG&#x27;), (&#x27;Metric&#x27;, &#x27;0&#x27;), (&#x27;Ref&#x27;, &#x27;0&#x27;), (&#x27;Use&#x27;, &#x27;0&#x27;), (&#x27;Iface&#x27;, &#x27;eth0&#x27;)])</span><br></pre></td></tr></table></figure><p>The flexibility of python never ceases to amaze me, and I am always finding hidden gems and quicker ways to do things.</p>]]></content:encoded>
      
      
      
      <category domain="https://johnpauljanecek.work/tags/python/">python</category>
      
      <category domain="https://johnpauljanecek.work/tags/tricks/">tricks</category>
      
      <category domain="https://johnpauljanecek.work/tags/namedtuple/">namedtuple</category>
      
      
      <comments>https://johnpauljanecek.work/blog/Named-tupled-as-a-poormans-parser/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Save time creating classmethods using a metaclass</title>
      <link>https://johnpauljanecek.work/blog/creating-classmethods-using-a-metaclass/</link>
      <guid>https://johnpauljanecek.work/blog/creating-classmethods-using-a-metaclass/</guid>
      <pubDate>Tue, 02 Feb 2016 16:00:00 GMT</pubDate>
      
        
        
      <description>&lt;p&gt;I was wrapping a client rpc which was calling functions on a server rpc. The code looked like this.&lt;/p&gt;
&lt;figure class=&quot;highlight python&quot;&gt;</description>
        
      
      
      
      <content:encoded><![CDATA[<p>I was wrapping a client rpc which was calling functions on a server rpc. The code looked like this.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">RpcClient</span>(<span class="title class_ inherited__">object</span>): </span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">rpc_list_users</span>(<span class="params">self,*args,**kwArgs</span>):</span><br><span class="line">        result = <span class="variable language_">self</span>.call(<span class="string">&quot;rpc_list_users&quot;</span>,args,kwArgs)</span><br><span class="line">        <span class="keyword">return</span> result</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">rpc_get_user</span>(<span class="params">self,*args,**kwArgs</span>):</span><br><span class="line">        result = <span class="variable language_">self</span>.call(<span class="string">&quot;rpc_get_user&quot;</span>,args,kwArgs)</span><br><span class="line">        <span class="keyword">return</span> result</span><br></pre></td></tr></table></figure><p>The are over 20 functions on the RPC server, I didn’t feel like typing out all of the code for these functions. Also what if I added more rpc functions on the server ?. The solution in this case was metaclasses.</p><p><strong>Note this demo uses python 3, the syntax for metaclasses with slightly different.</strong></p><h2 id="Understanding-python-classes-and-objects"><a href="#Understanding-python-classes-and-objects" class="headerlink" title="Understanding python classes and objects"></a>Understanding python classes and objects</h2><p>To understand how to use metaclasses, one must understand how python classes and objects work behind the scenes. A great way to explore this is with ipython or ipython notebooks which is part of the <a href="http://jupyter.org/">juypter project</a>.</p><p>Simply put classes and objects are nothing more then dictionaries. You can verify this yourself using your python interpretor.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Foo</span>(<span class="title class_ inherited__">object</span>):</span><br><span class="line">    a_class_variable = <span class="string">&quot;a&quot;</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">a_function</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="built_in">print</span>(a_function)</span><br><span class="line">        </span><br><span class="line">pp(<span class="string">&quot;Foo.__dict__&quot;</span>)</span><br><span class="line">pp(Foo.__dict__)</span><br><span class="line">pp(<span class="string">&quot;pretty Foo&quot;</span>)</span><br><span class="line">pp(<span class="string">&quot;Pretty Foo.__dict__&quot;</span>)</span><br><span class="line">pp(<span class="built_in">dict</span>(Foo.__dict__)) <span class="comment">#convert it to a dictionary so pp dumps it out nice</span></span><br></pre></td></tr></table></figure><p>Output from running above code.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="string">&#x27;Foo.__dict__&#x27;</span></span><br><span class="line">mappingproxy(&#123;<span class="string">&#x27;__doc__&#x27;</span>: <span class="literal">None</span>, <span class="string">&#x27;__weakref__&#x27;</span>: &lt;attribute <span class="string">&#x27;__weakref__&#x27;</span> of <span class="string">&#x27;Foo&#x27;</span> objects&gt;, <span class="string">&#x27;a_class_variable&#x27;</span>: <span class="string">&#x27;a&#x27;</span>, <span class="string">&#x27;a_function&#x27;</span>: &lt;function Foo.a_function at <span class="number">0x7fb358f8d6a8</span>&gt;, <span class="string">&#x27;__dict__&#x27;</span>: &lt;attribute <span class="string">&#x27;__dict__&#x27;</span> of <span class="string">&#x27;Foo&#x27;</span> objects&gt;, <span class="string">&#x27;__module__&#x27;</span>: <span class="string">&#x27;__main__&#x27;</span>&#125;)</span><br><span class="line"><span class="string">&#x27;pretty Foo&#x27;</span></span><br><span class="line"><span class="string">&#x27;Pretty Foo.__dict__&#x27;</span></span><br><span class="line">&#123;<span class="string">&#x27;__dict__&#x27;</span>: &lt;attribute <span class="string">&#x27;__dict__&#x27;</span> of <span class="string">&#x27;Foo&#x27;</span> objects&gt;,</span><br><span class="line"> <span class="string">&#x27;__doc__&#x27;</span>: <span class="literal">None</span>,</span><br><span class="line"> <span class="string">&#x27;__module__&#x27;</span>: <span class="string">&#x27;__main__&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;__weakref__&#x27;</span>: &lt;attribute <span class="string">&#x27;__weakref__&#x27;</span> of <span class="string">&#x27;Foo&#x27;</span> objects&gt;,</span><br><span class="line"> <span class="string">&#x27;a_class_variable&#x27;</span>: <span class="string">&#x27;a&#x27;</span>,</span><br><span class="line"> <span class="string">&#x27;a_function&#x27;</span>: &lt;function Foo.a_function at <span class="number">0x7fb358f8d6a8</span>&gt;&#125;</span><br></pre></td></tr></table></figure><p>Inside all python classes, there is a variable called <strong>__dict__</strong>. If we print it out, we see that type <a href="https://docs.python.org/3/library/types.html">mappingproxy</a> which if we look inside the python docs says that it is type of dictionary which can not be modified.</p><p>Inside the <strong>dict</strong> variable we see two values:</p><ul><li>‘a_class_variable’: ‘a’</li><li>‘a_function’: &lt;function Foo.a_function at 0x7fb358f8d6a8&gt;</li></ul><p>If we could modify <strong>Foo.__dict__</strong> we could add methods and variables to class Foo at runtime. So we would want to do something like this.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">my_function</span>(<span class="params">self</span>):</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">Foo.__dict__[<span class="string">&quot;my_function&quot;</span>] = my_function</span><br><span class="line">Foo.__dict__[<span class="string">&quot;my_variable&quot;</span>] = <span class="number">99</span> </span><br></pre></td></tr></table></figure><p>But the mappingproxy object will not allow itself to be modified. So how can we do this ? With a metaclass.</p><h2 id="What-is-a-metaclass"><a href="#What-is-a-metaclass" class="headerlink" title="What is a metaclass"></a>What is a metaclass</h2><p>In simple english a metaclass is a class which inherits off class type and allows one to modify the class’s mappingproxy. Here is a simple example.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">BarMetaClass</span>(<span class="title class_ inherited__">type</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__new__</span>(<span class="params">cls, name,bases, dct</span>):</span><br><span class="line">        <span class="comment">#this is called before the class has been created</span></span><br><span class="line">        pp(<span class="string">&quot;__new__ \n cls =&gt; %r \n name =&gt; %r \n bases =&gt; %r \n dct =&gt; %r&quot;</span> % (cls,name,bases,dct))</span><br><span class="line">        <span class="comment">#the parent __new__ metaclass has to be returned</span></span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">type</span>.__new__(cls,name, bases, dct)</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">cls, name,bases, dct</span>):</span><br><span class="line">        <span class="comment">#the parent __init__ metaclass method has to be called</span></span><br><span class="line">        <span class="built_in">type</span>.__init__(cls,name, bases, dct)</span><br><span class="line">        <span class="comment">#this is called after the class has been created</span></span><br><span class="line">        pp(<span class="string">&quot;__init__ \n cls =&gt; %r \n name =&gt; %r \n bases =&gt; %r \n dct =&gt; %r&quot;</span> % (cls,name,bases,dct))</span><br><span class="line">        </span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Bar</span>(<span class="built_in">object</span>,metaclass = BarMetaClass):</span><br><span class="line">    a_class_variable = <span class="string">&quot;a&quot;</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">a_function</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="built_in">print</span>(a_function)</span><br></pre></td></tr></table></figure><p>And here is the output from the code.</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">(<span class="string">&#x27;__new__ \n&#x27;</span></span><br><span class="line"> <span class="string">&quot; cls =&gt; &lt;class &#x27;__main__.BarMetaClass&#x27;&gt; \n&quot;</span></span><br><span class="line"> <span class="string">&quot; name =&gt; &#x27;Bar&#x27; \n&quot;</span></span><br><span class="line"> <span class="string">&quot; bases =&gt; (&lt;class &#x27;object&#x27;&gt;,) \n&quot;</span></span><br><span class="line"> <span class="string">&quot; dct =&gt; &#123;&#x27;__qualname__&#x27;: &#x27;Bar&#x27;, &#x27;a_class_variable&#x27;: &#x27;a&#x27;, &#x27;__module__&#x27;: &quot;</span></span><br><span class="line"> <span class="string">&quot;&#x27;__main__&#x27;, &#x27;a_function&#x27;: &lt;function Bar.a_function at 0x7fb358f43598&gt;&#125;&quot;</span>)</span><br><span class="line">(<span class="string">&#x27;__init__ \n&#x27;</span></span><br><span class="line"> <span class="string">&quot; cls =&gt; &lt;class &#x27;__main__.Bar&#x27;&gt; \n&quot;</span></span><br><span class="line"> <span class="string">&quot; name =&gt; &#x27;Bar&#x27; \n&quot;</span></span><br><span class="line"> <span class="string">&quot; bases =&gt; (&lt;class &#x27;object&#x27;&gt;,) \n&quot;</span></span><br><span class="line"> <span class="string">&quot; dct =&gt; &#123;&#x27;__qualname__&#x27;: &#x27;Bar&#x27;, &#x27;a_class_variable&#x27;: &#x27;a&#x27;, &#x27;__module__&#x27;: &quot;</span></span><br><span class="line"> <span class="string">&quot;&#x27;__main__&#x27;, &#x27;a_function&#x27;: &lt;function Bar.a_function at 0x7fb358f43598&gt;&#125;&quot;</span>)</span><br></pre></td></tr></table></figure><h2 id="Simple-Explanation-what-is-going-on"><a href="#Simple-Explanation-what-is-going-on" class="headerlink" title="Simple Explanation what is going on"></a>Simple Explanation what is going on</h2><p>The metaclass of a class in python 3 is set like this <strong>class Bar(object,metaclass &#x3D; BarMetaClass)</strong>. All Metaclasses are inherited off class <a href="https://docs.python.org/3/library/types.html">type</a>. All class type classes contain two <em>constuctors</em> which will be called when the type class is being created. These two constructors are.</p><ul><li><strong>def __new__(cls, name, bases, dct)</strong> is called <strong>before</strong> the class is created. It must return the parent metaclass <strong>new</strong> method which in this case is <strong>type.__new__</strong></li><li><strong>def __init__(cls, name, bases, dct):</strong> is called <strong>after</strong> the class is created. Somewhere in the function it much called the parent’s <strong>init</strong> function which in this case is <strong>type.__init__</strong></li></ul><p>Both of these functions container 4 arguments.</p><ul><li><strong>cls</strong> : this refers to the metaclass itself. It is equivalent to <strong>self</strong> in a regular object method. So if the metaclass had other methods they could be called like this <strong>cls.somemethod(cls,arg)</strong>. Remember metaclasses are only called when the class is being created. So in the above example, class Bar can not access the methods of class BarMetaClass.</li><li><strong>name</strong> : The name of the class being created. So in the above example the name is “Bar”.</li><li><strong>base</strong> : which classes it inherits off, in this case “Bar” inherits off “object”</li><li><strong>dct</strong> : this equivalent to Bar.<strong>dict</strong> except it is a regular python dictionary. This means we can modify it.</li></ul><p>Since cls,name,base and dct are normal python structures, that means we can modify them before we call the parent’s <strong>new</strong> function. Before when we wattempted to modify Foo.<strong>dict</strong> python would not allow use to do this. Using a metaclass this is possible. It done in the <strong>new</strong> method of the metaclass. Here is a simple example.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">my_function</span>(<span class="params">self</span>):</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;from my function&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">FooMetaClass</span>(<span class="title class_ inherited__">type</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__new__</span>(<span class="params">cls, name,bases, dct</span>):</span><br><span class="line">        dct[<span class="string">&quot;my_function&quot;</span>] = my_function</span><br><span class="line">        dct[<span class="string">&quot;my_variable&quot;</span>] = <span class="string">&quot;my_variable&quot;</span></span><br><span class="line">        <span class="comment">#the parent __new__ metaclass has to be returned</span></span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">type</span>.__new__(cls,name, bases, dct)        </span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Foo</span>(<span class="built_in">object</span>,metaclass = FooMetaClass):</span><br><span class="line">    a_class_variable = <span class="string">&quot;a&quot;</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">a_function</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="built_in">print</span>(a_function)</span><br><span class="line">        </span><br><span class="line">pp(<span class="string">&quot;testing out foo&quot;</span>)</span><br><span class="line">pp(<span class="string">&quot;Foo.my_variable =&gt; %r&quot;</span> % Foo.my_variable)</span><br><span class="line">foo = Foo()</span><br><span class="line">pp(<span class="string">&quot;foo.my_function() =&gt; %r&quot;</span> % foo.my_function())content</span><br></pre></td></tr></table></figure><p>When we run the above example we get the following output.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="string">&#x27;testing out foo&#x27;</span></span><br><span class="line"><span class="string">&quot;Foo.my_variable =&gt; &#x27;my_variable&#x27;&quot;</span></span><br><span class="line"><span class="string">&quot;foo.my_function() =&gt; &#x27;from my function&#x27;&quot;</span></span><br></pre></td></tr></table></figure><p>We can see that we have added a class variable and a class method to foo. Ofcourse in this case we could have done this in the class defintion of Foo, there was no need to use a metaclass, but it is just an example to show how it is done.</p><h2 id="Solving-our-orignal-problem"><a href="#Solving-our-orignal-problem" class="headerlink" title="Solving our orignal problem"></a>Solving our orignal problem</h2><p>In our orignal problem we needed a client class which we needed to add methods to. Each method was basically the same except for the name of the rpc call. So we need a class or a function which creates a function which is similar to this</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">rpc_list_users</span>(<span class="params">self,*args,**kwArgs</span>):</span><br><span class="line">    result = <span class="keyword">await</span> <span class="variable language_">self</span>.call(<span class="string">&quot;rpc_list_users&quot;</span>,args,kwArgs)</span><br><span class="line">    <span class="keyword">return</span> result</span><br></pre></td></tr></table></figure><p>We notice that the “rpc_list_users” is the only thing changing. So my solution is the make a class like this.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">CreateRpcFunction</span>(<span class="params">name</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">wrappedFunction</span>(<span class="params">self,*args,**kwArgs</span>):</span><br><span class="line">        <span class="variable language_">self</span>.call(name,*args,**kwArgs)</span><br><span class="line">        <span class="keyword">return</span> name</span><br><span class="line">    <span class="keyword">return</span> wrappedFunction</span><br></pre></td></tr></table></figure><p>There are other possible ways to do this. In this case we have created what I believe is known as a closure. We then put our function creater to use like this. wrapFunctionNames contains a list of rpc methods in the serve, our metaclass creates the required functions on the client.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line">wrapFunctionNames = [<span class="string">&quot;rpc_list_users&quot;</span>,<span class="string">&quot;rpc_get_user&quot;</span>,<span class="string">&quot;rpc_set_user&quot;</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">RpcClientMeta</span>(<span class="title class_ inherited__">type</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__new__</span>(<span class="params">cls,name,bases, dct</span>):</span><br><span class="line">        <span class="keyword">for</span> name <span class="keyword">in</span> wrapFunctionNames :</span><br><span class="line">            dct[name] = CreateRpcFunction(name)</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">type</span>.__new__(cls,name,bases, dct)</span><br><span class="line">        </span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">RpcClient</span>(<span class="built_in">object</span>,metaclass = RpcClientMeta):</span><br><span class="line">        </span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">call</span>(<span class="params">self,name,*args,**kwArgs</span>):</span><br><span class="line">        <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">        simulates calling the rpc on the server.</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        pp(<span class="string">&quot;called name %r args %r kwArgs %r&quot;</span> % (name,args,kwArgs))</span><br><span class="line">        <span class="keyword">return</span> name</span><br><span class="line">        </span><br><span class="line">rpcClient = RpcClient()</span><br><span class="line">pp(<span class="string">&quot;dump rpc functions&quot;</span>)</span><br><span class="line">pp([name <span class="keyword">for</span> name <span class="keyword">in</span> <span class="built_in">dir</span>(rpcClient) <span class="keyword">if</span> name.startswith(<span class="string">&quot;rpc_&quot;</span>)])</span><br><span class="line"></span><br><span class="line">pp(<span class="string">&quot;rpcClient.rpc_get_user() =&gt; %r&quot;</span> % rpcClient.rpc_get_user())</span><br><span class="line">pp(<span class="string">&quot;rpcClient.rpc_list_user() =&gt; %r&quot;</span> % rpcClient.rpc_list_users(startsWith = <span class="string">&quot;Fred&quot;</span>))</span><br></pre></td></tr></table></figure><p>The output of the above code looks like this.</p><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&#x27;dump rpc functions&#x27;</span><br><span class="line">[&#x27;rpc_get_user&#x27;, &#x27;rpc_list_users&#x27;, &#x27;rpc_set_user&#x27;]</span><br><span class="line">&quot;called name &#x27;rpc_get_user&#x27; args () kwArgs &#123;&#125;&quot;</span><br><span class="line">&quot;rpcClient.rpc_get_user() =&gt; &#x27;rpc_get_user&#x27;&quot;</span><br><span class="line">&quot;called name &#x27;rpc_list_users&#x27; args () kwArgs &#123;&#x27;startsWith&#x27;: &#x27;Fred&#x27;&#125;&quot;</span><br><span class="line">&quot;rpcClient.rpc_list_user() =&gt; &#x27;rpc_list_users&#x27;&quot;</span><br></pre></td></tr></table></figure><h2 id="Summary"><a href="#Summary" class="headerlink" title="Summary"></a>Summary</h2><p>This is just a simple example of how to use a metaclass to create class method at runtime. Once you understand the basics of metaclasses, then the more advanced tutorials start to make sense. In the above example we could have queried the server for a list of rpc functions it provides. Then we could have created the appropriate functions on the client using a metaclass. This is the magic that many python database libraries use. The query the database and then generate the classes at runtime using metaclasses.</p><p>The best way to learn about metaclasses is to use a good python console such as ipython or jupyter notebooks (formerly ipython notebooks). The advantage is that you can modify things at runtime and experiment with them.</p><p>All of the code for this post is in an <a href="https://gist.github.com/johnpauljanecek/1e767022198dcc7e45d7">ipython notebook located here</a>.</p>]]></content:encoded>
      
      
      
      
      <comments>https://johnpauljanecek.work/blog/creating-classmethods-using-a-metaclass/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Creating and configuring digitalocean droplets with ipython notebooks.</title>
      <link>https://johnpauljanecek.work/blog/functions-create-metaclass/</link>
      <guid>https://johnpauljanecek.work/blog/functions-create-metaclass/</guid>
      <pubDate>Sun, 31 Jan 2016 16:00:00 GMT</pubDate>
      
        
        
      <description>&lt;p&gt;You’ll find this post in your &lt;code&gt;_posts&lt;/code&gt; directory - edit this post and re-build (or run with the &lt;code&gt;-w&lt;/code&gt; switch) to see</description>
        
      
      
      
      <content:encoded><![CDATA[<p>You’ll find this post in your <code>_posts</code> directory - edit this post and re-build (or run with the <code>-w</code> switch) to see your changes!To add new posts, simply add a file in the <code>_posts</code> directory that follows the convention: YYYY-MM-DD-name-of-post.ext.</p><h2 id="Sample-Heading"><a href="#Sample-Heading" class="headerlink" title="Sample Heading"></a>Sample Heading</h2><h3 id="Sample-Heading-2"><a href="#Sample-Heading-2" class="headerlink" title="Sample Heading 2"></a>Sample Heading 2</h3><p>Jekyll also offers powerful support for code snippets:</p><figure class="highlight ruby"><table><tr><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">print_hi</span>(<span class="params">name</span>)</span><br><span class="line">  puts <span class="string">&quot;Hi, <span class="subst">#&#123;name&#125;</span>&quot;</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">print_hi(<span class="string">&#x27;Tom&#x27;</span>)</span><br><span class="line"><span class="comment">#=&gt; prints &#x27;Hi, Tom&#x27; to STDOUT.</span></span><br></pre></td></tr></table></figure><p>Check out the <a href="http://jekyllrb.com/">Jekyll docs</a> for more info on how to get the most out of Jekyll. File all bugs&#x2F;feature requests at <a href="https://github.com/jekyll/jekyll">Jekyll’s GitHub repo</a>.</p>]]></content:encoded>
      
      
      
      
      <comments>https://johnpauljanecek.work/blog/functions-create-metaclass/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Creating and configuring digitalocean droplets with ipython notebooks.</title>
      <link>https://johnpauljanecek.work/blog/creating-and-configuring-digitalocean-servers-with-ipython/</link>
      <guid>https://johnpauljanecek.work/blog/creating-and-configuring-digitalocean-servers-with-ipython/</guid>
      <pubDate>Thu, 23 Jul 2015 16:00:00 GMT</pubDate>
      
        
        
      <description>&lt;p&gt;I recently had an extremely large web scraping gig where I required 4 VPS at once. The client wanted to use &lt;a href=&quot;https://www.digitalo</description>
        
      
      
      
      <content:encoded><![CDATA[<p>I recently had an extremely large web scraping gig where I required 4 VPS at once. The client wanted to use <a href="https://www.digitalocean.com/?refcode=da3d5d4ab00c">digitalocean</a> since you pay for the VPS by the hour, instead of by the month. To make the job more difficult, as the job was progressing the client would specify changes. To make these changes I would need to ssh into each VPS and make a change. Also on digitalocean you pay for the VPS whether it is poweredup or off, but you do not pay for the storage of snapshots. Since the client wanted to scrape for only a few hours a day, it was in my best interest to be able to bring the VPS up, run my scrapers and then when finished power it off, and take a snapshot as quickly as possible. Time is money.</p><p>Once each VPS was up and running, controling each VPS was a breeze with <a href="https://rpyc.readthedocs.org/en/latest/">rpyc</a>, it was how to run shell commands on each VPS to set things up. In the rpyc documentation it mentions another module called <a href="http://plumbum.readthedocs.org/en/latest/">plumbum</a> which uses a python syntax to do shell commands. More importantly it will ssh into another machine and run them there. You can do ssh commands as shown here <a href="http://plumbum.readthedocs.org/en/latest/remote.html#remote-machines">plumbum remote machines</a></p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="number">1</span></span><br><span class="line"><span class="number">2</span><span class="keyword">from</span> plumbum <span class="keyword">import</span> SshMachine</span><br><span class="line">rem = SshMachine(<span class="string">&quot;hostname&quot;</span>, user = <span class="string">&quot;john&quot;</span>, keyfile = <span class="string">&quot;/path/to/idrsa&quot;</span>)</span><br></pre></td></tr></table></figure><p>Creating the actual droplet is simple since digitalocean has python binding to their api <a href="https://github.com/valerylisay/digitalocean-api">digitalocean-api</a>.But unfortunately when I attempted to ssh into one of my freshly created droplets it would not connect. The problem is I needed to add the knownhosts file. While I was researching this I found this webpage <a href="http://www.robotgoblin.co.uk/blog/2012/07/24/managing-multiple-ssh-keys/">Managing Multiple SSH Keys</a>. So I decided to make a python script which would generate the required files as described on the webpage. While I was using the script in ipython notebook, kept on getting confused which VPS I was logging into, what images where on the server etc. I happened to have some code kicking around which will dump a python dictionary into an HTML table and displays it in the ipython notebook. So I decided to use that to dump which droplets are active, what images are available etc. To convert the python object into a dictionary I just fed my function the <strong>dict</strong> property.</p><p>Basically I have 3 files:</p><ul><li>ipython_helpers.py - contains functions to display python dictionaries as tables. I just happened to have this kicking around. The file is on my gist here. <a href="https://gist.github.com/johnpauljanecek/a1c9f61f0609c330c213">ipython_helpers.py</a></li><li>secret.py - a file which needs to contain three variables.digitalOceanToken,IdRsaPub and idRsa. Set these as appropriate for your digitalocean account.</li><li>common.py - contains common functions, I need to refactor more. If I have to work on other IAAS frameworks besides digitalocean, I will refactor more. <a href="https://gist.github.com/johnpauljanecek/a91d45cf1ba6a03f5993">common.py</a>.</li><li>digitalocean_config.py - the file that I does everything I talked about. <a href="https://gist.github.com/johnpauljanecek/132bdb2ad4379be38b01">digitalocean_config.py</a></li><li>and ofcourse last but not least an ipython notebook which gives an example of it in operation.<a href="https://gist.github.com/johnpauljanecek/1252a4b0c626bbc62410">Ipython demo notebook</a></li></ul><h2 id="Summary"><a href="#Summary" class="headerlink" title="Summary"></a>Summary</h2><p>This is just a short quick post on how to make tools which save you time. Before running the code, make sure you backup your .ssh directory. Also it is good to keep old code lying around, the ipython_helpers.py was from another project.</p><p>Digitalocean also is great for testing new ideas. <a href="https://www.digitalocean.com/?refcode=da3d5d4ab00c">digitalocean</a>. So I wanted to start using mongodb, since it seemed to be similar to zodb, but I didn’t want the hassle of installing it on my system. So I just created a mongodb on digitalocean and within minutes I was able to test and try out mongodb.</p>]]></content:encoded>
      
      
      
      
      <comments>https://johnpauljanecek.work/blog/creating-and-configuring-digitalocean-servers-with-ipython/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Injecting XMLHttpRequests into python selenium</title>
      <link>https://johnpauljanecek.work/blog/Injecting-XMLHttpRequest-into-python-selenium/</link>
      <guid>https://johnpauljanecek.work/blog/Injecting-XMLHttpRequest-into-python-selenium/</guid>
      <pubDate>Tue, 23 Jun 2015 16:00:00 GMT</pubDate>
      
        
        
      <description>&lt;p&gt;When scraping websites using a headless browser, if it is possible to call the XMLHttpRequest call using &lt;a href=&quot;https://github.com/cryz</description>
        
      
      
      
      <content:encoded><![CDATA[<p>When scraping websites using a headless browser, if it is possible to call the XMLHttpRequest call using <a href="https://github.com/cryzed/Selenium-Requests">Selenium Requests</a> which is an extension of <a href="http://docs.python-requests.org/en/latest/">Selenium-Requests</a>. The Selenium Requests Library works by creating a small webserver, spawning another selenium window and copying all of the browser cookies. The solution is ingenious, and making calls with the requests library makes things a lot easier.</p><p>These are the possible pitfalls when using Selenium Requests</p><ul><li>When selenium requests spawns the extra selenium windows to get the cookies this takes time.</li><li>When doing repeated XMLHttpRequest calls, it does not seem to update the cookies, in certain cases it does not work.</li><li>On rare occasions it can crash the headless browser.</li></ul><p>Selenium requests is a great addon to to python selenium, and I use it frequently. It is in the cases when Selenium Requests does not work that I am talking about.</p><p>Recently a client asked me to scrape results from kickstarter. In this case he wanted all <a href="http://nbviewer.ipython.org/gist/johnpauljanecek/3446d11bed47b3b12b27">kickstarter projects which are card games in the USA</a>. I was able to locate the XMLHttpRequest, but is sets an anti-xss token on one of the headers. I located where the token is in the webpage and extracted it, but when I set the headers, the request would fail. But when I called the request from within firebug, it worked fine. Inclued in this post is a ipython notebook which explains the technique I used to solve the problem. <a href="http://nbviewer.ipython.org/gist/johnpauljanecek/3446d11bed47b3b12b27">IPython notebook demonstrating the technique</a></p><p>The important function in example is in SearchPage.doajaxresultsrequest with this piece of javascript code.</p><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="number">1</span></span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="number">5</span></span><br><span class="line"><span class="number">6</span></span><br><span class="line"><span class="number">7</span></span><br><span class="line"><span class="number">8</span></span><br><span class="line"><span class="number">9</span></span><br><span class="line"><span class="number">10</span></span><br><span class="line"><span class="number">11</span></span><br><span class="line"><span class="number">12</span></span><br><span class="line"><span class="number">13</span></span><br><span class="line"><span class="number">14</span></span><br><span class="line"><span class="number">15</span></span><br><span class="line"><span class="number">16</span></span><br><span class="line"><span class="number">17</span></span><br><span class="line">18<span class="keyword">var</span> url = <span class="variable language_">arguments</span>[<span class="number">0</span>];</span><br><span class="line"><span class="variable language_">window</span>.<span class="property">_jsonResult</span> = <span class="literal">null</span>;</span><br><span class="line"><span class="keyword">var</span> token = <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;meta[name = &quot;csrf-token&quot;]&#x27;</span>).<span class="title function_">getAttribute</span>(<span class="string">&quot;content&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> xmlhttp = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line"></span><br><span class="line">xmlhttp.<span class="property">onreadystatechange</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line"><span class="keyword">if</span> (xmlhttp.<span class="property">readyState</span> == <span class="number">4</span> &amp;&amp; xmlhttp.<span class="property">status</span> == <span class="number">200</span>) &#123;</span><br><span class="line">    <span class="variable language_">window</span>.<span class="property">_jsonResult</span> = jsonResult = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(xmlhttp.<span class="property">responseText</span>);</span><br><span class="line">    &#125;&#125;</span><br><span class="line"></span><br><span class="line">xmlhttp.<span class="title function_">open</span>(<span class="string">&quot;GET&quot;</span>, url, <span class="literal">true</span>);</span><br><span class="line">xmlhttp.<span class="title function_">setRequestHeader</span>(<span class="string">&quot;X-CSRF-Token&quot;</span>,token);</span><br><span class="line">xmlhttp.<span class="title function_">setRequestHeader</span>(<span class="string">&quot;X-Requested-With&quot;</span>,<span class="string">&quot;XMLHttpRequest&quot;</span>)</span><br><span class="line">xmlhttp.<span class="title function_">setRequestHeader</span>(<span class="string">&quot;Accept&quot;</span>,<span class="string">&quot;application/json, text/javascript, */*; q=0.01&quot;</span>)</span><br><span class="line">xmlhttp.<span class="title function_">send</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="literal">true</span>;;</span><br></pre></td></tr></table></figure><p>The url is pulled off the arguments array, the xss token is extracted from the document,and then the XMLHTTPRequest call is setup and called. I decided not to wait for the XMLHTTPRequest call to complete, but instead store the result in window._jsonResult.</p><p>A second call is then made with getajaxresult to return the result. In this case the XMLHttpRequest is parsed into json before it is stored, that means when the result is fetched by python there is no need to parse it with JSON.</p><p>The first example uses the browser class of my <a href="http://johnpauljanecek.github.io/controlling-docker-containers-with-python-rpyc/">docker_rpyc module</a> . The second example uses the worker class of my rpyc_docker module which means the browser is running totally headless and isolated within a docker container. Since my library uses rpyc the code is almost identical, and the same SearchPage class in the same namespace can be used. It is also possible to run multiple isolated headless browsers.</p><h1 id="Possible-improvements-on-the-technique"><a href="#Possible-improvements-on-the-technique" class="headerlink" title="Possible improvements on the technique."></a>Possible improvements on the technique.</h1><ul><li>Instead of making two calls to get the result, wait till the XMLHttpRequest finishes before returning, I am not really sure if this is an improvement.</li><li>Have the XMLHttpRequest call save the status of the request instead of just saving the result.</li><li>Have an array which stores XMLHttpRequests, and then repeatedly call the request function. Since javascript is able to do asycronous requests this would probably be a lot quicker for multiple XMLHttpRequests.</li><li>A similar technique can be used to hook HMLHttpRequests, and then intercepting the results.</li></ul><h1 id="Why-this-matters"><a href="#Why-this-matters" class="headerlink" title="Why this matters ?"></a>Why this matters ?</h1><p>In the past scraping web pages could be done with just curl and raw http requests. But websites have transformed from a series of static pages, into applications running inside a web browser. As a result new web scraping techniques need to be developed. From my experience the hybrid method of web scraping websites is highly effective. So a combination of raw http calls, running headless browsers and injecting javacripts.</p>]]></content:encoded>
      
      
      
      
      <comments>https://johnpauljanecek.work/blog/Injecting-XMLHttpRequest-into-python-selenium/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Controlling docker containers with python rpyc</title>
      <link>https://johnpauljanecek.work/blog/controlling-docker-containers-with-python-rpyc/</link>
      <guid>https://johnpauljanecek.work/blog/controlling-docker-containers-with-python-rpyc/</guid>
      <pubDate>Wed, 03 Jun 2015 16:00:00 GMT</pubDate>
      
        
        
      <description>&lt;p&gt;In the post I am going to talk about controlling docker container with the python module rpyc. The main reason you will want to do this i</description>
        
      
      
      
      <content:encoded><![CDATA[<p>In the post I am going to talk about controlling docker container with the python module rpyc. The main reason you will want to do this is to control multiple processes each running in an isolated virtual machine. I will then introduce the module I created rpyc_docker which makes it simpler to control multiple instances of docker. I use rpyc_docker primarily to run headless browsers, that way I can control multiple instances of a browser, each brower being a difference version if I desire. With some websites there is a problem with the browser freezing or crashing. When each browser runs in its own docker container this is not a problem, if the browser freezes or crashes it is isolated from the rest of your browser grid.</p><h2 id="What-is-docker"><a href="#What-is-docker" class="headerlink" title="What is docker ?"></a>What is docker ?</h2><p>Docker is built on top of <a href="http://man7.org/linux/man-pages/man7/namespaces.7.html">linux namespaces</a>, which are similar to bsd jails. Linux namespaces allow processes to be isolated in the linux kernel, each process with its own environment. Initially I attempted to use linux namespaces directly to isolate my processes, this is extremely complicated since each namespace requires its own file system and network to be configured.</p><p>Fortunately I discovered docker so I did not need to reinvent the wheel. Docker allows you to create extremely light wieght processes, each one running in its own customized linux environment. So your server could be running linux 14.04 but inside your docker container you could be running the latest version of redhat. It is best to check out the <a href="https://www.docker.com/whatisdocker/">docker website</a> to see what all of the fuss is. With Docker it is extremely simple to customize new virtual machines and the processes inside them run with no extra overhead.</p><h2 id="What-is-rpyc-python"><a href="#What-is-rpyc-python" class="headerlink" title="What is rpyc python ?"></a>What is rpyc python ?</h2><p>Rpyc solves the problem on how to access python objects transparently inside a running docker container. The docker container is a running virtual machine, rpyc acts as a bridge to get around the isolation problem.</p><p>Rpyc is a remote procedure call library similar to <a href="https://pypi.python.org/pypi/Pyro4">pyro</a> or <a href="http://twistedmatrix.com/documents/current/core/howto/pb-usage.html">twisted spread</a>. All three libraries allow you to perform rpc calls on python objects, and all three libraries are great libraries. Rpyc is designed for controlling machines which you own, and it is symetric. Which twisted spread and pyro are more designed for a client to server type model. In these two libraries it is assumed that you do not control the client, and possibly the client might be hostile.</p><p>Rpyc when running in classic mode makes the remote object appear as if it is locally on your machine. If you are unfamiliar with rpyc and classic mode read <a href="https://rpyc.readthedocs.org/en/latest/tutorial/tut1.html">Introduction to Classic RPyC</a>. With the remote object you can do things like monkey patching, if the object crashes you can get a remote traceback or even enter into a remote debugging session. This makes development a lot easier.</p><p>Rpyc also comes with other utilities like the ability to upload or download files to your remote machine.</p><h2 id="Introducting-Rpyc-docker"><a href="#Introducting-Rpyc-docker" class="headerlink" title="Introducting Rpyc_docker"></a>Introducting Rpyc_docker</h2><p>Rpyc_docker is a python library which runs an rpyc server inside a docker container. There are instructions on how to setup and use rpyc_docker and rudimentary api documentation here which I am still working on <a href="https://johnpauljanecek.github.io/rpyc_docker/">Rpyc_docker</a> and there is a <a href="https://github.com/johnpauljanecek/rpyc_docker">github repository</a>.</p><p>Rpyc_docker works well with the <a href="http://selenium-python.readthedocs.org/en/latest/page-objects.html">page object</a> design pattern of testing and craping websites. For development purposes it is best to design with the browser visible and not running in a container. Later you can run multiple headless browsers each in its own docker container isolated and seperated.</p>]]></content:encoded>
      
      
      
      
      <comments>https://johnpauljanecek.work/blog/controlling-docker-containers-with-python-rpyc/#disqus_thread</comments>
      
    </item>
    
    <item>
      <title>Injecting javascript into python selenium to increase scraping speed</title>
      <link>https://johnpauljanecek.work/blog/using-javascript-with-python-selenium/</link>
      <guid>https://johnpauljanecek.work/blog/using-javascript-with-python-selenium/</guid>
      <pubDate>Sun, 31 May 2015 16:00:00 GMT</pubDate>
      
        
        
      <description>&lt;p&gt;When python selenium communicates with the webbrowser it sends its requests through a bridge. For locating a single element in a page and</description>
        
      
      
      
      <content:encoded><![CDATA[<p>When python selenium communicates with the webbrowser it sends its requests through a bridge. For locating a single element in a page and getting its data or clicking on it, this will not be much of a problem. But if you are scrapping a 100+ results from a page this can take a long delay. Sometimes upto several seconds.</p><p>The solution is to parse the data that is needed inside the browser using javascript, and then to pass the results back to python selenium using the selenium function <a href="http://selenium-python.readthedocs.org/en/latest/api.html?highlight=execute_script#selenium.webdriver.remote.webdriver.WebDriver.execute_script">execute_script</a></p><p>The function execute_script if passed arguments will attempt to convert them from python to javascript, when returning the arguments the reverse will happen.</p><p>Here is an example where two arguments are passed to the function from python.</p><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="number">1</span></span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="number">5</span></span><br><span class="line"><span class="number">6</span></span><br><span class="line"><span class="number">7</span></span><br><span class="line"><span class="number">8</span>#driver is a webdriver instance</span><br><span class="line"></span><br><span class="line">js_function = <span class="string">&quot;&quot;</span><span class="string">&quot;</span></span><br><span class="line"><span class="string">return (function(a,b) &#123;</span></span><br><span class="line"><span class="string">return a + b;</span></span><br><span class="line"><span class="string">&#125;)(arguments[0],arguments[1]);</span></span><br><span class="line"><span class="string">&quot;</span><span class="string">&quot;&quot;</span></span><br><span class="line">driver.<span class="title function_">execute_script</span>(js_function,<span class="number">1</span>,<span class="number">2</span>)</span><br></pre></td></tr></table></figure><p>The example I have used is scrapping the results from duckduckgo. I created a simple example here in an ipython notebook here <a href="http://nbviewer.ipython.org/gist/johnpauljanecek/39c1ab450f3d188af548">Inject javascript into python selenium</a>.</p><p>The class DuckDuckGoResults takes a driver as an argument. Here is a brief description of the member functions.</p><ul><li>search(self,searchTerm) - takes a search term and inputs it into duckduckgo, should return when the search page results are there.</li><li>scroll_botton(self) - utility function to scroll the page to the bottom. Used to load all the results from duckduckgo.</li><li>load_all_results(self) - keeps on scrolling the page down until all of the results have been loaded.</li><li>parse_resultElm(self,resultElm) - utility function for parsing a result div. Extracts the title,href and description from the div and returns it as dict.</li><li>def get_results_python(self) - returns all of the results of the page as an array of dicts. This function is written using python. This function is extremely slow.</li><li>def get_results_javascript(self): same as get_results_python except it uses javascript this function returns the results almost instantly.</li></ul><p>The get_results_javascript function is an example of extracting results using javascript inside the browser and then passing them back to python selenium. Here is the javascript part of the function.</p><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="number">1</span></span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line"><span class="number">4</span></span><br><span class="line"><span class="number">5</span></span><br><span class="line"><span class="number">6</span></span><br><span class="line"><span class="number">7</span></span><br><span class="line"><span class="number">8</span></span><br><span class="line">9<span class="keyword">var</span> resultElms = <span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">slice</span>.<span class="title function_">call</span>(<span class="variable language_">document</span>.<span class="title function_">querySelectorAll</span>(<span class="string">&quot;#links&gt;div.results_links_deep&quot;</span>));</span><br><span class="line"><span class="keyword">return</span> resultElms.<span class="title function_">map</span>(<span class="keyword">function</span>(<span class="params">resultElm</span>) &#123;</span><br><span class="line">    <span class="keyword">var</span> result = [];</span><br><span class="line">    <span class="keyword">var</span> resultAElm = resultElm.<span class="title function_">querySelector</span>(<span class="string">&quot;a.result__a&quot;</span>);</span><br><span class="line">    result.<span class="title function_">push</span>([<span class="string">&quot;title&quot;</span>,resultAElm.<span class="property">textContent</span>]);</span><br><span class="line">    result.<span class="title function_">push</span>([<span class="string">&quot;href&quot;</span>,resultAElm.<span class="title function_">getAttribute</span>(<span class="string">&quot;href&quot;</span>)]);</span><br><span class="line">    result.<span class="title function_">push</span>([<span class="string">&quot;snippet&quot;</span>,resultElm.<span class="title function_">querySelector</span>(<span class="string">&quot;div.result__snippet&quot;</span>).<span class="property">textContent</span>]);</span><br><span class="line">    <span class="keyword">return</span> result;</span><br><span class="line">    &#125;);</span><br></pre></td></tr></table></figure><p>There is one problem when returning dicts from javascript. Javascript dicts and objects are the same data type. An object returning from javascript into python will not convert properly. Otherwise there is no problem returning all basing datatypes including arrays. The solution is to return the dictionary structure as an array of arrays like I have done. So each item in the array will be [[“title”,”XXXXX”],[“href”,”XXXXX”],[snippet,”XXXX]]. Once the structure has been returned to python convert it into a dict like this.</p><figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="number">1</span></span><br><span class="line">2results = <span class="variable language_">self</span>.driver.execute_script(jsFunction)</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">map</span>(<span class="built_in">dict</span>,results)</span><br></pre></td></tr></table></figure><p>The map function applies dict to each member to convert it into an array of dicts so the output is the same as the python function.</p><p>For most of my web scrapping I use the firebug extension to assist me. Within firebug run the javascript code, and you can test it inside firebug.</p><p>This is an introduction to running javascript code from selenium. The big advantage is speed, and that javascript was designed to manipulate DOM structures.</p>]]></content:encoded>
      
      
      
      
      <comments>https://johnpauljanecek.work/blog/using-javascript-with-python-selenium/#disqus_thread</comments>
      
    </item>
    
  </channel>
</rss>
