2013-06-07 4 views
1

Когда выскабливание этот Afghanistan page, я получил сообщение об ошибке сказав:как сказать, если фильтр() возвращает новый список

Traceback (most recent call last):                                             
    File "extract_table.py", line 23, in <module>                                          
    li = dict(chunks([i.text for i in all_td], 2))                                         
ValueError: dictionary update sequence element #28 has length 1; 2 is required 

Но когда выскабливание Argentina page, код работает нормально.

Есть ли способ, как сказать, что если all_td вернул новый список? Я хотел бы знать, какие функции в python использовать.

что-то вроде этого псевдокода:

if all_td is new list, 
    execute dict(chunks([i.text for i in all_td], 2)) 
else 
    execute dict(chunks([i.text for i in areatable.findAll('td')], 2)) 

То, что я хочу сделать, это запустить код для обеих стран Афганистана и Аргентины.

Это мой код

from bs4 import BeautifulSoup                                              
import urllib2                                                  
import re                                                   

url = "http://www.howtocallabroad.com/afghanistan" # argentina works fine 
html_page = urllib2.urlopen(url) 
soup = BeautifulSoup(html_page) 

areatable = soup.find('table',{'id':'codes'}) 
if areatable is None: 
    print "areatable is None" 
else: 
    d = {} 

    def chunks(l, n): 
      return [l[i : i + n] for i in range(0, len(l), n)] 


    all_td = areatable.findAll('td') 
    all_td = filter(lambda x: x.attrs == {}, all_td) 
    print ">>>>> all_td=", all_td 

    li = dict(chunks([i.text for i in all_td], 2)) 
    print ">>>>> li=", li 

ответ

1

Строго говоря, filter не возвращает список не является источником ваших проблем (помимо того, что это может быть отфильтровывать элементы, которые вы не хотите быть отфильтрован), но ошибка в вашей функции chunks. Конструктор dict принимает итерабельность итераций длина 2. Ваша функция chunks не всегда возвращает пары (если в списке есть нечетное количество элементов).


Пример:

In [1]: def chunks(l, n): 
    ...:  return [l[i : i + n] for i in range(0, len(l), n)] 

In [2]: a = chunks(range(4), 2) # even number of elements 

In [3]: b = chunks(range(5), 2) # odd number of elements 

In [4]: a 
Out[4]: [[0, 1], [2, 3]] 

In [5]: b 
Out[5]: [[0, 1], [2, 3], [4]] # <-- note the trailing [4] at position 2 

In [6]: dict(b) 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-6-57f7c289a3e5> in <module>() 
----> 1 dict(b) 

ValueError: dictionary update sequence element #2 has length 1; 2 is required 
2

Ваш фильтр устраняет эти 3 имена, потому что .attrs != {}

<tr> 
     <td width="25%">Badghis</td> 
     <td>41</td> 
     <td width="25%">Kabul</td> 
     <td>20</td> 
     <td width="25%">Panjshar</td> 
     <td>28</td> 
    </tr> 

Вот почему вы получаете нечетное число, чтобы кусок на пары. И результат будет искажать числа для несвязанных имен, даже если у него будет четное число.

Аргентина отлично работает, потому что у них нет дополнительных атрибутов ширины.

Это боль, потому что теперь вы знаете, что они не просто заполняют эти таблицы из шаблона, как любой здравомыслящий человек. Кто-то - это ругательство, по крайней мере, некоторых из них.

При попытке проанализировать эти типы страниц вам придется более защищать код.

+0

+1, для погружения в источник html. – root

Смежные вопросы