Поиск правильных элементов для очистки сайта - PullRequest
1 голос
/ 16 января 2020

Я пытаюсь почистить только некоторые статьи с этой главной страницы. Чтобы быть более точным c, я пытаюсь почистить только статьи из подстраниц и из подстраниц Пресс-релизы ; Решения Совета управляющих ; Пресс-конференции ; Счета денежно-кредитной политики ; Выступления ; Интервью , а также только те, которые есть на английском языке sh.

Мне удалось (основываясь на некоторых уроках и других SE: ответы о переполнении) собрать код, который полностью удаляет все с веб-сайта, потому что моей первоначальной идеей было очистить все, а затем в фрейме данных просто очистить вывод позже, но сайт включает в себя так много, что он всегда зависает через некоторое время.

Получение под-ссылок:

import requests
import re
from bs4 import BeautifulSoup
master_request = requests.get("https://www.ecb.europa.eu/")
base_url = "https://www.ecb.europa.eu"
master_soup = BeautifulSoup(master_request.content, 'html.parser')
master_atags = master_soup.find_all("a", href=True)
master_links = [ ] 
sub_links = {}
for master_atag in master_atags:
    master_href = master_atag.get('href')
    master_href = base_url + master_href
    print(master_href)
    master_links.append(master_href)
    sub_request = requests.get(master_href)
    sub_soup = BeautifulSoup(sub_request.content, 'html.parser')
    sub_atags = sub_soup.find_all("a", href=True)
    sub_links[master_href] = []
    for sub_atag in sub_atags:
        sub_href = sub_atag.get('href')
        sub_links[master_href].append(sub_href)
        print("\t"+sub_href)

Я пытался изменить базовую ссылку на под-ссылки - моя идея состояла в том, что, возможно, я могу просто сделать это отдельно для каждой подстраницы и позже просто соединить ссылки, но это не сработало). Другие вещи, которые я пробовал, состояли в том, чтобы заменить 17-ю строку следующим:

sub_atags = sub_soup.find_all("a",{'class': ['doc-title']}, herf=True)

это, казалось, частично решило мою проблему, потому что, хотя оно не получало только ссылки с подстраниц, оно по крайней мере игнорировало ссылки это не 'do c -title', это все ссылки с текстом на сайте, но это было все еще слишком много, и некоторые ссылки не были получены правильно.

Я пытался также попробовать следующее:

for master_atag in master_atags:
    master_href = master_atag.get('href')
    for href in master_href:
        master_href = [base_url + master_href if str(master_href).find(".en") in master_herf
    print(master_href)

Я думал, что, поскольку все hrefs с документами Engli sh имеют где-то в них .en, это даст мне все ссылки, где .en происходит где-то в href, но этот код дает мне синтаксическую ошибку для печати (master_href), которую я не понимаю, потому что ранее print (master_href) работала.

Далее я хочу извлечь следующую информацию из подссылок. Эта часть кода работает, когда я тестирую ее для одной ссылки, но у меня никогда не было возможности попробовать ее в приведенном выше коде, так как она не работает до конца. Будет ли это работать, как только мне удастся получить правильный список всех ссылок?

for links in sublinks:
    resp = requests.get(sublinks)
    soup = BeautifulSoup(resp.content, 'html5lib')
    article = soup.find('article')
    title = soup.find('title')
    textdate = soup.find('h2')
    paragraphs = article.find_all('p')
    matches = re.findall('(\d{2}[\/ ](\d{2}|January|Jan|February|Feb|March|Mar|April|Apr|May|May|June|Jun|July|Jul|August|Aug|September|Sep|October|Oct|November|Nov|December|Dec)[\/ ]\d{2,4})', str(textdate))
        for match in matches:
        print(match[0])
        datadate = match[0]
import pandas as pd
ecbdf = pd.DataFrame({"Article": [Article]; "Title": [title]: "Text": [paragraphs], "date": datadate})

Также возвращаясь к соскобу, так как первый подход с красивым супом не работал для меня, я также попытался просто подойти к проблеме по-другому. На веб-сайте есть RSS-каналы, поэтому я хотел использовать следующий код:

import feedparser
from pandas.io.json import json_normalize
import pandas as pd
import requests
rss_url='https://www.ecb.europa.eu/home/html/rss.en.html'
ecb_feed = feedparser.parse(rss_url) 
df_ecb_feed=json_normalize(ecb_feed.entries)
df_ecb_fead.head()

Здесь я столкнулся с проблемой невозможности найти URL-адрес RSS-канала. Я попробовал следующее: я просмотрел исходную страницу и попытался найти «RSS» и перепробовал все URL, которые мог найти таким образом, но я всегда получаю пустой фрейм данных.

Я новичок в изучении веб-страниц, и на данный момент я не знаю, как поступить или как решить эту проблему. В конце концов, я хочу сделать 1046 * просто собрать все статьи с подстраниц с их названиями, датами и авторами и поместить их в один фрейм данных.

1 Ответ

2 голосов
/ 17 января 2020

Самой большой проблемой, с которой вы сталкиваетесь при очистке этого сайта, является, вероятно, ленивая загрузка: используя JavaScript, они загружают статьи с нескольких страниц html и объединяют их в список. За подробностями обращайте внимание на index_include в исходном коде. Это проблематично c для очистки только с запросами и BeautifulSoup, потому что то, что ваш экземпляр супа получает из содержимого запроса, является просто базовым c каркасом без списка статей. Теперь у вас есть две опции:

  1. Вместо основной страницы списка статей (пресс-релизы, интервью и т. Д. c.) Используйте загруженные ленивыми списки статей, например, /press/pr/date/2019/html/index_include.en.html. Возможно, это будет более простой вариант, но вы должны делать это для каждого интересующего вас года.
  2. Используйте клиент, который может выполнять JavaScript, как Selenium, для получения HTML вместо запросов.

Кроме того, я бы предложил использовать селекторы CSS для извлечения информации из кода HTML. Таким образом, вам нужно всего несколько строк для статьи. Кроме того, я не думаю, что вам придется фильтровать статьи Engli sh, если вы используете страницу index.en.html для очистки, потому что она показывает Engli sh по умолчанию и - дополнительно - другие языки, если они доступны.

Вот пример, который я быстро собрал, его, безусловно, можно оптимизировать, но он показывает, как загрузить страницу с помощью Selenium и извлечь URL-адреса и содержание статьи:

from bs4 import BeautifulSoup
from selenium import webdriver

base_url = 'https://www.ecb.europa.eu'
urls = [
    f'{base_url}/press/pr/html/index.en.html',
    f'{base_url}/press/govcdec/html/index.en.html'
]
driver = webdriver.Chrome()

for url in urls:
    driver.get(url)
    soup = BeautifulSoup(driver.page_source, 'html.parser')

    for anchor in soup.select('span.doc-title > a[href]'):
        driver.get(f'{base_url}{anchor["href"]}')
        article_soup = BeautifulSoup(driver.page_source, 'html.parser')

        title = article_soup.select_one('h1.ecb-pressContentTitle').text
        date = article_soup.select_one('p.ecb-publicationDate').text
        paragraphs = article_soup.select('div.ecb-pressContent > article > p:not([class])')
        content = '\n\n'.join(p.text for p in paragraphs)

        print(f'title: {title}')
        print(f'date: {date}')
        print(f'content: {content[0:80]}...')

Я получаю следующий вывод для страница пресс-релизов:

title: ECB appoints Petra Senkovic as Director General Secretariat and Pedro Gustavo Teixeira as Director General Secretariat to the Supervisory Board                         
date: 20 December 2019                                    
content: The European Central Bank (ECB) today announced the appointments of Petra Senkov...

title: Monetary policy decisions                          
date: 12 December 2019                                    
content: At today’s meeting the Governing Council of the European Central Bank (ECB) deci...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...