Ошибка при извлечении текста с веб-сайта: у объекта AttributeError 'NoneType' нет атрибута 'get_text' - PullRequest
0 голосов
/ 12 мая 2018

Я очищаю этот веб-сайт и получаю "заголовок" и "категорию" в виде текста, используя .get_text().strip().

У меня проблема с использованием того же подхода для извлечения "автора" из текста.

data2 = {
    'url' : [],
    'title' : [],
    'category': [],
    'author': [],
} 

url_pattern = "https://www.nature.com/nature/articles?searchType=journalSearch&sort=PubDate&year=2018&page={}"
count_min = 1
count_max = 3

while count_min <= count_max: 
    print (count_min)
    url = url_pattern.format(count_min)
    r = requests.get(url)
    try: 
        soup = BeautifulSoup(r.content, 'lxml')
        for links in soup.find_all('article'):
            data2['url'].append(links.a.attrs['href']) 
            data2['title'].append(links.h3.get_text().strip())
            data2["category"].append(links.span.get_text().strip()) 
            data2["author"].append(links.find('span', {"itemprop": "name"}).get_text().strip()) #??????

    except Exception as exc:
        print(exc.__class__.__name__, exc)

    time.sleep(0.1)
    count_min = count_min + 1

print ("Fertig.")
df = pd.DataFrame( data2 )
df

df предполагается напечатать таблицу с "автором", "категорией", "заголовком", "URL".Исключение печати дает мне следующую подсказку: AttributeError 'NoneType' object has no attribute 'get_text'.Но вместо таблицы я получаю следующее сообщение:

ValueError                                Traceback (most recent call last)
<ipython-input-34-9bfb92af1135> in <module>()
     29 
     30 print ("Fertig.")
---> 31 df = pd.DataFrame( data2 )
     32 df

~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in __init__(self, data, index, columns, dtype, copy)
    328                                  dtype=dtype, copy=copy)
    329         elif isinstance(data, dict):
--> 330             mgr = self._init_dict(data, index, columns, dtype=dtype)
    331         elif isinstance(data, ma.MaskedArray):
    332             import numpy.ma.mrecords as mrecords

~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in _init_dict(self, data, index, columns, dtype)
    459             arrays = [data[k] for k in keys]
    460 
--> 461         return _arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype)
    462 
    463     def _init_ndarray(self, values, index, columns, dtype=None, copy=False):

~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in _arrays_to_mgr(arrays, arr_names, index, columns, dtype)
   6161     # figure out the index, if necessary
   6162     if index is None:
-> 6163         index = extract_index(arrays)
   6164     else:
   6165         index = _ensure_index(index)

~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in extract_index(data)
   6209             lengths = list(set(raw_lengths))
   6210             if len(lengths) > 1:
-> 6211                 raise ValueError('arrays must all be same length')
   6212 
   6213             if have_dicts:

ValueError: arrays must all be same length 

Как я могу улучшить свой код для извлечения имен "автора"?

Ответы [ 2 ]

0 голосов
/ 12 мая 2018

Вместо использования метода полос. Создайте переменную со всеми элементами, а затем используйте цикл for и используйте .text

author = links.findAll('span', {"itemprop": "name"})
for i in author:
    data2["author"].append(i.text) #??????

печать

'author': ['Mark Zastrow', 'Barbara Mühlemann', 'Terry C. Jones', 'Peter de Barros Damgaard', 'Morten E. Allentoft', 'Irina Shevnina', 'Andrey Logvin', 'Emma Usmanova', ......

0 голосов
/ 12 мая 2018

Вы очень близки - есть пара вещей, которые я рекомендую. Во-первых, я бы рекомендовал поближе взглянуть на HTML - в этом случае имена авторов на самом деле указаны в ul, где каждый li содержит span, где itemprop равно 'name'. Однако не во всех статьях вообще есть имена авторов. В этом случае с вашим текущим кодом вызов links.find('div', {'itemprop': 'name'}) возвращает None. None, конечно, не имеет атрибута get_text. Это означает, что строка выдаст ошибку, которая в этом случае просто не приведет к добавлению значения в список data2 'author'. Я бы порекомендовал хранить авторов в списке примерно так:

authors = []
ul = links.find('ul', itemprop='creator')
for author in ul.find_all('span', itemprop='name'):
    authors.append(author.text.strip())
data2['authors'].append(authors)

Это обрабатывает случай, когда нет авторов, как мы могли бы ожидать, поскольку «авторы» являются пустым списком.

Как примечание, поместите ваш код в

try:
    ...
except:
    pass

конструкция обычно считается плохой практикой, именно по той причине, которую вы сейчас видите. Бесшумное игнорирование ошибок может привести к тому, что ваша программа будет работать правильно, в то время как на самом деле любое количество вещей может работать неправильно. По крайней мере, редко выводить информацию об ошибках на stdout. Даже делать что-то подобное лучше, чем ничего:

try:
    ...
except Exception as exc:
    print(exc.__class__.__name__, exc)

Однако для отладки часто желательно иметь полный возврат. Для этого вы можете использовать модуль traceback.

import traceback
try:
    ...
except:
    traceback.print_exc()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...