nodes: 0, module; 1, function_definition; 2, function_name:search; 3, parameters; 4, block; 5, identifier:self; 6, identifier:terms; 7, default_parameter; 8, default_parameter; 9, default_parameter; 10, default_parameter; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, expression_statement; 15, comment:# first, get the total number of pages returned. this findall returns; 16, comment:# two results (one from the top half of the page, one from the bottom),; 17, comment:# so only take the first element.; 18, expression_statement; 19, if_statement; 20, expression_statement; 21, expression_statement; 22, for_statement; 23, return_statement; 24, identifier:category; 25, attribute; 26, identifier:page; 27, integer:1; 28, identifier:sort_key; 29, attribute; 30, identifier:order_key; 31, attribute; 32, comment:"""Get a list of torrents that match the given search term
  
          :param terms: the `str` needle
          :param category: the desired :class:`Category` of the results
          :param page: the 1-based page to return the result
          :param sort_key: the :class:`SearchSortKey` of the results list
          :param order_key: the :class:`SearchOrderkey` of the results list
          :return: a :class:`SearchPage` of results
          """; 33, assignment; 34, assignment; 35, assignment; 36, assignment; 37, not_operator; 38, block; 39, else_clause; 40, assignment; 41, assignment; 42, identifier:row; 43, identifier:rows; 44, block; 45, call; 46, identifier:Category; 47, identifier:all_categories; 48, identifier:SearchSortKey; 49, identifier:date; 50, identifier:SearchOrderKey; 51, identifier:descending; 52, identifier:params; 53, dictionary; 54, identifier:r; 55, call; 56, identifier:content; 57, call; 58, identifier:a_to_last_page; 59, call; 60, identifier:a_to_last_page; 61, expression_statement; 62, block; 63, identifier:torrent_stubs; 64, list; 65, identifier:rows; 66, generator_expression; 67, expression_statement; 68, expression_statement; 69, expression_statement; 70, expression_statement; 71, expression_statement; 72, expression_statement; 73, if_statement; 74, if_statement; 75, expression_statement; 76, expression_statement; 77, expression_statement; 78, identifier:SearchResultPage; 79, argument_list; 80, pair; 81, pair; 82, pair; 83, pair; 84, pair; 85, attribute; 86, argument_list; 87, attribute; 88, argument_list; 89, attribute; 90, argument_list; 91, assignment; 92, expression_statement; 93, expression_statement; 94, expression_statement; 95, identifier:x; 96, for_in_clause; 97, if_clause; 98, assignment; 99, assignment; 100, assignment; 101, assignment; 102, assignment; 103, assignment; 104, call; 105, block; 106, else_clause; 107, call; 108, block; 109, else_clause; 110, assignment; 111, assignment; 112, call; 113, identifier:terms; 114, identifier:category; 115, identifier:sort_key; 116, identifier:order_key; 117, identifier:page; 118, identifier:total_pages; 119, identifier:torrent_stubs; 120, string; 121, string; 122, string; 123, identifier:terms; 124, string; 125, attribute; 126, string; 127, attribute; 128, string; 129, attribute; 130, identifier:requests; 131, identifier:get; 132, attribute; 133, keyword_argument; 134, identifier:self; 135, identifier:_get_page_content; 136, identifier:r; 137, identifier:content; 138, identifier:findall; 139, string:'.//div[@class="rightpages"]/a[2]'; 140, identifier:total_pages; 141, integer:1; 142, assignment; 143, assignment; 144, assignment; 145, identifier:x; 146, call; 147, comparison_operator:'tlistrow' in x.attrib.get('class', ''); 148, identifier:cell_td_elems; 149, call; 150, identifier:category_value; 151, subscript; 152, identifier:category; 153, call; 154, identifier:torrent_id; 155, subscript; 156, identifier:name; 157, attribute; 158, identifier:file_size; 159, attribute; 160, attribute; 161, argument_list; 162, expression_statement; 163, block; 164, attribute; 165, argument_list; 166, expression_statement; 167, block; 168, identifier:downloads; 169, call; 170, identifier:stub; 171, call; 172, attribute; 173, argument_list; 174, string_content:page; 175, string_content:search; 176, string_content:term; 177, string_content:cats; 178, identifier:category; 179, identifier:value; 180, string_content:sort; 181, identifier:sort_key; 182, identifier:value; 183, string_content:order; 184, identifier:order_key; 185, identifier:value; 186, identifier:self; 187, identifier:base_url; 188, identifier:params; 189, identifier:params; 190, identifier:last_page_url; 191, subscript; 192, identifier:offset; 193, subscript; 194, identifier:total_pages; 195, call; 196, attribute; 197, argument_list; 198, string; 199, call; 200, attribute; 201, argument_list; 202, call; 203, integer:0; 204, attribute; 205, argument_list; 206, call; 207, integer:0; 208, call; 209, identifier:text; 210, subscript; 211, identifier:text; 212, attribute; 213, identifier:isdigit; 214, assignment; 215, expression_statement; 216, attribute; 217, identifier:isdigit; 218, assignment; 219, expression_statement; 220, identifier:int; 221, argument_list; 222, identifier:TorrentStub; 223, argument_list; 224, identifier:torrent_stubs; 225, identifier:append; 226, identifier:stub; 227, attribute; 228, string; 229, call; 230, integer:0; 231, identifier:int; 232, argument_list; 233, identifier:content; 234, identifier:findall; 235, string; 236, string_content:tlistrow; 237, attribute; 238, argument_list; 239, identifier:row; 240, identifier:findall; 241, string; 242, identifier:extract_url_query_parameter; 243, argument_list; 244, identifier:Category; 245, identifier:lookup_category; 246, identifier:category_value; 247, identifier:extract_url_query_parameter; 248, argument_list; 249, attribute; 250, argument_list; 251, identifier:cell_td_elems; 252, integer:3; 253, subscript; 254, identifier:text; 255, identifier:seeders; 256, call; 257, assignment; 258, subscript; 259, identifier:text; 260, identifier:leechers; 261, call; 262, assignment; 263, attribute; 264, identifier:torrent_id; 265, identifier:name; 266, identifier:category; 267, identifier:seeders; 268, identifier:leechers; 269, identifier:file_size; 270, identifier:downloads; 271, subscript; 272, identifier:attrib; 273, string_content:href; 274, identifier:extract_url_query_parameter; 275, argument_list; 276, identifier:offset; 277, string_content:.//table//tr; 278, attribute; 279, identifier:get; 280, string; 281, string; 282, string_content:td; 283, subscript; 284, string; 285, subscript; 286, string:"tid"; 287, subscript; 288, identifier:find; 289, string; 290, identifier:cell_td_elems; 291, integer:4; 292, identifier:int; 293, argument_list; 294, identifier:seeders; 295, None; 296, identifier:cell_td_elems; 297, integer:5; 298, identifier:int; 299, argument_list; 300, identifier:leechers; 301, None; 302, subscript; 303, identifier:text; 304, identifier:a_to_last_page; 305, integer:0; 306, identifier:last_page_url; 307, string:"offset"; 308, identifier:x; 309, identifier:attrib; 310, string_content:class; 311, attribute; 312, string; 313, string_content:cats; 314, attribute; 315, string; 316, identifier:cell_td_elems; 317, integer:1; 318, string_content:a; 319, attribute; 320, attribute; 321, identifier:cell_td_elems; 322, integer:6; 323, call; 324, identifier:attrib; 325, string_content:href; 326, call; 327, identifier:attrib; 328, string_content:href; 329, subscript; 330, identifier:text; 331, subscript; 332, identifier:text; 333, attribute; 334, argument_list; 335, attribute; 336, argument_list; 337, identifier:cell_td_elems; 338, integer:4; 339, identifier:cell_td_elems; 340, integer:5; 341, subscript; 342, identifier:find; 343, string; 344, subscript; 345, identifier:find; 346, string; 347, identifier:cell_td_elems; 348, integer:0; 349, string_content:a; 350, identifier:cell_td_elems; 351, integer:1; 352, string_content:a
code: def search(self, terms, category=Category.all_categories, page=1,
                 sort_key=SearchSortKey.date,
                 order_key=SearchOrderKey.descending):
          """Get a list of torrents that match the given search term
  
          :param terms: the `str` needle
          :param category: the desired :class:`Category` of the results
          :param page: the 1-based page to return the result
          :param sort_key: the :class:`SearchSortKey` of the results list
          :param order_key: the :class:`SearchOrderkey` of the results list
          :return: a :class:`SearchPage` of results
          """
          params = {
              'page': 'search',
              'term': terms,
              'cats': category.value,
              'sort': sort_key.value,
              'order': order_key.value,
          }
          r = requests.get(self.base_url, params=params)
          content = self._get_page_content(r)
  
          # first, get the total number of pages returned. this findall returns
          # two results (one from the top half of the page, one from the bottom),
          # so only take the first element.
          a_to_last_page = content.findall('.//div[@class="rightpages"]/a[2]')
          if not a_to_last_page:
              total_pages = 1
          else:
              last_page_url = a_to_last_page[0].attrib['href']
              offset = extract_url_query_parameter(last_page_url, "offset")[0]
              total_pages = int(offset)
  
          torrent_stubs = []
          rows = (x for x in content.findall('.//table//tr')
                  if 'tlistrow' in x.attrib.get('class', ''))
          for row in rows:
              cell_td_elems = row.findall('td')
  
              category_value = extract_url_query_parameter(
                  cell_td_elems[0].find('a').attrib['href'],
                  'cats')[0]
              category = Category.lookup_category(category_value)
              torrent_id = extract_url_query_parameter(
                  cell_td_elems[1].find('a').attrib['href'],
                  "tid")[0]
              name = cell_td_elems[1].find('a').text
              file_size = cell_td_elems[3].text
              if cell_td_elems[4].text.isdigit():
                  seeders = int(cell_td_elems[4].text)
              else:
                  seeders = None
              if cell_td_elems[5].text.isdigit():
                  leechers = int(cell_td_elems[5].text)
              else:
                  leechers = None
              downloads = int(cell_td_elems[6].text)
  
              stub = TorrentStub(torrent_id, name, category, seeders, leechers,
                                 file_size, downloads)
              torrent_stubs.append(stub)
          return SearchResultPage(
              terms, category, sort_key, order_key, page, total_pages,
              torrent_stubs)