2014-04-25 19 views
11

Sto provando a racimolare http://www.dailyfinance.com/quote/NYSE/international-business-machines/IBM/financial-ratios, ma la tecnica di costruzione delle stringhe url tradizionale non funziona perché la stringa "nome-azienda-è-inserita-nel-percorso". E l'esatto "nome dell'azienda" non è noto in anticipo. È noto solo il simbolo dell'azienda, "IBM".Come posso raschiare le pagine con URL generati dinamicamente usando Python?

In sostanza, il modo in cui scrivo consiste nel fare il ciclo di un array di simbolo aziendale e creare la stringa dell'URL prima di inviarla a urllib2.urlopen (url). Ma in questo caso, non si può fare.

Per esempio, stringa CSCO è

http://www.dailyfinance.com/quote/NASDAQ/cisco-systems-inc/CSCO/financial-ratios 

e un'altra stringa esempio url è AAPL:

http://www.dailyfinance.com/quote/NASDAQ/apple/AAPL/financial-ratios 

Quindi, al fine di ottenere l'url, ho dovuto cercare il simbolo nella casella di input sulla pagina principale:

http://www.dailyfinance.com/ 

ho notato che quando si digita "CSCO" e controllare l'ingresso di ricerca al numero (012.340.in Firefox scheda di rete sviluppatore web, ho notato che la richiesta GET sta inviando a

http://j.foolcdn.com/tmf/predictivesearch?callback=_predictiveSearch_csco&term=csco&domain=dailyfinance.com 

e che il referer dà effettivamente il percorso che voglio catturare

Host: j.foolcdn.com 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:28.0) Gecko/20100101 Firefox/28.0 
Accept: */* 
Accept-Language: en-US,en;q=0.5 
Accept-Encoding: gzip, deflate 
Referer: http://www.dailyfinance.com/quote/NASDAQ/cisco-systems-inc/CSCO/financial-ratios?source=itxwebtxt0000007 
Connection: keep-alive 

Ci scusiamo per la lunga spiegazione. Quindi la domanda è come estrarre l'url nel Referer? Se ciò non è possibile, come dovrei affrontare questo problema? C'è un altro modo?

Apprezzo molto il vostro aiuto.

+2

+1: * Molto * bella domanda, per me personalmente. – Manhattan

+0

Ci sono aggiornamenti su questo? Hai visto come il Referente è gestito correttamente nella mia risposta? – Manhattan

risposta

22

Mi piace questa domanda. E a causa di ciò, darò una risposta molto approfondita. Per questo, userò la mia libreria delle richieste preferite insieme a BeautifulSoup4. Effettuare il porting su Mechanize se vuoi davvero usarlo dipende da te. Le richieste ti faranno risparmiare un sacco di mal di testa.


Prima di tutto, probabilmente siete alla ricerca di una richiesta POST. Tuttavia, le richieste POST spesso non sono necessarie se una funzione di ricerca porta immediatamente alla pagina che stai cercando. Quindi controlliamolo, vero?

Quando atterro sulla URL di base, http://www.dailyfinance.com/, posso fare un semplice controllo tramite Firebug o Chrome di strumento ispezionare che quando ho messo in CSCO o AAPL sulla barra di ricerca e consentire il "salto", c'è un codice di 301 Moved Permanently di stato . Cosa significa questo?

enter image description here

In termini semplici, ero trasferiti da qualche parte. L'URL per questa richiesta GET è la seguente:

http://www.dailyfinance.com/quote/jump?exchange-input=&ticker-input=CSCO 

Ora, ci prova se funziona con AAPL utilizzando un semplice manipolazione URL.

import requests as rq 

apl_tick = "AAPL" 
url = "http://www.dailyfinance.com/quote/jump?exchange-input=&ticker-input=" 
r = rq.get(url + apl_tick) 
print r.url 

È possibile che questo dà il seguente risultato:

http://www.dailyfinance.com/quote/nasdaq/apple/aapl 
[Finished in 2.3s] 

vedere come l'URL della risposta è cambiato? Prendiamo la manipolazione URL un ulteriore passo avanti, cercando la pagina /financial-ratios aggiungendo il seguente per il codice di cui sopra:

new_url = r.url + "/financial-ratios" 
p = rq.get(new_url) 
print p.url 

Quando correva, questo dà è il seguente risultato:

http://www.dailyfinance.com/quote/nasdaq/apple/aapl 
http://www.dailyfinance.com/quote/nasdaq/apple/aapl/financial-ratios 
[Finished in 6.0s] 

Ora noi' ri sulla strada giusta. Ora cercherò di analizzare i dati usando BeautifulSoup. Il mio codice completo è il seguente:

from bs4 import BeautifulSoup as bsoup 
import requests as rq 

apl_tick = "AAPL" 
url = "http://www.dailyfinance.com/quote/jump?exchange-input=&ticker-input=" 
r = rq.get(url + apl_tick) 
new_url = r.url + "/financial-ratios" 
p = rq.get(new_url) 

soup = bsoup(p.content) 
div = soup.find("div", id="clear").table 
rows = table.find_all("tr") 
for row in rows: 
    print row 

Ho poi provare a eseguire questo codice, solo per incontrare un errore con il seguente traceback:

File "C:\Users\nanashi\Desktop\test.py", line 13, in <module> 
    div = soup.find("div", id="clear").table 
AttributeError: 'NoneType' object has no attribute 'table' 

di nota è la linea di 'NoneType' object.... Questo significa che il nostro obiettivo div non esiste! Egads, ma perché sto vedendo quanto segue ?!

enter image description here

Non ci può essere una sola spiegazione: la tabella è caricata in modo dinamico! Ratti. Vediamo se riusciamo a trovare un'altra fonte per il tavolo. Studio la pagina e vedo che ci sono delle barre di scorrimento in basso. Ciò potrebbe significare che la tabella è stata caricata all'interno di un frame o è stata caricata direttamente da un'altra fonte interamente e inserita in un div nella pagina.

Aggiorna la pagina e guardo di nuovo le richieste GET. Bingo, ho trovato qualcosa che sembra un po 'promettente:

enter image description here

un URL di riferimento di terze parti, e guarda, è facilmente manipolabile con il simbolo! Proviamo a caricarlo in una nuova scheda. Ecco cosa si ottiene:

enter image description here

WOW! Ora abbiamo la fonte esatta dei nostri dati. L'ultimo ostacolo è che funzionerà quando proveremo a estrarre i dati CSCO usando questa stringa (ricordate che siamo passati a CSCO -> AAPL e ora torniamo di nuovo a CSCO, quindi non siete confusi). Puliamo la stringa e abbandoniamo completamente il ruolo di www.dailyfinance.com.Il nostro nuovo URL è il seguente:

http://www.motleyfool.idmanagedsolutions.com/stocks/financial_ratios.idms?SYMBOL_US=AAPL 

Proviamo a utilizzarlo nel nostro raschietto finale!

from bs4 import BeautifulSoup as bsoup 
import requests as rq 

csco_tick = "CSCO" 
url = "http://www.motleyfool.idmanagedsolutions.com/stocks/financial_ratios.idms?SYMBOL_US=" 
new_url = url + csco_tick 

r = rq.get(new_url) 
soup = bsoup(r.content) 

table = soup.find("div", id="clear").table 
rows = table.find_all("tr") 
for row in rows: 
    print row.get_text() 

E i nostri risultati grezzi per i dati indici finanziari del CSCO è la seguente:

Company 
Industry 


Valuation Ratios 


P/E Ratio (TTM) 
15.40 
14.80 


P/E High - Last 5 Yrs 
24.00 
28.90 


P/E Low - Last 5 Yrs 
8.40 
12.10 


Beta 
1.37 
1.50 


Price to Sales (TTM) 
2.51 
2.59 


Price to Book (MRQ) 
2.14 
2.17 


Price to Tangible Book (MRQ) 
4.25 
3.83 


Price to Cash Flow (TTM) 
11.40 
11.60 


Price to Free Cash Flow (TTM) 
28.20 
60.20 


Dividends 


Dividend Yield (%) 
3.30 
2.50 


Dividend Yield - 5 Yr Avg (%) 
N.A. 
1.20 


Dividend 5 Yr Growth Rate (%) 
N.A. 
144.07 


Payout Ratio (TTM) 
45.00 
32.00 


Sales (MRQ) vs Qtr 1 Yr Ago (%) 
-7.80 
-3.70 


Sales (TTM) vs TTM 1 Yr Ago (%) 
5.50 
5.60 


Growth Rates (%) 


Sales - 5 Yr Growth Rate (%) 
5.51 
5.12 


EPS (MRQ) vs Qtr 1 Yr Ago (%) 
-54.50 
-51.90 


EPS (TTM) vs TTM 1 Yr Ago (%) 
-54.50 
-51.90 


EPS - 5 Yr Growth Rate (%) 
8.91 
9.04 


Capital Spending - 5 Yr Growth Rate (%) 
20.30 
20.94 


Financial Strength 


Quick Ratio (MRQ) 
2.40 
2.70 


Current Ratio (MRQ) 
2.60 
2.90 


LT Debt to Equity (MRQ) 
0.22 
0.20 


Total Debt to Equity (MRQ) 
0.31 
0.25 


Interest Coverage (TTM) 
18.90 
19.10 


Profitability Ratios (%) 


Gross Margin (TTM) 
63.20 
62.50 


Gross Margin - 5 Yr Avg 
66.30 
64.00 


EBITD Margin (TTM) 
26.20 
25.00 


EBITD - 5 Yr Avg 
28.82 
0.00 


Pre-Tax Margin (TTM) 
21.10 
20.00 


Pre-Tax Margin - 5 Yr Avg 
21.60 
18.80 


Management Effectiveness (%) 


Net Profit Margin (TTM) 
17.10 
17.65 


Net Profit Margin - 5 Yr Avg 
17.90 
15.40 


Return on Assets (TTM) 
8.30 
8.90 


Return on Assets - 5 Yr Avg 
8.90 
8.00 


Return on Investment (TTM) 
11.90 
12.30 


Return on Investment - 5 Yr Avg 
12.50 
10.90 


Efficiency 


Revenue/Employee (TTM) 
637,890.00 
556,027.00 


Net Income/Employee (TTM) 
108,902.00 
98,118.00 


Receivable Turnover (TTM) 
5.70 
5.80 


Inventory Turnover (TTM) 
11.30 
9.70 


Asset Turnover (TTM) 
0.50 
0.50 

[Finished in 2.0s] 

eliminando i dati dipende da voi.


Una buona lezione da imparare da questo raschiare non è tutti i dati sono contenuti in una pagina sola. È piuttosto bello vederlo provenire da un altro sito statico. Se fosse stato prodotto tramite chiamate JavaScript o AJAX o simili, avremmo probabilmente qualche difficoltà con il nostro approccio.

Speriamo che tu abbia imparato qualcosa da questo. Facci sapere se questo aiuta e buona fortuna.

+3

Wow, sei un maniaco del web-scraping (in senso buono)! :) Non ci sono più revisioni per oggi - arriverà e +1 domani. – alecxe

+1

@alecxe: Amico, non sai quanto ho imparato da te. Venendo da te, è un grande complimento. ;) Grazie! – Manhattan

+1

Grazie! Siamo qui per imparare gli uni dagli altri. Tali risposte dettagliate rendono davvero migliore il mondo del web-scraping. Spero di sentire di più da te in tag correlati. – alecxe

2

Non risponde alla domanda specifica, ma risolve il problema.

http://www.dailyfinance.com/quotes/{Company Symbol}/{Stock Exchange}

Esempi:

http://www.dailyfinance.com/quotes/AAPL/NAS

http://www.dailyfinance.com/quotes/IBM/NYSE

http://www.dailyfinance.com/quotes/CSCO/NAS

Per accedere alla pagina indici finanziari si potrebbe quindi utilizzare qualcosa di simile:

import urllib2 

def financial_ratio_url(symbol, stock_exchange): 
    starturl = 'http://www.dailyfinance.com/quotes/' 
    starturl += '/'.join([symbol, stock_exchange]) 
    req = urllib2.Request(starturl) 
    res = urllib2.urlopen(starturl) 
    return '/'.join([res.geturl(),'financial-ratios']) 

Esempio:

financial_ratio_url('AAPL', 'NAS') 
'http://www.dailyfinance.com/quote/nasdaq/apple/aapl/financial-ratios' 
+0

Grazie per la risposta. L'ho trovato utile e molto educativo. – vt2424253

Problemi correlati