Найти - Пользователи
Полная версия: Как при парсинге указать парсить именно span (без класса) внутри div'a с классом
Начало » Python для новичков » Как при парсинге указать парсить именно span (без класса) внутри div'a с классом
1
JD724
Добрый день!
Необходимо парсить содержимое span (без класса) внутри div'a с классом ‘free_seats’ . Где-то видел, что можно поставить символ показывающий дочернее отношение. Но найти самостоятельно не получается, все примеры span'oв с классами. Если указать просто span, то он берет его первый по счету, а это не мой!

Приведу часть кода:
for item in items:
comps.append({
‘title’: item.find('a').get_text(strip = True),
‘mesta’: item.find('div', class_ = ‘free_seats’ что тут указать? ‘span’).get_text(strip = True)
})
JD724
Проверил на другом сайте с .find_next. Все отлично работает (правда со ‘strong’)! НО на сайте на котором мне нужно парсить в этом месте стоит скрипт. При загрузки страницы он отсылает запрос и выдает количество свободных мест чуть позже.. видимо парсер успевает пробежать до того как страница полностью загрузится.. Нужно как то проверять загрузилась ли страница полностью..
Работает вот так:
'mesta': item.find('div', class_ = ‘events__free-places’).find_next('strong').get_text(strip = True)
xam1816
покажи какой сайт и что нужно спарсить
и на будущее
[code python]между этими тегами вставлять код[/code]
JD724
xam1816
покажи какой сайт и что нужно спарситьи на будущее
Сайт: https://russdramteatr.ru/index.php/ru/afisha
Нужно название спектакля и количество свободных мест. Вот с количеством как раз у меня проблема. За подсказу с выставлением кода отдельное спасибо!
py.user.next
JD724
количество свободных мест
Из этого куска можно id получить
  
<div class="free_seats">Свободных мест: <span id="free_seats_96449ed3-92bc-4e2b-9796-a2a2e381fc32"></span></div>

Дальше посылается POST-запрос с передачей этого id и в ответ приходит JSON-документ
  
[guest@localhost py]$ curl -X POST --data 'id=96449ed3-92bc-4e2b-9796-a2a2e381fc32' "https://russdramteatr.ru/mesta/query.php"
{"seatsFree":34}[guest@localhost py]$ 

JD724
Вот с количеством как раз у меня проблема.
Там количества свободных мест и нет изначально. Они догружаются через JavaScript-код с помощью XMLHttpRequest-запроса.

Так что тут надо получить id из страницы и посылать дополнительный запрос с указанием этого id, чтобы получить данные по местам для спектакля с этим id.

Думаю, xam1816 справится.
JD724
Точно!! Огромное спасибо! Мысль собирать id летала рядом, но для чего я так и не увидел! И если вытащить id и разложить я возможно еще смогу. Но вот написать POST запрос правильно в Python пока нет. Буду копать, т.к. с питоном только неделю примерно..! Еще раз спасибо за разъяснения!
xam1816
если сильно не заморачиваться
  
import re
import csv
 
import requests
from bs4 import BeautifulSoup
URL = 'https://russdramteatr.ru/index.php/ru/afisha'
def get_html(url):
    resp = requests.get(url)
    if resp.status_code == 200:
        return resp.content.decode()
 
def get_num_free_seats(id):
    r = requests.post('https://russdramteatr.ru/mesta/query.php', data={'id': id})
    if r.status_code == 200 and r.headers['Content-type'] == 'application/json':
        num = r.json()['seatsFree']
        return num
 
def get_data_from_item(item):
    data = dict.fromkeys(['название', 'свободных мест'])
    search_head = item.find('h2')
    if search_head:
        data['название'] = search_head.text
    search_addr = item.find('address')
    search_title = search_addr.findPreviousSibling('p')
    if search_title:
        data['название'] += f'\n{search_title.text}'
    search = item.find('span', id=re.compile('free_seats_'))
    id = search['id'].replace('free_seats_', '') if search else None
    if id:
        data['свободных мест'] = get_num_free_seats(id)
    return data
 
def parse():
    out = []
    print('загрузка страницы')
    html = get_html(URL)
    soup = BeautifulSoup(html, 'html.parser')
    items = soup.find_all('div', class_=re.compile('items-row cols-\d+ row-\d+'))
    if items:
        print('загрузка данных')
        for i in items:
            data = get_data_from_item(i)
            out.append(data)
        print('.............done..................')
    return out
 
def main():
    res = parse()
    with open('parse_data.csv', 'w') as f:
        fieldnames = ['название', 'свободных мест']
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(res)
    print(res)
 
if __name__ == '__main__':
    main()

только загрузка мест долго идет, можно попробовать асинхронно
JD724
Работает! Огромное спасибо!!! Постепенно подчерпываю для себя что-то новое!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB