#python #html #web-scraping #beautifulsoup
#python #HTML #очистка веб-страниц #beautifulsoup
Вопрос:
Я хочу использовать Beautiful Soup для очистки страницы обновлений новостей Fujitsu: https://www.fujitsu.com/uk/news/pr/2020 /
Я хочу извлечь информацию только под заголовками текущего месяца и предыдущего месяца.
Для определенного месяца (например, ноября) я пытаюсь извлечь в список
- заголовок
- URL-адрес
- текст
для каждого новостного брифинга (таким образом, список списков).
Моя попытка пока выглядит следующим образом (для простоты показан только предыдущий месяц):
today = datetime.datetime.today()
year_str = str(today.year)
current_m = today.month
previous_m = current_m - 1
current_m_str = calendar.month_name[current_m]
previous_m_str = calendar.month_name[previous_m]
URL = 'https://www.fujitsu.com/uk/news/pr/' year_str '/'
resp = requests.get(URL)
soup = BeautifulSoup(resp.text, 'lxml')
previous_m_body = soup.find('h3', text=previous_m_str)
if previous_m_body is not None:
for sib in previous_m_body.find_next_siblings():
if sib.name == "h3":
break
else:
previous_m_text = str(sib.text)
print(previous_m_text)
Однако при этом генерируется одна длинная строка с новыми строками и без разделения между заголовком, текстом, url:
Fujitsu подписывает крупный контракт с правительством Шотландии на поставку решения для электронного подсчета голосов на выборах Лондон, Великобритания, 30 ноября 2020 г. — Fujitsu, ведущая компания по цифровым преобразованиям, сегодня объявила о крупном контракте с правительством Шотландии и местным населением Шотландии…
Fujitsu представляет ультракомпактное реле на печатной плате на 50 А для средне- и тяжеловесных автомобильных нагрузок Хофддорп, EMEA, 11 ноября 2020 г. — Fujitsu Components Europe расширила ассортимент автомобильных реле, добавив новое реле на печатной плате 12 В постоянного тока…….
Ответ №1:
Попробуйте это:
import requests
from bs4 import BeautifulSoup
html = requests.get("https://www.fujitsu.com/uk/news/pr/2020/").text
all_lists = BeautifulSoup(html, "html.parser").find_all("ul", class_="filterlist")
news = []
for unordered_list in all_lists:
for list_item in unordered_list.find_all("li"):
news.append(
[
list_item.find("a").getText(),
f"https://www.fujitsu.com{list_item.find('a')['href']}",
list_item.getText(strip=True)[len(list_item.find("a").getText()):],
]
)
for news_item in news:
print("n".join(news_item))
print("-" * 80)
Вывод (сокращенный для краткости):
Fujitsu signs major contract with Scottish Government to deliver election e-Counting solution
https://www.fujitsu.com/uk/news/pr/2020/fs-20201130.html
London, United Kingdom, November 30, 2020- Fujitsu, a leading digital transformation company, has today announced a major contract with the Scottish Government and Scottish Local Authorities to support the electronic counting (e-Counting) of ballot papers at the Scottish Local Government elections in May 2022.Fujitsu Introduces Ultra-Compact, 50A PCB Relay for Medium-to-Heavy Automotive LoadsHoofddorp, EMEA, November 11, 2020- Fujitsu Components Europe has expanded its automotive relay offering with a new 12VDC PCB relay featuring a switching capacity of 50A at 14VDC. The FBR53-HC offers a higher contact rating than its 40A FBR53-HW counterpart, yet occupies the same 12.1 x 15.5 x 13.7mm footprint and weighs the same 6g.
--------------------------------------------------------------------------------
and more ...
Редактировать:
Чтобы получить только последние два месяца, все, что вам нужно, это первые два ul
элемента из soup
. Итак, добавьте [:2]
к первому for loop
, вот так:
for unordered_list in all_lists[:2]:
# the rest of the loop body goes here
Комментарии:
1. Привет — большое спасибо за ответ. Похоже, это работает, но только для первой новости в каждом месяце (вплоть до января 2020 года) Как я могу изменить это, чтобы извлечь все новости за текущий и предыдущий месяц?
2. Я думаю, это потому, что, хотя «суп» содержит 10 элементов ul (10 разных месяцев), каждый из них содержит 1 или более новостных элементов, но цикл for извлекает только первый экземпляр ‘a’, href и сводный текст?
Ответ №2:
здесь я изменил ваш код. Я объединил ваш код bs4 с selenium. Selenium очень эффективен для создания динамического веб-сайта или веб-сайта на основе JavaScript. Вы можете использовать selenium с BeautifulSoup, чтобы упростить себе жизнь. Теперь он выдаст вам выходные данные за все месяцы.
from selenium import webdriver
from bs4 import BeautifulSoup
driver = webdriver.Firefox()
driver.maximize_window()
url = "https://www.fujitsu.com/uk/news/pr/2020/" #change the url if you want to get result for different year
driver.get(url)
# now your bs4 code start. It will give you output from current month to previous all month
soup = BeautifulSoup(driver.page_source, "html.parser")
#here I am getting all month name from January to november.
months = soup.find_all('h3')
for month in months:
month = month.text
print(f"month_name : {month}n")
#here we are getting all description text from current month to all previous months
description_texts = soup.find_all('ul',class_='filterlist')
for description_text in description_texts:
description_texts = description_text.text.replace('n','')
print(f"description_text: {description_texts}")
Комментарии:
1. Использование
selenium
в этом случае — просто перебор.