Снятие заголовков с домашних страниц новостного сайта с использованием BeautifulSoup в Python - PullRequest
0 голосов
/ 07 марта 2019

Я пытаюсь извлечь заголовки с главной страницы нескольких новостных сайтов, используя BeautifulSoup.Я изучаю Python, но не очень разбираюсь в HTML, CSS в Javascript, поэтому использую метод проб и ошибок, используя Inspect on Chrome.Вот код, который я написал для этого на веб-странице New York Times:

import requests from bs4
import BeautifulSoup


url = "https://www.nytimes.com/"
r = requests.get(url)
r_html = r.text
soup = BeautifulSoup(r_html, features="html.parser")
headlines = soup.find_all(class_="css-1vynn0q esl82me3")

for item in headlines:
    if len(item.contents) == 1:
        print(item.text)
    elif len(item.contents) == 2:
        print(item.contents[1].text)

Вот мои вопросы:

  1. Как я планирую сделать этодля нескольких новостных сайтов, есть ли лучшее решение, чем этот подход, который вы можете предложить?

  2. Я заметил, что тег CSS был изменен с тех пор, как я написал этот код, из-за чего япришлось обновить его.Есть ли какое-либо решение, которое не потребует от меня изменения кода при каждом обновлении тегов?

1 Ответ

0 голосов
/ 07 марта 2019

Это возможно, так как вы можете найти теги <script> в html, а затем проанализировать их как формат json.Он может не работать конкретно с каждым новостным веб-сайтом, так как, скорее всего, будут разные теги / коды для идентификации тегов заголовков, но вы можете иметь общий рабочий код для извлечения этих заголовков, даже если они обновляются позже.

Разберите html как обычно:

import requests 
from bs4 import BeautifulSoup
import json

url = "https://www.nytimes.com/"
r = requests.get(url)
r_html = r.text
soup = BeautifulSoup(r_html, "html.parser")

Затем найдите все теги <script>.Тот, который нам нужен, начинается с текста window.__preloadedData =, поэтому мы просто хотим найти его из 14 найденных элементов с помощью тега <script>:

scripts = soup.find_all('script')
for script in scripts:
    if 'preloadedData' in script.text:
        jsonStr = script.text

После того, как он его найдет,мы будем хранить его как jsonStr, а затем начнем обрезать начальную и конечную части строки, чтобы преобразовать его в чистый формат json, который затем можно загрузить с помощью json.loads(), и сохранить его как наш jsonObj:

    jsonStr = jsonStr.split('=', 1)[1].strip()
    jsonStr = jsonStr.rsplit(';', 1)[0]
    jsonObj = json.loads(jsonStr)

Как только мы получим jsonObj, мы проведем итерацию по ключу: значениям внутри структуры, чтобы найти значения, связанные с ключом headline в объекте json:

for ele, v in jsonObj['initialState'].items():
    try:
        if v['headline']:
            print(v['headline'])
    except:
        continue

Полный код:

Я также добавил элемент даты и времени, так как вы можете сохранить его, чтобы увидеть, какие заголовки были в определенные даты / время, когда он обновляется позже.

import requests 
from bs4 import BeautifulSoup
import json
import datetime



url = "https://www.nytimes.com/"
r = requests.get(url)
now = datetime.datetime.now()
now = now.strftime('%A, %B %d, %Y  %I:%M %p')

r_html = r.text
soup = BeautifulSoup(r_html, "html.parser")

scripts = soup.find_all('script')
for script in scripts:
    if 'preloadedData' in script.text:
        jsonStr = script.text
        jsonStr = jsonStr.split('=', 1)[1].strip()
        jsonStr = jsonStr.rsplit(';', 1)[0]
        jsonObj = json.loads(jsonStr)


print ('%s\nHeadlines\n%s\n' %(url, now))
count = 1
for ele, v in jsonObj['initialState'].items():
    try:
        if v['headline'] and v['__typename'] == 'PromotionalProperties':
            print('Headline %s: %s' %(count, v['headline']))
            count += 1
    except:
        continue

Вывод:

https://www.nytimes.com/
Headlines
Thursday, March 07, 2019  11:50 AM

Headline 1: The Trade Deficit Set a New Record. For Trump, That’s a Failure.
Headline 2: Rules Relaxed for Banks, Giving Wall Street a Big Win
Headline 3: Biden’s Candidacy Plan is Almost Complete. Democrats Are Impatient.
Headline 4: Why Did Four Top Democrats Just Say No to 2020?
Headline 5: Why Birthrates Among Hispanic Americans Have Plummeted
Headline 6: The Top 25 Songs That Matter Right Now
Headline 7: Cohen Says Papers Prove His Lies Were Aided by Trump Lawyers
Headline 8: Paul Manafort to Be Sentenced Thursday in 1 of 2 Cases Against Him
Headline 9: Trump’s Lawyer Says Several Have Sought Presidential Pardons
Headline 10: Senator Says She Was Raped in the Military, Describing a Broken System
Headline 11: Your Thursday Briefing
Headline 12: Listen to ‘The Daily’
Headline 13: Listen: ‘Modern Love’ Podcast
Headline 14: In the ‘DealBook’ Newsletter
Headline 15: What if the Mueller Report Demands Bold Action?
Headline 16: Ilhan Omar Knows Exactly What She Is Doing
Headline 17: How to Think About Taxing and Spending Like a Swede
Headline 18: Even Google Can No Longer Hide Its Gender Pay Gap
Headline 19: Questions For and About Jared Kushner
Headline 20: The Big Race: It’s Time for a Rhyme
Headline 21: Listen to ‘The Argument’: How Does the Catholic Church Redeem Itself?
Headline 22: We Will Survive. Probably.
Headline 23: A Peace Plan for India and Pakistan Already Exists
Headline 24: Ilhan Omar, Aipac and Me
Headline 25: The India-Pakistan Conflict Was a Parade of Lies
Headline 26: Seven Buds for Seven Brothers
Headline 27: This Tech Makes D.I.Y. Key Duplication Easy. Maybe Too Easy.
Headline 28: 36 Hours in St. Augustine
...