2010-10-21 37 views
1

我使用Bing API編寫了Python 2.6中的網絡爬蟲,該API搜索特定文檔,然後將其下載以供以後進行分類。我一直在使用字符串的方法和urllib.urlretrieve()下載結果,其URL以.pdf,.PS等結束,但我碰到麻煩時,該文件是「隱藏」的URL後面,如:使用Python下載URL中未明確引用的文檔

http://www.oecd.org/officialdocuments/displaydocument/?cote=STD/CSTAT/WPNA(2008)25&docLanguage=En

所以,有兩個問題。有沒有一種方法可以判斷一個URL是否有一個pdf/doc等文件,如果它沒有明確地這樣做(如www.domain.com/file.pdf),它就會鏈接到它?有沒有辦法讓Python截獲該文件?

編輯: 感謝您的回覆,其中幾個建議下載文件,看它是否是正確的類型。唯一的問題是......我不知道該怎麼做(參見上面的問題#2)。 urlretrieve(<above url>)只給出一個包含相同url的href文件。

+0

我一直在尋找到這樣的事情我自己。我使用os.system()來調用「curl -I url」並通過頭部結果進行解析以獲得我所需的內容。 – MRR0GERS 2010-10-21 15:18:47

回答

3

在這種情況下,你指的是什麼「這不是明確URL引用文檔」似乎是所謂的「重定向」。基本上,服務器告訴你,你必須在另一個URL獲取文檔。通常,python的urllib會自動遵循這些重定向,以便最終獲得正確的文件。 (和 - 正如其他人已經提到的 - 你可以檢查響應的MIME類型標題,看看它是否是PDF)。

但是,有問題的服務器在這裏做了一些奇怪的事情。您請求網址,並將您重定向到另一個網址。您請求其他網址,然後將您重新導向至同一個網址!再次......再一次......在某個時候,urllib已經決定這已經足夠了,並且會在重定向之後停止,以避免陷入無限循環。

那麼,當你使用瀏覽器時你怎麼能夠得到pdf?因爲顯然,如果您啓用了cookie,服務器將只提供pdf。 (爲什麼?你必須詢問負責服務器的人員......)如果你沒有cookie,它會一直持續地重定向你。

(檢查urllib2cookielib模塊,以獲得支持Cookies,this tutorial可能幫助)

至少,這是我認爲是造成問題的原因。我還沒有嘗試過使用Cookie來做這件事。也可能是因爲服務器檢測到你沒有使用「普通」瀏覽器(在這種情況下你可能需要擺弄User-Agent頭),服務器並不是「想要」爲pdf提供服務,但它將是一個奇怪的做法。所以我的猜測是,它在某個地方使用「會話cookie」,如果你還沒有一個,還是繼續嘗試重定向。

+0

Cookie理論已得到確認:禁止在Firefox中爲該網站使用Cookie例如,然後請求該URL給出「重定向循環」錯誤(甚至暗示它可能是由於不接受cookie而引起的) – Steven 2010-10-21 18:06:08

+0

非常豐富,謝謝! – JonC 2010-10-21 22:39:41

0

不可能僅僅通過查看就知道URL引用了哪種資源。服務器完全取決於您在請求某個URL時所提供的內容。

8

沒有辦法從網址告訴你它會給你什麼。即使它在.pdf結束它仍然可以給你HTML或任何它喜歡的東西。

你可以做一個HEAD請求並查看內容類型,如果服務器沒有對你說謊,它會告訴你它是否是PDF。

或者,您可以下載它,然後計算出您是否是PDF。

+0

感謝您的回覆。對於上面的URL,內容類型以text/html形式返回,儘管它間接地指向了.pdf。並下載它只給出一個HTML文件與href到相同的URL ...任何想法? – JonC 2010-10-21 15:33:19

+0

在沒有文件擴展名或僞文件擴展名,Python 3.X和Web應用程序的情況下檢查我的答案http://stackoverflow.com/a/39356849/1209842 – 2016-09-06 20:06:49

0

urllib.info()函數檢查mimetype。這可能不是100%準確的,它確實取決於網站作爲Content-Type標頭返回的內容。如果表現良好,它會返回適當的MIME類型。

PDF應該返回application/pdf,但可能並非如此。

否則,你可能只需要下載並嘗試它。

0

您無法直接從網址中看到它。您可以嘗試僅下載HTTP響應的標題並查找Content-Type標題。但是,您必須相信服務器 - 它可能會響應錯誤的內容類型標頭,而不匹配正文中提供的數據。

2

如前所述,無法通過URL告知內容類型。但是,如果你不介意的標題爲每個網址,你可以這樣做:

obj = urllib.urlopen(URL) 

headers = obj.info() 
if headers['Content-Type'].find('pdf') != -1: 
    # we have pdf file, download whole 
... 

這樣你就不必下載每個URL只是它的頭。它仍然不是完全節省網絡流量,但你不會比這更好。

而且你應該使用的,而不是我的粗查找(「PDF」)MIME類型。

0

在Python 3.x中檢測文件類型,並將帶有url的webapp檢測到不能有擴展名或假擴展名的文件。你應該安裝python-魔法,使用

pip3 install python-magic 

對於Mac OS X,您還應該安裝libmagic使用

brew install libmagic 

代碼片斷

import urllib 
import magic 
from urllib.request import urlopen 

url = "http://...url to the file ..." 
request = urllib.request.Request(url) 
response = urlopen(request) 
mime_type = magic.from_buffer(response.read()) 
print(mime_type)