2014-04-25 16 views
11

Tôi đang cố gắng để cạo http://www.dailyfinance.com/quote/NYSE/international-business-machines/IBM/financial-ratios, nhưng kỹ thuật xây dựng chuỗi url truyền thống không hoạt động vì chuỗi "toàn công ty-tên-được-chèn-trong-đường dẫn". Và chính xác "tên đầy đủ của công ty" không được biết trước. Chỉ có biểu tượng công ty, "IBM" được biết đến.Làm cách nào để tôi đánh lừa các trang bằng URL được tạo động bằng Python?

Về cơ bản, cách tôi xóa bằng cách lặp qua một mảng biểu tượng công ty và xây dựng chuỗi url trước khi gửi đến urllib2.urlopen (url). Nhưng trong trường hợp này, điều đó không thể làm được.

Ví dụ, CSCO chuỗi là

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

và một chuỗi ví dụ url là AAPL:

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

Vì vậy, để có được url, tôi đã phải tìm kiếm các biểu tượng vào hộp nhập liệu trên trang chính:

http://www.dailyfinance.com/ 

Tôi đã nhận thấy rằng khi tôi nhập "CSCO" và kiểm tra đầu vào tìm kiếm tại ()trong tab mạng nhà phát triển web Firefox, tôi nhận thấy rằng yêu cầu get được gửi đến

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

và rằng referer thực sự mang đến cho con đường mà tôi muốn chụp

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 

Xin lỗi vì lời giải thích dài. Vì vậy, câu hỏi là làm cách nào để trích xuất url trong Referer? Nếu điều đó là không thể, tôi nên tiếp cận vấn đề này như thế nào? Có cách nào khác không?

Tôi thực sự đánh giá cao sự trợ giúp của bạn.

+2

+1: * Rất * câu hỏi hay, cho cá nhân tôi. – Manhattan

+0

Có bất kỳ cập nhật nào về điều này không? Bạn đã thấy cách Người giới thiệu được xử lý đúng cách trong câu trả lời của tôi chưa? – Manhattan

Trả lời

22

Tôi thích câu hỏi này. Và vì lý do đó, tôi sẽ đưa ra một câu trả lời rất kỹ lưỡng. Đối với điều này, tôi sẽ sử dụng thư viện yêu cầu yêu thích của tôi cùng với BeautifulSoup4. Chuyển sang Cơ chế nếu bạn thực sự muốn sử dụng tùy thuộc vào bạn. Yêu cầu sẽ giúp bạn tiết kiệm rất nhiều đau đầu.


Trước hết, có thể bạn đang tìm kiếm yêu cầu POST. Tuy nhiên, các yêu cầu POST thường không cần thiết nếu chức năng tìm kiếm mang bạn ngay đến trang bạn đang tìm kiếm. Vì vậy, chúng ta hãy kiểm tra nó, phải không?

Khi tôi truy cập URL cơ sở, http://www.dailyfinance.com/, tôi có thể kiểm tra đơn giản qua công cụ kiểm tra Firebug hoặc Chrome khi tôi đặt CSCO hoặc AAPL trên thanh tìm kiếm và bật "nhảy", có mã trạng thái 301 Moved Permanently . Điều đó có nghĩa là gì?

enter image description here

Trong thuật ngữ đơn giản, tôi đã chuyển nơi nào đó. URL cho yêu cầu GET này là như sau:

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

Bây giờ, chúng tôi thử nghiệm nếu nó hoạt động với AAPL bằng cách sử dụng thao tác URL đơn giản.

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 

Trên đây đưa ra kết quả sau:

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

Xem cách URL của phản ứng thay đổi không? Hãy lấy thao tác URL thêm một bước nữa bằng cách tìm kiếm các trang /financial-ratios bằng cách thêm dưới đây để đoạn code trên:

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

Khi chạy, điều này mang lại là kết quả sau:

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

Bây giờ chúng tôi đi đúng hướng. Bây giờ tôi sẽ cố phân tích dữ liệu bằng cách sử dụng BeautifulSoup. mã hoàn chỉnh của tôi là như sau:

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 

Sau đó tôi cố gắng chạy mã này, chỉ gặp phải một lỗi với traceback sau:

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' 

Đáng chú ý là dòng 'NoneType' object.... Điều này có nghĩa là mục tiêu của chúng tôi div không tồn tại! Egads, nhưng tại sao tôi nhìn thấy sau đây ?!

enter image description here

Chỉ có thể có một lời giải thích: bảng được nạp tự động! Chuột. Hãy xem liệu chúng ta có thể tìm thấy một nguồn khác cho bảng. Tôi nghiên cứu trang và thấy rằng có thanh cuộn ở phía dưới. Điều này có nghĩa là bảng đã được tải bên trong một khung hoặc được tải thẳng từ một nguồn khác hoàn toàn và được đặt vào một trang div.

Tôi làm mới trang và xem lại yêu cầu GET. Bingo, tôi thấy một cái gì đó có vẻ hơi đầy hứa hẹn:

enter image description here

URL nguồn của bên thứ ba, và tìm kiếm, đó là dễ thuyết bằng cách sử dụng biểu tượng ticker! Hãy thử tải nó vào một tab mới. Dưới đây là những gì chúng ta nhận được:

enter image description here

WOW! Bây giờ chúng ta có nguồn dữ liệu chính xác. Rào cản cuối cùng là nó sẽ làm việc khi chúng ta cố gắng kéo dữ liệu CSCO bằng chuỗi này (nhớ chúng ta đã đi CSCO -> AAPL và bây giờ trở lại CSCO một lần nữa, vì vậy bạn không bị nhầm lẫn). Hãy làm sạch chuỗi và mương vai trò của www.dailyfinance.com ở đây hoàn toàn.Url mới của chúng tôi là như sau:

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

Hãy thử sử dụng nó trong công cụ cạo cuối cùng!

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

Và kết quả thô cung cấp dữ liệu chỉ số tài chính CSCO là như sau:

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] 

Dọn dẹp dữ liệu là tùy thuộc vào bạn.


Một bài học tốt để học hỏi từ mẩu tin lưu niệm này không phải là tất cả dữ liệu được chứa trong một trang. Thật tuyệt khi thấy nó đến từ một trang tĩnh khác. Nếu nó được sản xuất thông qua JavaScript hoặc các cuộc gọi AJAX hoặc tương tự, chúng tôi có thể sẽ gặp một số khó khăn với cách tiếp cận của chúng tôi.

Hy vọng rằng bạn đã học được điều gì đó từ điều này. Hãy cho chúng tôi biết nếu điều này giúp và may mắn.

+3

Ồ, bạn là một kẻ lừa đảo trên web (theo nghĩa tốt)! :) Không còn số phiếu bầu nào khác cho ngày hôm nay - sẽ đến và +1 vào ngày mai. – alecxe

+1

@alecxe: Người đàn ông, bạn không biết tôi đã học được bao nhiêu từ bạn. Đến từ bạn, đó là một lời khen lớn. ;) Cảm ơn! – Manhattan

+1

Cảm ơn bạn! Chúng tôi ở đây để học hỏi lẫn nhau. Các câu trả lời chi tiết như vậy thực sự làm cho thế giới giải quyết web tốt hơn. Hy vọng được nghe nhiều hơn từ bạn trong các thẻ có liên quan. – alecxe

2

Không trả lời câu hỏi cụ thể của bạn, nhưng giải quyết được vấn đề của bạn.

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

Ví dụ:

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

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

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

Để đến được trang chỉ tiêu tài chính thì bạn có thể sử dụng một cái gì đó như thế này:

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

Ví dụ:

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

Cảm ơn câu trả lời. Tôi thấy nó hữu ích và rất giáo dục. – vt2424253

Các vấn đề liên quan