如何使用Python刮取带有动态生成的url的页面?

2024-07-08 15:06:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图擦掉http://www.dailyfinance.com/quote/NYSE/international-business-machines/IBM/financial-ratios,但是传统的url字符串构建技术不起作用,因为“在路径中插入完整的公司名称”字符串。而确切的“公司全名”还不知道。只有公司的标志“IBM”是已知的。

实际上,我刮取的方法是循环遍历一个公司符号数组,并在将url字符串发送到urllib2.urlopen(url)之前构建它。但在这种情况下,这是做不到的。

例如,CSCO字符串是

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

另一个url字符串示例是AAPL:

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

所以为了得到这个url,我必须在主页的输入框中搜索这个符号:

http://www.dailyfinance.com/

我注意到,当我键入“CSCO”并检查Firefox web开发人员网络选项卡中(http://www.dailyfinance.com/quote/NASDAQ/apple/AAPL/financial-ratios)处的搜索输入时,我注意到get请求被发送到

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

引用者实际上给出了我想要捕获的路径

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

对不起,解释太长了。所以问题是如何提取Referer中的url?如果这是不可能的,我应该如何处理这个问题?还有别的办法吗?

我真的很感谢你的帮助。


Tags: 字符串comhttpurlwww公司ibmquote
2条回答

我喜欢这个问题。因此,我将给出一个非常彻底的答案。为此,我将使用我最喜欢的请求库和BeautifulSoup4。如果你真的想用的话,移植到Mechanize是你自己的事。不过,提出要求会让你省去很多麻烦。


首先,你可能在寻找一个POST请求。但是,如果搜索函数带到您要查找的页面,则通常不需要POST请求。我们来检查一下,好吗?

当我登陆基本URL http://www.dailyfinance.com/时,我可以通过Firebug或Chrome的inspect工具进行一个简单的检查,当我在搜索栏上输入CSCO或AAPL并启用“跳转”时,会有一个301 Moved Permanently状态代码。这是什么意思?

enter image description here

简单地说,我被转移到了某处。此GET请求的URL如下:

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

现在,我们通过使用一个简单的URL操作来测试它是否与AAPL一起工作。

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

上述结果如下:

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

查看响应的URL是如何更改的?让我们通过在上面的代码后面附加以下内容来查找/financial-ratios页面,进一步执行URL操作:

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

运行时,会得到以下结果:

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

现在我们走上了正轨。我现在将尝试使用BeautifulSoup解析数据。我的完整代码如下:

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

然后我尝试运行此代码,但遇到以下回溯错误:

  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'

值得注意的是'NoneType' object...行。这意味着我们的目标div不存在!伊加斯,但我为什么要看到下面这些?!

enter image description here

只能有一个解释:表是动态加载的!胡扯。让我们看看能否找到另一个表的源。我研究了一下页面,发现底部有滚动条。这可能意味着表是在一个框架内加载的,或者是直接从另一个源完全加载的,并放在页面的div中。

我刷新页面并再次查看GET请求。对了,我发现了一些有希望的东西:

enter image description here

一个第三方来源的网址,看,它很容易操作使用股票代码!我们试着把它放进一个新的标签页。我们得到的是:

enter image description here

哇!我们现在有了非常准确的数据来源。不过,最后一个障碍是,当我们尝试使用此字符串提取CSCO数据时,它是否有效(请记住,我们使用了CSCO->;AAPL,现在再次返回CSCO,所以您不会感到困惑)。让我们把字符串清理干净,在这里完全抛弃www.dailyfinance.com的角色。我们的新网址如下:

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

让我们试着在最后一个刮刀上使用它!

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()

我们对中信建投(国际)财务比率数据的原始结果如下:

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]

清理数据取决于你。


从这一擦边球中可以学到的一个好教训是,并非所有数据都单独包含在一个页面中。很高兴看到它来自另一个静态站点。如果它是通过JavaScript或AJAX调用等方式生成的,那么我们的方法可能会有一些困难。

希望你能从中学到一些东西。如果有帮助,请告诉我们,祝你好运。

不回答你的具体问题,而是解决你的问题。

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

示例:

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

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

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

要进入财务比率页面,您可以采用以下方法:

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'])

示例:

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

相关问题 更多 >

    热门问题