title: Extending CSS selectors in BeautifulSoup
body: <p><strong>The Question:</strong></p>
  
  <p><code>BeautifulSoup</code> provides a <em>very limited support for <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#css-selectors">CSS selectors</a></em>. For instance, the only supported pseudo-class is <code>nth-of-type</code> and it can only accept numerical values - arguments like <code>even</code> or <code>odd</code> are not allowed.</p>
  
  <p>Is it possible to extend <code>BeautifulSoup</code> CSS selectors or let it use <a href="http://lxml.de/cssselect.html"><code>lxml.cssselect</code></a> internally as an underlying CSS selection mechanism?</p>
  
  <hr>
  
  <p>Let's take a look at an <strong>example problem/use case</strong>. Locate only even rows in the following HTML:</p>
  
  <pre><code>&lt;table&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
      &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;4&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/table&gt;
  </code></pre>
  
  <p>In <code>lxml.html</code> and <code>lxml.cssselect</code>, it is easy to do via <code>:nth-of-type(even)</code>:</p>
  
  <pre><code>from lxml.html import fromstring
  from lxml.cssselect import CSSSelector
  
  tree = fromstring(data)
  
  sel = CSSSelector('tr:nth-of-type(even)')
  
  print [e.text_content().strip() for e in sel(tree)]
  </code></pre>
  
  <p>But, in <code>BeautifulSoup</code>:</p>
  
  <pre><code>print(soup.select("tr:nth-of-type(even)"))
  </code></pre>
  
  <p>would throw an error:</p>
  
  <blockquote>
    <p>NotImplementedError: Only numeric values are currently supported for the nth-of-type pseudo-class.</p>
  </blockquote>
  
  <hr>
  
  <p>Note that we can workaround it with <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#find-all"><code>.find_all()</code></a>:</p>
  
  <pre><code>print([row.get_text(strip=True) for index, row in enumerate(soup.find_all("tr"), start=1) if index % 2 == 0])
  </code></pre>