Оптимизация кода парсера
Я практикуюсь в написании парсеров. Пытаюсь написать как можно оптимальнее. Можно ли его как-нибудь оптимизировать?
Вот мой код, главная идея это собрать ссылки на изображения и тэги. С сайта reactor.cc.
Код рабочий, но мне кажется в плане оптимизации он ужасен, прошу посмотреть и сказать что можно изменить. У меня мысли насчет не практичности моего использования try. Говорят использовать это в цикле - табу, как goto в с++.
import logging
import requests
from bs4 import BeautifulSoup
def get_content():
tags = None
image = None
content = requests.get('http://joyreactor.cc/')
soup = BeautifulSoup(content.text, 'lxml')
posts = soup.find_all('div', class_='postContainer')
data = []
for post in posts:
try:
image = post.find('div', class_='image').find('img')['src']
tags = post.find('h2', class_='taglist').find_all('b')
except AttributeError:
print(post)
continue
except Exception as e:
logging.exception(e)
row = str(len(tags)).split()
for tag in tags:
tag = tag.find('a')['title']
row.append(tag)
row[0] = image
data.append(row)
print(data)
get_content()
Ответы (2 шт):
Автор решения: ganz
→ Ссылка
Как то так...
import logging
import requests
from bs4 import BeautifulSoup
def get_content():
#атавизм из строго типизированых яп?
tags = None
image = None
content = requests.get('http://joyreactor.cc/')
soup = BeautifulSoup(content.text, 'lxml')
#здесь можно удалить переменную content, на случай если вдруг когда либо нужно будет парсить ну прям очень много данных
del content
posts = soup.find_all('div', class_='postContainer')
data = []
for post in posts: #тут тоже можно удалять обработанные значения, но это уложнит понимание кода
#try тут нежелательно так как можно проверить наличие атрибута через if
try:
image = post.find('div', class_='image').find('img')['src']
tags = post.find('h2', class_='taglist').find_all('b')
except AttributeError:
print(post)
continue
except Exception as e: #а это выражение довольно часто вводит в заблуждение
logging.exception(e) #но хотябы логируются
row = str(len(tags)).split()
for tag in tags: #есть предположение что лямбда работала бы быстрее но выглядела бы хуже
tag = tag.find('a')['title']
row.append(tag)
row[0] = image
data.append(row)
print(row)
get_content()
Автор решения: Сергей Шашко
→ Ссылка
По коду
import logging
import requests
from bs4 import BeautifulSoup
def get_content():
tags = None
image = None
content = requests.get('http://joyreactor.cc/')
soup = BeautifulSoup(content.text, 'lxml')
posts = soup.find_all('div', class_='postContainer')
data = []
for post in posts:
try:
image = post.find('div', class_='image').find('img')['src']
tags=post.find('h2',class_='taglist').find_all('a')
'''
find_all('b') заменяем find_all('a')
в выбраном теге 'h2' остались все нам нужные теги 'a'
'''
except AttributeError:
print(post)
continue
except Exception as e:
logging.exception(e)
row = [image]
'''
row = str(len(tags)).split() Добротный костыль )) на пару row[0] = image
'''
for tag in tags:
'''
tag = tag.find('a')['title']
в теге 'a' остался текст в количестве одна штука извлекаем его tag.text
'''
row.append(tag.text)
'''
row[0] = image
коммент выше
'''
data.append(row)
print(data)
get_content()
Код сыроват:
- Не извлекает ссылки на gif-ки
- В не которых постах есть несколько картинок. Извлекается только одна ссылка на картинку.
Моя оптимизация Мутим генератор списка
tags =[tag.text for tag in post.find('h2', class_='taglist').find_all('a')]
print(tags)
['cosplay', 'Millenia69', 'Melisandre', 'ИП others', 'Игра престолов', 'фэндомы', 'ИП косплей', 'под катом еще']
Потребность в цикле for tag in tags отпадает
data.append(image,tags)
Правда на выходе формат чуть чуть другой. Ну и да ладно, я художник, я так вижу.))
P.S. "Я не волшебник, я только учусь" (х/ф"Золушка"(1947))