web-dev-qa-db-fra.com

Analyser le code JavaScript renvoyé de BeautifulSoup

Je voudrais analyser la page Web http://dcsd.nutrislice.com/menu/meadow-view/lunch/ pour saisir le menu du déjeuner de ce jour. (J'ai construit une imprimante thermique Adafruit #IoT et j'aimerais imprimer automatiquement le menu tous les jours.)

J'ai d'abord abordé cette question en utilisant BeautifulSoup, mais il s'avère que la plupart des données sont chargées en JavaScript et je ne suis pas sûr que BeautifulSoup puisse les gérer. Si vous visualisez la source, vous verrez les données pertinentes stockées dans bootstrapData['menuMonthWeeks'].

import urllib2
from BeautifulSoup import BeautifulSoup

url = "http://dcsd.nutrislice.com/menu/meadow-view/lunch/"
soup = BeautifulSoup(urllib2.urlopen(url).read())

C'est un moyen facile d'obtenir la source et de la réviser.

Ma question est la suivante: quel est le moyen le plus simple d’extraire ces données pour pouvoir en faire quelque chose? Littéralement, tout ce que je veux, c'est une chaîne qui ressemble à ceci:

Omelette au fromage du sud-ouest, quartiers de pomme de terre, barre de récolte (THB), THB - pain au pesto au fromage, sandwich au jambon et au Deli, bâtonnets de piment rouge

J'ai envisagé d'utiliser Webkit pour traiter la page et obtenir le code HTML (c'est-à-dire ce que fait un navigateur), mais cela semble inutilement complexe. Je préférerais simplement trouver quelque chose qui puisse analyser les données bootstrapData['menuMonthWeeks'].

15
Wade

Quelque chose comme PhantomJS peut être plus robuste, mais voici un code de base Python pour l'extraire du menu complet:

import json
import re
import urllib2

text = urllib2.urlopen('http://dcsd.nutrislice.com/menu/meadow-view/lunch/').read()
menu = json.loads(re.search(r"bootstrapData\['menuMonthWeeks'\]\s*=\s*(.*);", text).group(1))

print menu

Après cela, vous voudrez rechercher dans le menu la date qui vous intéresse.

EDIT: Un excès de ma part:

import itertools
import json
import re
import urllib2

text = urllib2.urlopen('http://dcsd.nutrislice.com/menu/meadow-view/lunch/').read()
menus = json.loads(re.search(r"bootstrapData\['menuMonthWeeks'\]\s*=\s*(.*);", text).group(1))

days = itertools.chain.from_iterable(menu['days'] for menu in menus)

day = next(itertools.dropwhile(lambda day: day['date'] != '2014-01-13', days), None)

if day:
    print '\n'.join(item['food']['description'] for item in day['menu_items'])
else:
    print 'Day not found.'
10
smarx

Tout ce dont vous avez besoin est un peu de coupe en ficelle:

import json

soup = BeautifulSoup(urllib2.urlopen(url).read())
script = soup.findAll('script')[1].string
data = script.split("bootstrapData['menuMonthWeeks'] = ", 1)[-1].rsplit(';', 1)[0]
data = json.loads(data)

JSON est, après tout, un sous-ensemble de JavaScript.

5
Martijn Pieters

Je me rends compte que c'est environ quatre ans plus tard, mais nutrislice (au moins maintenant) a une api à partir de laquelle vous pouvez obtenir directement du JSON. Le déjeuner de vos enfants d'il y a quelques jours: http://dcsd.nutrislice.com/menu/api/digest/school/meadow-view/menu-type/lunch/date/2018/03/14/

1
chad

sans BeautifulSoup, un moyen simple de:

import urllib2
import json
url = "http://dcsd.nutrislice.com/menu/meadow-view/lunch/"
for line in urllib2.urlopen(url):
    if "bootstrapData['menuMonthWeeks']" in line:
        data = json.loads(line.split("=")[1].strip('\n;'))
        print data[0]["last_updated"]

sortie:

2013-11-11T11:18:13.636

pour une manière plus générique, voir Analyseur JavaScript en Python

1
Guy Gavriely

Sans jouer avec json, si vous préférez, ce qui n'est pas recommandé, vous pouvez essayer les solutions suivantes:

import urllib2
import re

url = "http://dcsd.nutrislice.com/menu/meadow-view/lunch/"
data = urllib2.urlopen(url).readlines()[60].partition('=')[2].strip()

foodlist = []

prev = 'name'
for i in re.findall('"([^"]*)"', data):
    if "The Harvest Bar (THB)" in i or i == "description" or i == "start_date":
        prev = i
        continue
    if prev == 'name':
        if i.startswith("THB - "):
            i = i[6:]
        foodlist.append(i)
    prev = i

Je suppose que c'est ce dont vous aurez besoin en fin de compte:

Orange Chicken Bowl
Roasted Veggie Pesto Pizza
Cheese Sandwich & Yogurt Tube
Steamed Peas
Peaches
Southwest Cheese Omelet
Potato Wedges
Cheesy Pesto Bread
Ham Deli Sandwich
Red Pepper Sticks
Strawberries
Hamburger
Cheeseburger
Potato Wedges
Chicken Minestrone Soup
Veggie Deli Sandwich
Baked Beans
Green Beans
Fruit Cocktail
Cheese Pizza
Pepperoni Pizza
Diced Chicken w/ Cornbread
Turkey Deli Sandwich
Celery Sticks
Blueberries
Cowboy Mac
BYO Asian Salad
Sunbutter Sandwich
Stir Fry Vegetables
Pineapple Tidbits
Enchilada Blanco
Sausage & Black Olive Pizza
Cheese Sandwich & Yogurt Tube
Southwest Black Beans
Red Pepper Sticks
Applesauce
BBQ Roasted Chicken.
Hummus Cup w/  Pita bread
Ham Deli Sandwich
Mashed potatoes w/ gravy
Celery Sticks
Kiwi
Popcorn Chicken Bowl
Tuna Salad w/  Pita Bread
Veggie Deli Sandwich
Corn Niblets
Blueberries
Cheese Pizza
Pepperoni Pizza
BYO Chef Salad
BYO Vegetarian Chef Salad
Turkey Deli Sandwich
Steamed Cauliflower
Banana, Whole
Bosco Sticks
Chicken Egg Roll & Chow Mein Noodles
Sunbutter Sandwich
California Blend Vegetables
Fresh Pears
Baked Mac & Cheese
Italian Dunker
Ham Deli Sandwich
Red Pepper Sticks
Pineapple Tidbits
Hamburger
Cheeseburger
Baked Fries
BYO Taco Salad
Veggie Deli Sandwich
Baked Beans
Coleslaw
Fresh Grapes
Cheese Pizza
Pepperoni Pizza
Diced Chicken w/ Cornbread
Turkey Deli Sandwich
Steamed Cauliflower
Fruit Cocktail
French Dip w/ Au Jus
Baked Fries
Turkey Noodle Soup
Sunbutter Sandwich
Green Beans
Warm Cinnamon Apples
Rotisserie Chicken
Mashed potatoes w/ gravy
Bacon Cheeseburger Pizza
Cheese Sandwich & Yogurt Tube
Steamed Peas
Apple Wedges
Turkey Chili 
Cornbread Muffins
BYO Chef Salad
BYO Vegetarian Chef Salad
Ham Deli Sandwich
Celery Sticks
Fresh Pears
Beef, Bean & Red Chili Burrito
Popcorn Chicken & Breadstick
Veggie Deli Sandwich
California Blend Vegetables
Strawberries
Cheese Pizza
Pepperoni Pizza
Hummus Cup w/  Pita bread
Turkey Deli Sandwich
Green Beans
Orange Wedges
Bosco Sticks
Cheesy Bean Soft Taco Roll Up
Sunbutter Sandwich
Pinto Bean Cup
Baby Carrots
Blueberries

Avec json:

import urllib2
import json
url = "http://dcsd.nutrislice.com/menu/meadow-view/lunch/"
for line in urllib2.urlopen(url):
    if "bootstrapData['menuMonthWeeks']" in line:
        data = json.loads(line.split("=")[1].strip('\n;'))
        print data[0]["name"]
    break
0
alvas