- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试抓取 http://www.dailyfinance.com/quote/NYSE/international-business-machines/IBM/financial-ratios ,但传统的 url 字符串构建技术不起作用,因为“完整的公司名称被插入到路径中”字符串。并且事先不知道确切的“公司全名”。只有公司标志“IBM”为人所知。
基本上,我抓取的方式是循环遍历公司符号数组并在将其发送到 urllib2.urlopen(url) 之前构建 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 处的搜索输入时,我注意到获取请求正在发送到
http://j.foolcdn.com/tmf/predictivesearch?callback=_predictiveSearch_csco&term=csco&domain=dailyfinance.com
并且 referer 实际上给出了我想要捕获的路径
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?如果那不可能,我应该如何解决这个问题?还有别的办法吗?
非常感谢您的帮助。
最佳答案
我喜欢这个问题。因此,我会给出一个非常彻底的答案。为此,我将使用我最喜欢的 Requests 库和 BeautifulSoup4。如果您真的想使用它,则移植到 Mechanize 取决于您。不过,请求会让你省去很多麻烦。
首先,您可能正在寻找 POST 请求。但是,如果搜索功能将您立即带到您要查找的页面,则通常不需要 POST 请求。那么让我们检查一下,好吗?
当我登陆基本 URL http://www.dailyfinance.com/
时,我可以通过 Firebug 或 Chrome 的检查工具进行简单检查,当我将 CSCO 或 AAPL 放在搜索栏并启用“跳转”,有一个 301 Moved Permanently
状态代码。这是什么意思?
简单来说,我被转移到某个地方。此 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
不存在!哎呀,但为什么我会看到以下内容?!
只能有一种解释:表是动态加载的!老鼠。让我们看看是否可以找到该表的另一个来源。我研究了页面,发现底部有滚动条。这可能意味着表格是在框架内加载的,或者是完全从另一个来源直接加载并放置在页面的 div
中的。
我刷新页面并再次查看 GET 请求。宾果游戏,我发现了一些看起来很有希望的东西:
第三方源 URL,看,使用股票代码可以轻松操纵它!让我们尝试将其加载到新选项卡中。这是我们得到的:
哇!我们现在有了非常准确的数据来源。最后一个障碍是,当我们尝试使用此字符串提取 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()
我们对 CSCO 财务比率数据的原始结果如下:
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 调用等生成的,我们的方法可能会遇到一些困难。
希望你能从中学到一些东西。让我们知道这是否有帮助,祝您好运。
关于python - 如何使用 Python 抓取具有动态生成的 URL 的页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23302676/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!