2016-01-06 24 views
5

.xlsまたは.xlsxまたは.csvをすべてこのWebサイトから指定のフォルダにダウンロードします。PythonとBeautifulSoupを使ってWebページから.xlsファイルをダウンロード

https://www.rbi.org.in/Scripts/bs_viewcontent.aspx?Id=2009 

私はurllib2のなどMechanizeのは、Python 3では動作しませんMechanizeの、美しいスープの中に見ている、urllib2のもPythonの3で問題を抱えていた、私はこの問題を回避するために見えたが、私はできませんでした。だから、私は現在、美しいスープを使って動作させようとしています。

私はいくつかのサンプルコードを見つけ、次のように、私の問題に合わせて、それを修正しようとした -

from bs4 import BeautifulSoup 
# Python 3.x 
from urllib.request import urlopen, urlretrieve, quote 
from urllib.parse import urljoin 

url = 'https://www.rbi.org.in/Scripts/bs_viewcontent.aspx?Id=2009/' 
u = urlopen(url) 
try: 
    html = u.read().decode('utf-8') 
finally: 
    u.close() 

soup = BeautifulSoup(html) 
for link in soup.select('div[webpartid] a'): 
    href = link.get('href') 
    if href.startswith('javascript:'): 
     continue 
    filename = href.rsplit('/', 1)[-1] 
    href = urljoin(url, quote(href)) 
    try: 
     urlretrieve(href, filename) 
    except: 
     print('failed to download') 

しかし、実行時にこのコードは、ターゲット・ページ、また出力、エラーメッセージからファイルを抽出しません。 (例えば、「ダウンロードに失敗しました」など)。

  • BeautifulSoupを使用してページからExcelファイルを選択するにはどうすればよいですか?
  • これらのファイルをPythonを使用してローカルファイルにダウンロードするにはどうすればよいですか?それはスタンドとしてあなたのスクリプトで
+0

あなたのコードがどのように "うまくいかなかった"と記述できますか?投稿されたコードは間違ってインデントされているため、まったく実行されません。 – mfitzp

+0

コードはたまに実行されましたが、決してファイルを作成しませんでした。インデントについては、私はポストしながら私はそれを甘やかす必要がありますが、コードを実行したときに私はインデントを世話したことを安心しなければならないことを謝ります –

+1

私はこの問題のために働く解決策を持っています。私はそれを要点としてここに掲載しています。https://gist.github.com/mfitzp/29522e2ac4057bf01745 – mfitzp

答えて

2

問題は、次のとおりです。

  1. urlは、あなたがダウンロードしたいファイルをリストではない、要求されたときに、無効なページを与える末尾/を持っています。
  2. soup.select(...)のCSSセレクタが、webpartidの属性を持つdivを選択していますが、これはリンクされたドキュメントのどこにも存在しません。
  3. リンクがページ内で絶対URLとして指定されており、引用符を付ける必要はありませんが、URLに参加して引用しています。
  4. try:...except:ブロックでは、ファイルをダウンロードしようとしたときに生成されたエラーが表示されなくなります。特定の例外を除いてブロックexceptを使用することは悪い習慣であり、避けるべきです。次のよう

正しいファイルを取得し、それらをダウンロードしようとすることをあなたのコードの修正版は次のとおりです。

from bs4 import BeautifulSoup 
# Python 3.x 
from urllib.request import urlopen, urlretrieve, quote 
from urllib.parse import urljoin 

# Remove the trailing/you had, as that gives a 404 page 
url = 'https://www.rbi.org.in/Scripts/bs_viewcontent.aspx?Id=2009' 
u = urlopen(url) 
try: 
    html = u.read().decode('utf-8') 
finally: 
    u.close() 

soup = BeautifulSoup(html, "html.parser") 

# Select all A elements with href attributes containing URLs starting with http:// 
for link in soup.select('a[href^="http://"]'): 
    href = link.get('href') 

    # Make sure it has one of the correct extensions 
    if not any(href.endswith(x) for x in ['.csv','.xls','.xlsx']): 
     continue 

    filename = href.rsplit('/', 1)[-1] 
    print("Downloading %s to %s..." % (href, filename)) 
    urlretrieve(href, filename) 
    print("Done.") 

ただし、これを実行する場合は、そのurllib.error.HTTPError: HTTP Error 403: Forbidden例外に気付くでしょうファイルがブラウザでダウンロード可能であってもスローされます。 最初はこれが紹介のチェック(ホットリンクを防ぐ)だと思っていましたが、ブラウザのリクエスト(Chromeデベロッパーツールなど)で見ると の最初のhttp://リクエストがブロックされていることがわかります同じファイルに対してhttps://要求を試みます。

言い換えれば、リクエストはHTTPSを経由して(ページ内のURLに関係なく)動作する必要があります。これを解決するには、リクエストのURLを使用する前にhttp:https:に書き直す必要があります。次のコードは、URLを正しく変更してファイルをダウンロードします。私もos.path.joinを使用して、ファイル名に付加された出力フォルダを指定する変数、コメントを追加しました:

import os 
from bs4 import BeautifulSoup 
# Python 3.x 
from urllib.request import urlopen, urlretrieve 

URL = 'https://www.rbi.org.in/Scripts/bs_viewcontent.aspx?Id=2009' 
OUTPUT_DIR = '' # path to output folder, '.' or '' uses current folder 

u = urlopen(URL) 
try: 
    html = u.read().decode('utf-8') 
finally: 
    u.close() 

soup = BeautifulSoup(html, "html.parser") 
for link in soup.select('a[href^="http://"]'): 
    href = link.get('href') 
    if not any(href.endswith(x) for x in ['.csv','.xls','.xlsx']): 
     continue 

    filename = os.path.join(OUTPUT_DIR, href.rsplit('/', 1)[-1]) 

    # We need a https:// URL for this site 
    href = href.replace('http://','https://') 

    print("Downloading %s to %s..." % (href, filename)) 
    urlretrieve(href, filename) 
    print("Done.") 
+0

美しく説明すると、私は学ぶことが大変です。私はあなたにとても感謝しています。 –

1

を私はrequestsBeautifulSoup4を使用して、これは良い実施例であることが判明し、Python用wgetモジュール2.7:

import requests 
import wget 
import os 

from bs4 import BeautifulSoup, SoupStrainer 

url = 'https://www.rbi.org.in/Scripts/bs_viewcontent.aspx?Id=2009' 

file_types = ['.xls', '.xlsx', '.csv'] 

for file_type in file_types: 

    response = requests.get(url) 

    for link in BeautifulSoup(response.content, 'html.parser', parse_only=SoupStrainer('a')): 
     if link.has_attr('href'): 
      if file_type in link['href']: 
       full_path = url + link['href'] 
       wget.download(full_path) 
1
i tried above code still giving me urllib.error.HTTPError: HTTP Error 403: Forbidden 


Also tried by adding user agents my modified code 


import os 

from bs4 import BeautifulSoup 
# Python 3.x 
from urllib.request import Request,urlopen, urlretrieve 

headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} 
URL = Request('https://www.rbi.org.in/scripts/bs_viewcontent.aspx?Id=2009', headers=headers) 

#URL = 'https://www.rbi.org.in/scripts/bs_viewcontent.aspx?Id=2009' 

OUTPUT_DIR = 'E:\python\out' # path to output folder, '.' or '' uses current folder 

u = urlopen(URL) 
try: 
    html = u.read().decode('utf-8') 
finally: 
    u.close() 

soup = BeautifulSoup(html, "html.parser") 
for link in soup.select('a[href^="http://"]'): 
    href = link.get('href') 
    if not any(href.endswith(x) for x in ['.csv','.xls','.xlsx']): 
     continue 

    filename = os.path.join(OUTPUT_DIR, href.rsplit('/', 1)[-1]) 

    # We need a https:// URL for this site 
    href = href.replace('http://','https://') 

    print("Downloading %s to %s..." % (href, filename)) 
    urlretrieve(href, filename) 
    print("Done.") 
0

これはのpython3

import os 
import urllib 

from bs4 import BeautifulSoup 
# Python 3.x 
from urllib.request import urlopen, urlretrieve 
from urllib.error import HTTPError 

URL = 'https://www.rbi.org.in/Scripts/bs_viewcontent.aspx?Id=2009' 
OUTPUT_DIR = '' # path to output folder, '.' or '' uses current folder 

u = urlopen(URL) 
try: 
    html = u.read().decode('utf-8') 
finally: 
    u.close() 

soup = BeautifulSoup(html, "html.parser") 
for link in soup.select('a[href^="http://"]'): 
    href = link.get('href') 
if not any(href.endswith(x) for x in ['.csv','.xls','.xlsx']): 
    continue 

filename = os.path.join(OUTPUT_DIR, href.rsplit('/', 1)[-1]) 

# We need a https:// URL for this site 
href = href.replace('http://','https://') 

try: 
    print("Downloading %s to %s..." % (href, filename)) 
    urlretrieve(href, filename) 
    print("Done.") 
except urllib.error.HTTPError as err: 
    if err.code == 404: 
     continue 
を使用して...私のために最高の仕事を
関連する問題