BeautifulSoup - пытаетесь разобрать сайт, но не знаете, как разобрать скрипт json? - PullRequest
2 голосов
/ 19 марта 2019

В качестве веселого побочного проекта я пытался разобрать сайт на случайный факт дня. Я решил попробовать свои силы сегодня с BeautifulSoup4 и urllib3. Однако, к сожалению, я не уверен, как можно глубже погрузиться в элемент сценария, чем я уже получил.

Это мой текущий уровень производства:

{
"@context": "http://schema.org",
"@type": "Article",
"headline": "Fact of the Day: 51 Facts Of the Day for 3/19/2019 ←FACTSlides→",
"image": "https://www.FACTSlides.com/imgs/ishots/8224.png",
"author": "Luke Reiner",
"genre": "facts",
"publisher": {
    "@type": "Organization",
    "name": "FACTSlides",
    "logo": {
        "@type": "ImageObject",
        "url": "https:\/\/www.factslides.com\/imgs\/logo.png"
    }
},
"url": "https://www.factslides.com/s-Fact-Of-The-Day",
"mainEntityOfPage": "https://www.factslides.com/s-Fact-Of-The-Day",
"datePublished": "2019-03-19",
"dateCreated": "2019-03-19",
"dateModified": "2019-03-19",
"description": "Description.",
"articleBody": "Article clutter here."
}

Сами факты хранятся в articleBody и не разделены, я собирался использовать ». как разделитель, если я зашел так далеко.

Это код, который у меня есть:

""" Get a random fact. """
import argparse
import json
import urllib3
from bs4 import BeautifulSoup

PARAMETERS = {
    "u": ["url", "passes in a url.", "1"],
}

PARSER = argparse.ArgumentParser(
    description="Arguments to parse a url."
)

HTTP = urllib3.PoolManager()


def __load_args(parser, cfg_list):
    """ Loads the passed arguments. """
    for cfg_key in cfg_list:
        if len(cfg_list[cfg_key]) > 3:
            parser.add_argument(
                "-" + cfg_key,
                "--" + cfg_list[cfg_key][0],
                help=cfg_list[cfg_key][1],
                action=cfg_list[cfg_key][2],
                nargs=cfg_list[cfg_key][3],
            )
        else:
            parser.add_argument(
                "-" + cfg_key,
                "--" + cfg_list[cfg_key][0],
                default=None,
                help=cfg_list[cfg_key][1],
            )


def parse_args(parser, section_list=[]):
    """ Parses the loaded arguments. """
    for section in section_list:
        __load_args(parser, section)
    return parser.parse_args()


ARGS = parse_args(PARSER, [PARAMETERS])

RESPONSE = HTTP.request('GET', ARGS.url)

SOUP = BeautifulSoup(RESPONSE.data, features="html.parser")

SOUP_SCRIPT = SOUP.find_all("script")

JS_TEXT = SOUP.find('script', type='application/ld+json').text

print(JS_TEXT)

Любая помощь будет оценена.

ПРИМЕЧАНИЕ: URL, который я анализировал для фактов: здесь .

Ответы [ 2 ]

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

Я решил проблему с помощью @ chitown88 .

Вот код функции здесь:

""" Get a random fact. """
import argparse
import random
import json
from bs4 import BeautifulSoup
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

PARAMETERS = {
    "u": ["url", "passes in a url.", "1"],
}

PARSER = argparse.ArgumentParser(
    description="Arguments to parse a url."
)

HTTP = urllib3.PoolManager()


def __load_args(parser, cfg_list):
    """ Loads the passed arguments. """
    for cfg_key in cfg_list:
        if len(cfg_list[cfg_key]) > 3:
            parser.add_argument(
                "-" + cfg_key,
                "--" + cfg_list[cfg_key][0],
                help=cfg_list[cfg_key][1],
                action=cfg_list[cfg_key][2],
                nargs=cfg_list[cfg_key][3],
            )
        else:
            parser.add_argument(
                "-" + cfg_key,
                "--" + cfg_list[cfg_key][0],
                default=None,
                help=cfg_list[cfg_key][1],
            )


def parse_args(parser, section_list=[]):
    """ Parses the loaded arguments. """
    for section in section_list:
        __load_args(parser, section)
    return parser.parse_args()


ARGS = parse_args(PARSER, [PARAMETERS])

RESPONSE = HTTP.request('GET', ARGS.url)

SOUP = BeautifulSoup(RESPONSE.data, features="html.parser")

SOUP_SCRIPT = SOUP.find_all("script")

JS_TEXT = SOUP.find('script', type='application/ld+json').text

JSON_OBJ = json.loads(JS_TEXT)

LIST_TEST = []
# print(JSON_OBJ['articleBody'])
for item in JSON_OBJ['articleBody'].split('. '):
    LIST_TEST.append(item.strip())

print(random.choice(LIST_TEST) + ".")

Я хотел бы отметить, что мой разделитель не самый лучший, поскольку некоторые «факты» разбиты на два предложения.

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

Пока ваш json является текстом / строкой, вы можете использовать json.loads(), чтобы прочитать это в:

import json

JS_TEXT = '''{
"@context": "http://schema.org",
"@type": "Article",
"headline": "Fact of the Day: 51 Facts Of the Day for 3/19/2019 ←FACTSlides→",
"image": "https://www.FACTSlides.com/imgs/ishots/8224.png",
"author": "Luke Reiner",
"genre": "facts",
"publisher": {
    "@type": "Organization",
    "name": "FACTSlides",
    "logo": {
        "@type": "ImageObject",
        "url": "https:\/\/www.factslides.com\/imgs\/logo.png"
    }
},
"url": "https://www.factslides.com/s-Fact-Of-The-Day",
"mainEntityOfPage": "https://www.factslides.com/s-Fact-Of-The-Day",
"datePublished": "2019-03-19",
"dateCreated": "2019-03-19",
"dateModified": "2019-03-19",
"description": "Description.",
"articleBody": "Article clutter here."
}'''


jsonObj = json.loads(JS_TEXT)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...