Первая проблема заключается в том, что вы используете обработку исключений для покемонов , вы действительно не хотите перехватывать их все .
Поймать определенные исключения, только или, по крайней мере, только перехват Exception
и убедитесь, что повторно подняли asyncio.CancelledError
(вы не хотите блокировать отмены задач), а также зарегистрируйте или распечатайте возникшие исключения, чтобы вы могли выполнить дальнейшую очисткуваш обработчик.В качестве быстрого исправления я заменил ваши try:... except: continue
блоки на:
try:
# ...
except asyncio.CancelledError:
raise
except Exception:
traceback.print_exc()
continue
и добавил import traceback
вверху.Когда вы затем запускаете свой код, вы видите, почему ваш код дает сбой:
Traceback (most recent call last):
File "test.py", line 43, in crawlAlbum
await self.crawlImgs(album_url)
File "test.py", line 51, in crawlImgs
self.end_album_num = await self.getAlbumTotalNum(album_url)
File "test.py", line 72, in getAlbumTotalNum
total_num = int(bsop.find('div', {'class': 'nav-links'}).findAll('a', {'class': 'page-numbers'})[-2].text)
AttributeError: 'NoneType' object has no attribute 'findAll'
Либо изменился способ, которым сайт размечал ссылки, либо сайт использует Javascript для изменения DOM в браузере после загрузки HTML,В любом случае, использование общего предложения except:
без регистрации ошибки скрывает такие проблемы от вас и затрудняет отладку.
Я бы, по крайней мере, добавил бы некоторые записи, чтобы записать, какой URL пытался коданализируйте, когда возникают исключения, поэтому вы можете повторить проблему в интерактивной, не асинхронной настройке и попробовать разные подходы для анализа страниц.
Вместо использования вызовов .find()
и .findAll()
используйте CSS селектор найти правильные элементы:
links = bsop.select(f'div.pagenavi a[href^="{album_url}"] span')
return 1 if len(links) < 3 else int(links[-2].string)
Вышеупомянутый URL использует текущий URL-адрес для ограничения поиска конкретными span
элементами с родительским элементом a
, которые имеют href
атрибут, значение которого, по крайней мере, начинается с URL текущей страницы.
Обратите внимание, что вышеизложенное не единственная проблема, однако, когда эта проблема исправлена, следующим исключением является
Traceback (most recent call last):
File "test.py", line 59, in crawlImgs
img_url = bsop.find('div', {'class': 'main-image'}).find('img').attrs['src']
AttributeError: 'NoneType' object has no attribute 'find'
This oneна самом деле вызвано неправильной обработкой URL для альбомов, при условии, что они всегда заканчиваются /
.Исправьте это:
async def crawlImgs(self, album_url):
end_album_num = await self.getAlbumTotalNum(album_url)
if album_url[-1] != '/':
album_url += '/'
for i in range(1, end_album_num + 1):
img_page_url = album_url + str(i)
# ...
Вы не хотите установить album_num
в качестве атрибута для self
однако!Состояние экземпляра класса является общим для задач, в то время как вы фактически не создаете несколько задач в своем коде (на данный момент это все одна последовательная задача), вы хотите избежать изменения общего состояния.