Это возможно, так как вы можете найти теги <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