Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  18 4797
Hei!

Jeg er selvlært og har litt basic erfaring med scraping fra tidligere prosjekter, men nå har jeg kommet over en nettside der jeg sliter med å hente det jeg ønsker.

Kode

<div class="dp-pair">
                                    <div class="dp-name ng-binding">Price/Sales</div>
                                    <div class="dp-value ng-binding">1.02</div>
                                </div>
Sånn her ser tagsa ut, og det jeg da ønsker er å finne en måte hvor jeg får hentet ut Price/Sales og 1.02. Er det noen som har noen gode forslag til hvordan jeg kan løse dette? Hittil har jeg kun fått til enten å hente dp-name eller dp-value, men det finnes veldig mange "dp-pair" og resultatet blir en haug av data, og det er vanskelig å koble opp name med value, noe som jeg må så jeg vet hvilken value resultatet representerer.
Sist endret av Ardluh; 17. januar 2019 kl. 18:40.
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Lite erfaring med beautifulsoup, men regner med at du kan bruke selectors som er mer eller mindre som i tilsvarende løsninger? Hva med å mappe .dp-pair til en dictionary siden du har par med nøkler og verdier? Det virker som den ideelle måten å behandle dem videre på.

Eksempel: lag dict, finn alle .dp-pair, for hvert element hent ut .dp-name og .dp-value, smell inn i dictionary som det måtte passe seg?
Sist endret av robhol; 17. januar 2019 kl. 19:34.
Nettsiden du scraper bruker angular. Stor sjanse for at den snakker med et api du kan hente data fra i stedet for å scrape
Lenge siden jeg har brukt BeautifulSoup, men kanskje noe som dette fungerer:

Kode

dp-pairs = soup.div.find_all(class_="dp-pair")
data = []
for p in pairs:
    data.append(list(d.text for d in p.div))
Denne koden antar at det bare er 2 div i hver dp-pair div.

Det snek seg inn en skrivefeil i koden, linje 3 skal selvfølgelig være

Kode

for p in dp-pairs:
Sist endret av steili; 18. januar 2019 kl. 00:50. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
Sitat av lor3ntz Vis innlegg
Nettsiden du scraper bruker angular. Stor sjanse for at den snakker med et api du kan hente data fra i stedet for å scrape
Vis hele sitatet...
Støtter denne.
  1. Åpne developer tools i chrome.
  2. trykk på fanen "Network".
  3. refresh siden.
  4. trykk på xhr for å kun se på ajax requests.
  5. Gå gjennom alle i listen og se etter noe som ser ut som json. Her ligger antageligvis dine data.
Som nevnt over kan se om kan om kan finne data i ajax,xhr,json request på side.
Det er annen måte det er og bruke Selenium Python.
Da får man med rendered JavaScript kan kombinere med beautifulsoup med og sende browser.page_source til BS for parsing.
Kan også la være og laste nettleser med --headless,
når man kun skal ha data vil ikke lasting av nettleser ha noen funksjon.

For gi et eksempel:

Kode

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import time

browser = webdriver.Chrome()
#---| Headless setup
#chrome_options = Options()
#chrome_options.add_argument("--headless")
#browser = webdriver.Chrome(chrome_options=chrome_options)
#---
url = 'https://howsecureismypassword.net/'
browser.get(url)
inputElement = browser.find_elements_by_class_name("password-input")[0]
inputElement.send_keys("123hello")
inputElement.send_keys(Keys.RETURN)
time.sleep(3)

# Give source code to BeautifulSoup
soup = BeautifulSoup(browser.page_source, 'lxml')
# Now can parse the rendred JavaScript from site
top_text = soup.select_one('.result__text.result__before')
crack_time = soup.select_one('.result__text.result__time')
bottom_text  = soup.select_one('.result__text.result__after')
print(top_text.text)
print(crack_time.text)
print(bottom_text.text)
time.sleep(3)
browser.close()

Kode

It would take a computer about
1 minute
to crack your password
Hvilken nettside er det du ønsker å scrape? Kan forsøke en løsning i R for moro skyld.
▼ ... over en måned senere ... ▼
Trådstarter
Sitat av Chronic420 Vis innlegg
Hvilken nettside er det du ønsker å scrape? Kan forsøke en løsning i R for moro skyld.
Vis hele sitatet...
Hei! Har hatt lite tid til å prioritere prosjektet i det siste, så beklager for sent svar. Men nettsiden er Morningstar, mer spesifikt f.eks. her: XXL quote.

Under tabben "quote" finner man bid/size, ask/size,, Price/sales osv, er disse tallene jeg er ute etter.

Jeg bruker allerede selenium og får tak i dataen på nettsiden, men det er parsingen av denne dataen jeg sliter med.
Sist endret av Ardluh; 2. mars 2019 kl. 00:02.
Du trenger ikke scrape siden.
Den blir populert med xhr, bare hent data fra de samme endepunktene.

https://api-global.morningstar.com/s...63029766099324
og
https://api-global.morningstar.com/s...8/securityInfo

Bare hent ut seed og headere på forhånd.
Sitat av Ardluh Vis innlegg
Hei! Har hatt lite tid til å prioritere prosjektet i det siste, så beklager for sent svar. Men nettsiden er Morningstar, mer spesifikt f.eks. her: XXL quote.

Under tabben "quote" finner man bid/size, ask/size,, Price/sales osv, er disse tallene jeg er ute etter.

Jeg bruker allerede selenium og får tak i dataen på nettsiden, men det er parsingen av denne dataen jeg sliter med.
Vis hele sitatet...
Igjen, anbefaler at du heller gjør som tidligere har blitt foreslått. Man kan helt fint parse en nettside, men da må man jo rendre javascript først, pluss at den blir svak mot endringer på nettside. Hvorfor gjøre all denne meningsløse rendringen, når man kan gå rett til kilden?

edit: hvis du ønsker å leke med eksemplet mitt, kopier teksten min ovenfor, gå til nettsiden du linket til, åpne developer console, og paste den inn der.

JSON eksempel:

HTML-kode

let request = await fetch("https://api-global.morningstar.com/sal-service/v1/stock/realTime/v3/0P00014DM8/data?secExchangeList=&random=0.9727767081695287", {"credentials":"omit","headers":{"accept":"application/json, text/plain, */*","apikey":"lstzFDEOhfFNMLikKa0am9mgEKLBl49T","x-api-realtime-e":"eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.PfhNqGbb5pDw7LpfST5lr9RMYI3hL_Ebmb8IaJLImhh-CrjUP89QQMirvsRtSxdQ9kOuWdf52b_xyjlALGhUyx5QC9q80VrTJnLbzMytFWsCsg26VU4qpDmheBSL74Em50ne2ldY1JbIJi_6hOaiJMVAA58RS_yKyIoKBOZRKDY.nLe9OTIYlYPVpL6x.BQKM7_bJYkgCRFcJ52GtqTdb_m9pVy8gasruHsNkbSm27UeU5Wlm-tUM3-sAog7iSbHx6mrfSsrVnMYqyTZ8bHI34kCq36E7KnNzhaQl_W1datGvjZNbX2ZRtGDUnc0CZA_IQsmO280FtbGGpOBkgaW9cJrhbp4Zh2zrbRXzWlxD7rUtKh1eStnrUPDhzIkKDS2asbHipzqeu9S3FdsSfGX8Kw.2gSc9-6dr6E6WwnB5Kl2rw","x-api-requestid":"657cd965-c7c6-3691-c436-72fd3296f01a","x-sal-contenttype":"e7FDDltrTy+tA2HnLovvGL0LFMwT+KkEptGju5wXVTU="},"referrer":"https://www.morningstar.com/stocks/XOSL/XXL/quote.html","referrerPolicy":"no-referrer-when-downgrade","body":null,"method":"GET","mode":"cors"});

let data = await request.json()

console.log(data.bid)
// => 32.85

console.log(data.bidSize)
// => 2117

console.log(data.ask)
// => 33.05

console.log(data.askSize)
// => 2003
I dette eksempelet er hele parsingen tatt hånd om. Hvis du ønsker å gjøre dette i python, trenger du å se på hvordan du kan sende http requests, og hvordan du konverterer responsen til å bli et JSON objekt.

Resultatet er ferdig parset med alle data du ønsker.
Sist endret av Patrick; 2. mars 2019 kl. 00:55. Grunn: tilleggsinfo
Trådstarter
Sitat av Patrick Vis innlegg
Igjen, anbefaler at du heller gjør som tidligere har blitt foreslått. Man kan helt fint parse en nettside, men da må man jo rendre javascript først, pluss at den blir svak mot endringer på nettside. Hvorfor gjøre all denne meningsløse rendringen, når man kan gå rett til kilden?

edit: hvis du ønsker å leke med eksemplet mitt, kopier teksten min ovenfor, gå til nettsiden du linket til, åpne developer console, og paste den inn der.

JSON eksempel:

HTML-kode

let request = await fetch("https://api-global.morningstar.com/sal-service/v1/stock/realTime/v3/0P00014DM8/data?secExchangeList=&random=0.9727767081695287", {"credentials":"omit","headers":{"accept":"application/json, text/plain, */*","apikey":"lstzFDEOhfFNMLikKa0am9mgEKLBl49T","x-api-realtime-e":"eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.PfhNqGbb5pDw7LpfST5lr9RMYI3hL_Ebmb8IaJLImhh-CrjUP89QQMirvsRtSxdQ9kOuWdf52b_xyjlALGhUyx5QC9q80VrTJnLbzMytFWsCsg26VU4qpDmheBSL74Em50ne2ldY1JbIJi_6hOaiJMVAA58RS_yKyIoKBOZRKDY.nLe9OTIYlYPVpL6x.BQKM7_bJYkgCRFcJ52GtqTdb_m9pVy8gasruHsNkbSm27UeU5Wlm-tUM3-sAog7iSbHx6mrfSsrVnMYqyTZ8bHI34kCq36E7KnNzhaQl_W1datGvjZNbX2ZRtGDUnc0CZA_IQsmO280FtbGGpOBkgaW9cJrhbp4Zh2zrbRXzWlxD7rUtKh1eStnrUPDhzIkKDS2asbHipzqeu9S3FdsSfGX8Kw.2gSc9-6dr6E6WwnB5Kl2rw","x-api-requestid":"657cd965-c7c6-3691-c436-72fd3296f01a","x-sal-contenttype":"e7FDDltrTy+tA2HnLovvGL0LFMwT+KkEptGju5wXVTU="},"referrer":"https://www.morningstar.com/stocks/XOSL/XXL/quote.html","referrerPolicy":"no-referrer-when-downgrade","body":null,"method":"GET","mode":"cors"});

let data = await request.json()

console.log(data.bid)
// => 32.85

console.log(data.bidSize)
// => 2117

console.log(data.ask)
// => 33.05

console.log(data.askSize)
// => 2003
I dette eksempelet er hele parsingen tatt hånd om. Hvis du ønsker å gjøre dette i python, trenger du å se på hvordan du kan sende http requests, og hvordan du konverterer responsen til å bli et JSON objekt.

Resultatet er ferdig parset med alle data du ønsker.
Vis hele sitatet...
Tusen takk, det virker naturligvis som den beste løsningen. Jeg leker meg litt med koden din nå, men det ser ikke ut til at jeg finner det aller viktigste som jeg leter etter: Price/Sales, Price/Book og Price/Earnings. Har du noen anelse om hvorfor?
Sitat av Ardluh
Jeg bruker allerede selenium og får tak i dataen på nettsiden, men det er parsingen av denne dataen jeg sliter med.
Vis hele sitatet...
Kan lage et eksempel og parse et par verdier.

Kode

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import time

#--| Setup
options = Options()
options.add_argument("--headless")
options.add_argument('--disable-gpu')
options.add_argument('--log-level=3')
browser = webdriver.Chrome(executable_path=r'C:\cmder\bin\chromedriver.exe', options=options)
#--| Parse or automation
browser.get('https://www.morningstar.com/stocks/XOSL/XXL/quote.html')
time.sleep(3)
soup = BeautifulSoup(browser.page_source, 'lxml')
bid_size = soup.select('div.dp-value.price-down.ng-binding.ng-scope')
price_sales = soup.select('li:nth-child(9) > div > div.dp-value.ng-binding')
print(bid_size[0].text.strip())
print(price_sales[0].text.strip())

Kode

32.85×2,117
0.49
Trådstarter
Sitat av snippsat Vis innlegg
Kan lage et eksempel og parse et par verdier.

Kode

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import time

#--| Setup
options = Options()
options.add_argument("--headless")
options.add_argument('--disable-gpu')
options.add_argument('--log-level=3')
browser = webdriver.Chrome(executable_path=r'C:\cmder\bin\chromedriver.exe', options=options)
#--| Parse or automation
browser.get('https://www.morningstar.com/stocks/XOSL/XXL/quote.html')
time.sleep(3)
soup = BeautifulSoup(browser.page_source, 'lxml')
bid_size = soup.select('div.dp-value.price-down.ng-binding.ng-scope')
price_sales = soup.select('li:nth-child(9) > div > div.dp-value.ng-binding')
print(bid_size[0].text.strip())
print(price_sales[0].text.strip())

Kode

32.85×2,117
0.49
Vis hele sitatet...
Hei! Takk for koden, men når linja for å finne Price/Sales kjøres, så får jeg følgende feilmelding:

Kode

Traceback (most recent call last):
  File "C:/Python34/Scripts/Fundemental lxml.py", line 20, in <module>
    price_sales = soup.select('li:nth-child(9) > div > div.dp-value.ng-binding')
  File "C:\Python34\lib\site-packages\bs4\element.py", line 1451, in select
    'Only the following pseudo-classes are implemented: nth-of-type.')
NotImplementedError: Only the following pseudo-classes are implemented: nth-of-type.
. Og etter å ha søkt litt rundt står det at beautifulsoup ikke støtter den formen for select på den type verdi og at jeg må bruke f.eks. find.. Hmm, vet du noe om det?

Har også forsøkt den andre metoden med api, men jeg får http access code 401, og har ikke helt funnet noen måte å få autorisert. Jeg tror det i utgangspunktet er en betalingstjeneste.
Ah, det er ikke bare å hente fra source, nei. Har du googlet egentlig? Sjekk ut disse: Morningstar API (GitHub), stackoverflow.
Trådstarter
Sitat av Chronic420 Vis innlegg
Ah, det er ikke bare å hente fra source, nei. Har du googlet egentlig? Sjekk ut disse: Morningstar API (GitHub), stackoverflow.
Vis hele sitatet...
Jeg kjenner til den, men av en eller annen rar grunn finner man ikke Price/Earnings, Price/Book eller Price/Sales der, noe som er de tre tallene jeg i all hovedsak er ute etter.

Eneste måten jeg har funnet ut hvordan jeg kan få hentet ut de tallene er gjennom selenium og webscraping, og jeg får jo til å hente alle de ulike parene med "db-pairs", men jeg kommer ikke på noen måte, eller har nok kompetanse til, å kun få fram verdiene til P/E, P/B, og P/S, så da har jeg bare en hel vegg av tekst.

Det burde jo finnes en måte det kan gjøres på, hmm.
Sist endret av Ardluh; 3. mars 2019 kl. 07:20.
Hvorfor gjør du det så vanskelig?
Skrev jo i posten min over hvilke kall du trengte...

Python eksempel:

Kode

#!/bin/env python

import requests

s = requests.Session()

s.get("https://www.morningstar.com/stocks/XOSL/XXL/quote.html")

headers = {"apikey": "lstzFDEOhfFNMLikKa0am9mgEKLBl49T",
           "X-API-REALTIME-E": "eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.NuHDrlK_QdmA9PTXQB3Nw_Rp4P28ZbyJvmw_d9u8dZzWgIlodjz32srgYAf81hTbiPLapHZ9-ySiwXti-qwd-Wfgu6MmIMwFEe0mEEdcw0wSVk_jdniQv4FwZSu8Xaa1Sa7asBgBmqESAf8g2OXl7A6IfSyExmSeAxvcFT2IGbc.FoSSTvt6vDIrGdRE.vDAFeW8-bUeC3Jymga-ZYG7Bwh1U7PBp_JmVgQifRNjbMhtY1SKeBS0wUqGU1aFQWT1O6yBa4uNqItJtThdPhpD1B9Ka70NLJjpcy0sA8-5uRa5VRR_UlV3wy2RukIU-wi2aW_VBsxpgEvwKSNqYVVdUblHo6Fwv5OVAaFMoIxChmjx8qWNeEYr7jBSTycovQC3U5xe8NgZR2brCgcPZsCxCRQ.r346lZPjs1ecBGUOMAIrZg"}

url = "https://api-global.morningstar.com/sal-service/v1/stock/realTime/v3/0P00014DM8/data?secExchangeList="
r = s.get(url,headers=headers)
rt = r.json()

url = "https://api-global.morningstar.com/sal-service/v1/stock/header/v2/data/0P00014DM8/securityInfo"
r = s.get(url, headers=headers)
se = r.json()

print rt["bid"], rt["bidSize"], rt["ask"], rt["askSize"]
print se["priceSale"], se["priceBook"], se["priceEarnings"]
Og etter å ha søkt litt rundt står det at beautifulsoup ikke støtter den formen for select på den type verdi og at jeg må bruke f.eks. find.. Hmm, vet du noe om det?
Vis hele sitatet...
Oppgrader BeautifulSoup,også smart og gå fra 3.4 til Python 3.7.

Kode

pip install beautifulsoup4 --upgrade
En API løsning som postet over av @Goophy kan være en bedre løsning,men begge skal fungere ok.
Andre med gode API ALPHA VANTAGE og Quandl.
Sist endret av snippsat; 3. mars 2019 kl. 18:14.
Trådstarter
Sitat av Goophy Vis innlegg
Hvorfor gjør du det så vanskelig?
Skrev jo i posten min over hvilke kall du trengte...

Python eksempel:

Kode

#!/bin/env python

import requests

s = requests.Session()

s.get("https://www.morningstar.com/stocks/XOSL/XXL/quote.html")

headers = {"apikey": "lstzFDEOhfFNMLikKa0am9mgEKLBl49T",
           "X-API-REALTIME-E": "eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.NuHDrlK_QdmA9PTXQB3Nw_Rp4P28ZbyJvmw_d9u8dZzWgIlodjz32srgYAf81hTbiPLapHZ9-ySiwXti-qwd-Wfgu6MmIMwFEe0mEEdcw0wSVk_jdniQv4FwZSu8Xaa1Sa7asBgBmqESAf8g2OXl7A6IfSyExmSeAxvcFT2IGbc.FoSSTvt6vDIrGdRE.vDAFeW8-bUeC3Jymga-ZYG7Bwh1U7PBp_JmVgQifRNjbMhtY1SKeBS0wUqGU1aFQWT1O6yBa4uNqItJtThdPhpD1B9Ka70NLJjpcy0sA8-5uRa5VRR_UlV3wy2RukIU-wi2aW_VBsxpgEvwKSNqYVVdUblHo6Fwv5OVAaFMoIxChmjx8qWNeEYr7jBSTycovQC3U5xe8NgZR2brCgcPZsCxCRQ.r346lZPjs1ecBGUOMAIrZg"}

url = "https://api-global.morningstar.com/sal-service/v1/stock/realTime/v3/0P00014DM8/data?secExchangeList="
r = s.get(url,headers=headers)
rt = r.json()

url = "https://api-global.morningstar.com/sal-service/v1/stock/header/v2/data/0P00014DM8/securityInfo"
r = s.get(url, headers=headers)
se = r.json()

print rt["bid"], rt["bidSize"], rt["ask"], rt["askSize"]
print se["priceSale"], se["priceBook"], se["priceEarnings"]
Vis hele sitatet...
Jeg tror du hadde rivd deg i håret om du hadde sett koden til flere av mine tidligere prosjekter. Jeg er nok en amatør, og jeg forstod nok ikke helt hva du mente tidligere.

Men jeg er evig takknemlig for all hjelp jeg har fått! Selv om en ikke skulle tro det så har jeg faktisk stått fast her ganske lenge. Men nå føler jeg at ting ble litt klarere.

Tusen takk alle sammen!

Sitat av snippsat Vis innlegg
Oppgrader BeautifulSoup,også smart og gå fra 3.4 til Python 3.7.

Kode

pip install beautifulsoup4 --upgrade
En API løsning som postet over av @Goophy kan være en bedre løsning,men begge skal fungere ok.
Andre med gode API ALPHA VANTAGE og Quandl.
Vis hele sitatet...
Jeg har gått for api-løsningen til Goophy, men er godt å vite at jeg har flere alternativ! Tusen takk! Skal også sjekke ut de andre api'ene om det viser seg at denne ikke strekker til.
Sist endret av Ardluh; 4. mars 2019 kl. 15:18. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
▼ ... noen uker senere ... ▼
Trådstarter
Hei!

Nå har jeg rotet meg opp i noe igjen.

Jeg prøver å hente informasjon fra https://financials.morningstar.com/r...n&platform=sal. I motsetning til den forrige nettlinken, så benytter denne seg av "XMLHttpRequest" og jeg har til nå bare benyttet meg av:
r = requests.get("https://financials.morningstar.com/finan/financials/getKeyStatPart.html?&callback=jsonp1552999108585&t=0P0000C7A V&region=nor&culture=en-US&version=SAL&cur=&order=asc&_=1552999108634")
Vis hele sitatet...
Dette fungerer, men det jeg får henta ut av det ser ut som dette: https://pastebin.com/Z2Y6VNsR

Og jeg vet ikke helt hvordan jeg skal få sortert ut informasjon fra denne stringen. Type er xhr, initiator er jquery-1.3.2 og content-type er: application/json;charset=UTF-8.

Jeg har prøvd json, men det fungerer ikke. Er det noen som har forslag til en riktig måte å hente ut informasjonen?

Eventuelt gjør jeg dette riktig? Eller er det bare at jeg har ikke forstått hvordan jeg skal parse det? Jeg har også prøvd beautifulsoup.
Sist endret av Ardluh; 19. mars 2019 kl. 21:30. Grunn: Automatisk sammenslåing med etterfølgende innlegg.