Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 29, 2022 00:23:11

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9716
Репутация: +  842  -
Профиль   Отправить e-mail  

пытаюсь парсить. помогите с методом .decompose()

123ksn
Просто мне потребовалось получить в удобном виде информацию и теперь могу получать все вакансии за последние сутки (около 45стр*20~900).
Не, там надо сначала написать склеиватель страниц. А он у тебя есть? Ты, наверное, не в курсе, но при добавлении вакансий они все сдвигаются вправо, и вакансии с четвёртой страницы плавно переходят на пятую, переселяются так незаметно, а бывает, если долго не взаимодействуешь с сайтом, не на пятую, а уже на десятую или там двадцатую. А твой скрипт-то это знает? Нет. Он думает, что все страницы различаются и вакансии там уникальны. Только в результате будет куча копий и ты будешь думать “а что за хрень? почему столько одинаковых вакансий? а как их убрать?” и всё. Закончится всё тем, что надо будет думать, как их по-новому разбирать, потому что этот вариант не подходит. Это называется “подводные камни” - понятие такое.

123ksn
Уважаемый xam1816! Мне было проще понять и доработать решение от Gdez под себя чем Ваше. Возможно, предложенное Вами решение более академическое что ли, но , как всегда злосчастное “НО”, Вы не предложили решение, которое нужно было мне.
Слушай, он тоже не зря код свой написал. По крайней мере, вот он его выложил, и я могу его прочитать и сказать ему, что у него return'ы у функций сделаны неправильно, потому что в питоне для этого надо использовать исключения, когда ошибки происходят, а всю допольнительную информацию про ошибки вкладывать внутрь этих исключений, потому что исключения - это объекты, у которых можно внутри что-то хранить. Ну, ты наследуешься от ValueError, например, и в подклассе этом своём просто добавляешь поле, к которому ты будешь прикреплять дополнительную информацию и методы для работы с этим полем. Если уж нужно что-то замороченное, то оно делается вот так. А потом ты просто вместо return делаешь raise MyException('error string', data=errordatadict) , а перехватывается оно потом где-нибудь наверху, где прикручен лог в удобном месте, который не мешает нигде и не замусоривает всю программу своими инструкциями повсюду. То есть, выкладывая свой код, xam1816 может получить обратную связь на него, критику разную, конструктивные замечания и узнать что-то новое для себя. Так что даже то, что этот его код тебе не помог, не мешает этому коду принести пользу автору кода по-другому как-то, каким-то другим путём.

123ksn
Просто несколько человек откликнулись на мою проблему и я в порыве восторга высказался об одном из них очень чувственно.
Вот я посмотрю, что ты будешь говорить, когда тебе надо будет вдруг поправить этот код от Gdez'а. Ты что сделаешь? Ты пойдёшь к нему, скажешь ему “слушай, а как поправить твой код?” и тот тебе скажет “ой, ну я не знаю, я вот только эту версию смог написать, а другую не могу просто, знаний не хватает”. Или же у тебя возникнет новая похожая задача и ты пойдёшь к нему, потому что сам ты не научился, и он не сможет тебе её решить. Так ты будешь сидеть с нерешённой задачей, потому что сам ты не умеешь, а у предыдущего решателя, который раньше успешно решал, на этой задаче мозги сломались, потому что он какую-то тему ещё не изучал.

И ты придёшь опять к нам. Понимаешь?

Вот зная это всё наперёд, я и написал тебе первое сообщение, в котором “почему-то” и предложил тебе научиться самому это всё делать и дал расклад, как такие задачи делаются, чтобы ты пальцем в небо не играл в угадайку.



Отредактировано py.user.next (Ноя. 29, 2022 00:24:30)

Офлайн

#2 Ноя. 29, 2022 00:24:53

xam1816
Зарегистрирован: 2020-05-11
Сообщения: 1308
Репутация: +  112  -
Профиль   Отправить e-mail  

пытаюсь парсить. помогите с методом .decompose()

123ksn
Как видите, большого ума не потребовалось.

  
import requests, re
from bs4 import BeautifulSoup
region, time_work, full_partial_load, experience, education = re.findall('(?<=\t)[^\t\n]+', BeautifulSoup(requests.get('https://praca.by/vacancy/499310/').content.decode(), 'html.parser').find('div', class_='vacancy-required').text)
print('\n'.join([region, time_work, full_partial_load, experience, education]))

Отредактировано xam1816 (Ноя. 29, 2022 00:25:38)

Офлайн

#3 Ноя. 29, 2022 20:47:27

123ksn
Зарегистрирован: 2022-11-26
Сообщения: 11
Репутация: +  0  -
Профиль   Отправить e-mail  

пытаюсь парсить. помогите с методом .decompose()

py.user.next
Вот я посмотрю, что ты будешь говорить, когда тебе надо будет вдруг поправить этот код от Gdez'а. Ты что сделаешь? Ты пойдёшь к нему, скажешь ему “слушай, а как поправить твой код?” и тот тебе скажет “ой, ну я не знаю, я вот только эту версию смог написать, а другую не могу просто, знаний не хватает”. Или же у тебя возникнет новая похожая задача и ты пойдёшь к нему, потому что сам ты не научился, и он не сможет тебе её решить
py.user.next, не опускайте себя ниже плинтуса! Вы говорите нехорошее о человеке у него “за спиной”, зная, что он Вам не ответит.
Если мне будет надо, то корона не свалится, и я попрошу помощи и у Gdez'а и у xam1816 и у любого, кроме, пожалуй, Вас. И опять же не потому, что корона пошатнется, просто теперь я точно знаю, что получу много умных слов, но не то, что нужно мне. А если не получу, тогда зачем спрашивать?

py.user.next
Не, там надо сначала написать склеиватель страниц. А он у тебя есть? Ты, наверное, не в курсе, но при добавлении вакансий они все сдвигаются вправо, и вакансии с четвёртой страницы плавно переходят на пятую, переселяются так незаметно, а бывает, если долго не взаимодействуешь с сайтом, не на пятую, а уже на десятую или там двадцатую. А твой скрипт-то это знает? Нет. Он думает, что все страницы различаются и вакансии там уникальны. Только в результате будет куча копий и ты будешь думать “а что за хрень? почему столько одинаковых вакансий? а как их убрать?” и всё.
Ну Вы прямо фантазер. Исходник своего парсера я выложил у Вас на сайте в соседней ветке.
https://python.su/forum/topic/42225/?page=1#post-225291
Думаю в исходнике Вы сможете найти ответы на все свои предположения.

xam1816
import requests, re
from bs4 import BeautifulSoup
region, time_work, full_partial_load, experience, education = re.findall('(?<=\t)+', BeautifulSoup(requests.get('https://praca.by/vacancy/499310/').content.decode(), ‘html.parser’).find('div', class_='vacancy-required').text)
print('\n'.join())
xam1816, вот где Вы раньше были такой умный, когда я просил? А теперь на ум приходит две пословицы: 1. Ложка дорога к обеду. 2.После драки кулаками не машут.
Да и простите Вы меня в конце-то концов!

Офлайн

#4 Ноя. 29, 2022 20:56:19

xam1816
Зарегистрирован: 2020-05-11
Сообщения: 1308
Репутация: +  112  -
Профиль   Отправить e-mail  

пытаюсь парсить. помогите с методом .decompose()

py.user.next
А потом ты просто вместо return делаешь raise MyException('error string', data=errordatadict) , а перехватывается оно потом где-нибудь наверху, где прикручен лог в удобном месте, который не мешает нигде и не замусоривает всю программу своими инструкциями повсюду.
  
import requests
from bs4 import BeautifulSoup
import re
import logging
 
logging.basicConfig(filename='example.log', filemode='w')
vacancy_ids = ['490695', '499310qw', '488145']
URL = 'https://praca.by/vacancy/'
 
def get_html(url):
    resp = requests.get(url)
    if resp.status_code == 200:
        return resp.content.decode('utf-8')
    else:
        raise Exception(f'{resp}')
 
def get_data_from_html(html):
    soup = BeautifulSoup(html, 'lxml')
    search = soup.find('div', class_='vacancy-required')
    if search:
        return re.findall('(?<=\t)[^\t\n]+', search.text)
    else:
        raise Exception(f"soup.find('div', class_='vacancy-required')\nsearch = {search}")
 
def main():
    count_errors = 0
    for id in vacancy_ids:
        current_url = f'{URL}{id}/'
        try:
            html = get_html(current_url)
            data = get_data_from_html(html)
            print(data)
        except Exception as e:
            logging.error(f'{current_url}, {e}')
            count_errors += 1
        if count_errors > 10: # на случай если много ошибок остановить скрипт
            break
    print('errors: ', count_errors)
 
if __name__ == '__main__':
    main()

один id спецально неправильный в лог кинет исключение,
ERROR:root:https://praca.by/vacancy/499310qw/, <Response [404]>

Отредактировано xam1816 (Ноя. 29, 2022 20:59:27)

Офлайн

#5 Ноя. 29, 2022 22:42:36

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 9716
Репутация: +  842  -
Профиль   Отправить e-mail  

пытаюсь парсить. помогите с методом .decompose()

xam1816
  
raise Exception(f'{resp}')
Не, надо сделать своё исключение сначала. Через наследование это делается. А потом передавать и осмысленное сообщение в нём, и данные, которые нужны дополнительно, чтобы что-то там дополнительно дописывать по ним.

Зачем нужно своё исключение?
Своё исключение делается дл того, чтобы не перепутать какое-нибудь системное исключение с исключением, произошедшим в скрипте. Ошибки по работе скрипта должны писаться в лог, системные же ошибки должны в консоль выпадать (они обрабатываются другими средствами, находящимися в операционной системе). Вот для их дифференцирования нужно для скрипта делать свои скриптовые исключения.

Зачем нужно передавать осмысленное сообщение в исключении?
Со скриптом будет работать человек, который не знает ни разработчика скрипта, ни то, как этот вообще скрипт написан и работает, который не знает языка Python вообще, который не знает какие модули в скрипте используются и в каких местах, и который скрипт вообще не может прочитать, потому что этот скрипт где-нибудь на сервере находится, а человек его только запускает удалённо, а чтение этого файла ему запрещено администратором сервера. Но при этом этот человек, пользователь скрипта, должен знать, что происходит в процессе его работы с этим скриптом, то ли он что-то не то сделал, то ли там просто что-то сломалось и там соединения с сервером нет и он просто недоступен. И вот для этого существует лог, который он прочитает и поймёт, что он неправильно сделал и докуда этот скрипт доработал.

Зачем нужны данные дополнительные в исключении?
Логирование имеет несколько уровней подробностей. Если ты запустил что-то просто без опций, то логироваться тебе будут только сообщения о том, что произошло; но если ты запустил скрипт с опцией -v, то логироваться будут и сообщения о том, что произошло, и после этих сообщений ещё подробности будут логироваться о том, как это произошло. И у этих подробностей тоже есть несколько уровней детализации. Если запустить скрипт с опцией -v будет первый уровень детализации, а если запустить скрипт с двумя опциями -v в виде -vv, то это будет второй уровень детализации, при котором подробностей в логе будет ещё больше. Но так как подробности до самого дна нужны редко когда, то чтобы лог не разрастался до гигабайтов, эти подробности выведены в опцию, которая включается только тогда, когда человек не может понять, в чём ошибка, и у него ремонт идёт, во время которого этот человек может запускать скрипт с разными опциями, чтобы выяснить, в чём корень проблемы. И это происходит только во время ремонта, а не всегда.

xam1816
ERROR:root:https://praca.by/vacancy/499310qw/, <Response [404]>
Ты думаешь, что через пять лет ты вспомнишь, что это значит? Нет! Через пять лет ты не сможешь вспомнить код, который ты сам же и писал. А уж тем более ты не сможешь вспомнить, что эти логовые сообщения означают и где они там вообще порождаются и в связи с чем. Бывает и несколько скачиваний разных страниц в одном скрипте, и несколько разных разборов этих страниц, которые похожи все друг на друга. Но самое главное, что ты даже если читать будешь скрипт, ничего не будешь помнить о нём; связано это с тем, что ты пишешь тысячи кодов за это прошедшее время и они друг друга в памяти мозга забивают, накладываются друг на друга, смешиваются. Поэтому сообщения в логе должны быть осмысленными, потому что ты самому себе их пишешь как незнакомому с кодом человеку, который будет читать это не сегодня, а через многие годы.

А вообще, затирание памяти происходит даже не за годы, а ещё быстрее. Это всё зависит от того, сколько ты софта пишешь. Если ты пишешь много, то ты даже неделю назад не помнишь уже.


tags: exception



Отредактировано py.user.next (Ноя. 29, 2022 22:57:17)

Офлайн

#6 Ноя. 30, 2022 16:34:30

123ksn
Зарегистрирован: 2022-11-26
Сообщения: 11
Репутация: +  0  -
Профиль   Отправить e-mail  

пытаюсь парсить. помогите с методом .decompose()


xam1816
один id спецально неправильный в лог кинет исключение,
xam1816, вот Вы предложили некую программу. Пообсуждали её с py.user.next. А нельзя ли для меня открыть тайну сего произведения? Прокомментировать “хитрые” строки можете? Поскольку код в моей ветке по парсеру, не могли бы Вы указать в какое место моего парсера я могу/должен вставить сей код?

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version