Я использую bs4 для извлечения ссылок из бегущей строки. Я могу получить данные бегущей строки, которые возвращаются как элемент bs4 resultSet. Однако я не могу получить доступ к href внутри данных. Я уверен, что что-то упускаю, так как я новичок в веб-скрейпинге, и ценю любые советы, которые есть у кого-либо.
Примечание. Я могу легко получить ссылки с драйвером селена и хрома, но это занимает вечность.
Это возвращает все данные выделения:
url = 'https://drugs.globalincidentmap.com/'
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
marquee = soup.select('div', class_='h-48')
print(marquee)
Однако, когда я пытаюсь углубиться в данные, я получаю пустой список или NoneType/KeyError или AttributeError.
for a in marquee.find_all('a', href=True):
link = a.find('div', class_=':nth-child')
или
for a in marquee.find_all('a', href=True):
link = a.find('div', class_='flex p-2')
Ссылки в шатре






Я могу легко получить ссылки с драйвером селена и хрома.
Вероятно, потому что класс div with h-48 загружается с помощью JavaScript; даже если бы это было не так, я не думаю, что soup.find('div', class_='h-48') сработает, потому что у этого элемента больше классов , и вам нужно передать их все как class_ [и я не думаю soap.select('div ', class_='h-48') дает точные результаты, которые вы ожидаете - select на самом деле не должен иметь class_ аргумент - просто CSS-селектор строка].
soup.find('div', attrs = {'class':'h-48'}) or soup.select('div.h-48') can be expected to work on the html that is formed after JS loading, but you need selenium to get that...
К счастью, я думаю, что нужные вам данные уже есть в извлеченном html, просто в другом формате — вы можете извлечь список словарей (mqCont) с помощью
# import json
marq = soup.find('marquee', attrs = {'class':'h-48'})
if marq is None: print('Could Not Find marquee.h-48')
if not marq.get(':contents'): print('marquee.h-48 has no [:contents] attr')
try: mqCont = json.loads(marq.get(':contents', '[]'))
except Exception as e:
mqCont = []
print('failed to parse marquee.h-48[:contents] <---', e)
или, короче (если вы уверены, что не будет ошибок для отладки/разбивки):
mqCont = json.loads(soup.select_one('marquee.h-48').get(':contents', '[]'))
Вы можете получить список ссылок на новостные статьи с помощью [m['url'] for m in mqCont if 'url' in m], но, поскольку вы пытались получить find с помощью class_='flex p-2', вам, вероятно, нужны ссылки .../event_detail?id=.... Вы можете сформировать их, как показано ниже
evtUrls = [f"{url.strip('/')}/event_detail?id = {m['id']}" for m in mqCont if 'id' in m]
Вы также можете просмотреть список словарей в виде таблицы [с пандами], выполнив что-то вроде:
# import pandas
omitKeys = ['domain_event_types', 'country']
for i, m in enumerate(mqCont):
mDesc = ' '.join(w for w in BeautifulSoup(
m['description'] if 'description' in m else ''
).get_text().split() if w)
if mDesc: m['description'] = mDesc
if 'id' in m: m['eventUrl'] = f"{url.strip('/')}/event_detail?id = {m['id']}"
mqCont[i] = {k:v for k, v in m.items() if k not in omitKeys}
mqcDF = pandas.DataFrame(mqCont).dropna(axis='columns', how='all').set_index('id')
и первые 5 рядов [всего 100 рядов] mqcDF:
Markdown for the above table was printed with print(mqcDf.loc[mqcDf.index[:5]].to_markdown())
Вау, это потрясающе. Большое спасибо за подробное объяснение. Похоже, я просто застрял на доступе к ':contents'. Я очень ценю это.
@facepet рад, что смог помочь! (Это очень необычный атрибут....)
что
print(marquee)печатает для вас? я ничего не получаю