2016-06-28 112 views
0

所以我让这个程序让重复性的任务变得更加恼人。这是假设采取一个链接,筛选“下载STV演示”按钮,从该按钮抓取URL并使用它下载。从url下载文件工作正常,我只是无法打开网址。它将从stackoverflow下载,而不是我想要的网站。我得到了403 Forbidden错误。任何人都有想法,如何得到这个工作http://sizzlingstats.com/stats/479453,也为该下载stv按钮过滤?使用Python 2.7从网页获取下载链接

import random, sys, urllib2, httplib2, win32clipboard, requests, urlparse 
from copy import deepcopy 
from bs4 import SoupStrainer 
from bs4 import BeautifulSoup 
from urllib2 import Request 
from urllib2 import urlopen 
#When I wrote this, only God and I knew what I was writing 
#Now only God knows 

page = raw_input("Please copy the .ss link and hit enter... ") 
win32clipboard.OpenClipboard() 
page = win32clipboard.GetClipboardData() 
win32clipboard.CloseClipboard() 
s = page 
try: 
    page = s.replace("http://","http://www.") 
    print page + " Found..." 
except: 
    page = s.replace("www.","http://www.") 
    print page 

req = urllib2.Request(page, '', headers = { 'User-Agent' : 'Mozilla/5.0' }) 
req.headers['User-agent'] = 'Mozilla/5.0' 
req.add_header('User-agent', 'Mozilla/5.0') 
print req 
soup = BeautifulSoup(page, 'html.parser') 
print soup.prettify() 
links = soup.find_all("Download STV Demo") 
for tag in links: 
    link = links.get('href',None) 
    if "Download STV Demo" in link: 
     print link 

file_name = page.split('/')[-1] 
u = urllib2.urlopen(page) 
f = open(file_name, 'wb') 
meta = u.info() 
file_size = int(meta.getheaders("Content-Length")[0]) 
print "Downloading: %s Bytes: %s" % (file_name, file_size) 

file_size_dl = 0 
block_sz = 8192 
while True: 
    buffer = u.read(block_sz) 
    if not buffer: 
     break 
    file_size_dl += len(buffer) 
    f.write(buffer) 
    status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100./file_size) 
    status = status + chr(8)*(len(status)+1) 
    print status, 
f.close() 
+0

您需要添加一个用户代理,你为什么要传递的raw_input输出到BS4? –

+0

我有一个用户代理,并且来自原始输入的页面被快速覆盖。但我会删除,因为它不需要 –

+0

无论如何,它是无关紧要的,因为页面内容是动态创建的。查看chrome开发工具的xhr选项卡下的内容,您可以获取所需的所有json格式的数据。 –

回答

0

该页面的内容是通过Javascript从API动态生成的。

>>> import requests 
>>> 
>>> requests.get('http://sizzlingstats.com/api/stats/479453').json()['stats']['stvUrl'] 
u'http://sizzlingstv.s3.amazonaws.com/stv/479453.zip' 

因为他们阻止了用户代理,所以你得到了403。

您已经使用用户代理创建了req对象,但是您不使用它,而是使用urllib2.urlopen(page)代替。

您还将page传递给BeautifulSoup,这是一个错误。

soup = BeautifulSoup(page, 'html.parser') 
1

让我们看一下你的代码: 首先要导入你不使用(也许这不是孔代码)很多模块和其他一些人使用,但你不会需要他们,其实你只需要:

from urllib2 import urlopen 

(后面我们会看到为什么),也许win32clipboard你的投入,你的投入是确定的,所以我会离开的这部分代码:

import win32clipboard 
page = input("Please copy the .ss link and hit enter... ") 
win32clipboard.OpenClipboard() 
page = win32clipboard.GetClipboardData() 
win32clipboard.CloseClipboard() 

但我真的d on't看到这些类型的输入的目的,是不是容易,只需使用类似:

page = raw_input("Please enter the .ss link: ") 

那么这部分代码实际上是不必要的:

s = page 
try:            
    page = s.replace("http://","http://www.") 
    print page + " Found..."     
except:            
    page = s.replace("www.","http://www.")  
    print page 

所以我就删除它,接下来的部分应该是这样的:

from urllib2 import Request, urlopen 
from bs4 import BeautifulSoup 
req = Request(page, headers = { 'User-Agent' : 'Mozilla/5.0' }) 
#req.headers['User-agent'] = 'Mozilla/5.0'  # you don't need this 
#req.add_header('User-agent', 'Mozilla/5.0') # you don't need this 
print req 
html = urlopen(req)  #you need to open page with urlopen before using BeautifulSoup 
# it is to fix this error: 
##  UserWarning: "b'http://www.sizzlingstats.com/stats/479453'" looks like a URL. 
##  Beautiful Soup is not an HTTP client. You should probably use an HTTP client 
##  to get the document behind the URL, and feed that document to Beautiful Soup. 
soup = BeautifulSoup(html, 'html.parser') # variable page changed to html 
# print soup.prettify()   # I commented this because you don't need to print html 
           # but if you want to see that it's work just uncomment it 

我不会使用此代码,我会解释为什么,但是但是如果你需要用刮某些其它BeautifulSoup页面,那么你可以使用它。

你并不需要它,因为这部分的:

links = soup.find_all("Download STV Demo") 

,所以这个问题是没有在HTML代码“下载STV演示”,至少不会在汤的HTML代码,因为页面是由JavaScript创建的,所以你要找到任何链接,你可以用print(links)看到links == [],正因为如此,你也不需要就此别过:

for tag in links:      
    link = links.get('href',None)  like I said there is no use of this 
    if "Download STV Demo" in link: because variable links is empty list 
     print link 

所以就像我说的网页的一部分,这里是连接我们需要的是用JavaScript创建,所以你可以刮脚本找到它,但它是很多更难做到这一点,但如果你看的网址,我们正在努力寻找它看起来像这样:

http://sizzlingstv.s3.amazonaws.com/stv/479453.zip

所以现在看网址你有,它看起来像这样:

http://sizzlingstats.com/stats/479453

得到这个链接http://sizzlingstv.s3.amazonaws.com/stv/479453.zip你只需要找到链接的最后部分,在这种情况下,它是479453,你有它,你的链接(http://sizzlingstats.com/stats/479453),这也就是它的最后一部分。你甚至使用该号码作为file_name。下面是代码正是这么做的:在那之后我会复制一些代码的

file_name = page.split('/')[-1] 
download_link = 'http://sizzlingstv.s3.amazonaws.com/stv/' + file_name + '.zip' 

u = urlopen(download_link) 
meta = u.info()  
file_size = int(meta.getheaders("Content-Length")[0]) 
print "Downloading: %s Bytes: %s" % (file_name, file_size) 

这部分如下工作:

f = open(file_name + '.zip', 'wb') # I added '.zip' 
file_size_dl = 0 
block_sz = 8192 
while True: 
    buffer = u.read(block_sz) 
    if not buffer: 
     break 
    file_size_dl += len(buffer) 
    f.write(buffer) 
    status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100./file_size) 
    status = status + chr(8)*(len(status)+1) 
    print status 
f.close() 

,也许你想看到下载消息,但我认为它更容易使用:

f = open(file_name + '.zip', 'wb') 
f.write(u.read()) 
print "Downloaded" 
f.close() 

这里只是代码:

from urllib2 import urlopen 

import win32clipboard 
page = input("Please copy the .ss link and hit enter... ") 
win32clipboard.OpenClipboard() 
page = win32clipboard.GetClipboardData() 
win32clipboard.CloseClipboard() 

# or use: 
# page = raw_input("Please enter the .ss link: ") 

file_name = page.split('/')[-1] 
download_link = 'http://sizzlingstv.s3.amazonaws.com/stv/' + file_name + '.zip' 
u = urlopen(download_link) 
meta = u.info()  
file_size = int(meta.getheaders("Content-Length")[0]) 
print "Downloading: %s Bytes: %s" % (file_name, file_size) 

f = open(file_name + '.zip', 'wb') # I added '.zip' 
file_size_dl = 0 
block_sz = 8192 
while True: 
    buffer = u.read(block_sz) 
    if not buffer: 
     break 
    file_size_dl += len(buffer) 
    f.write(buffer) 
    status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100./file_size) 
    status = status + chr(8)*(len(status)+1) 
    print(status) 
f.close() 

# or use: 
##f = open(file_name + '.zip', 'wb') 
##f.write(u.read()) 
##print "Downloaded" 
##f.close() 
+0

很遗憾,在没有评论的情况下看到类似这样的答案。还有一点可以证明,OP没有接受你的答案,或者高估了答案。感谢您的努力和详细的解释。 – xverges