Python中相当于wget的下载网站及资源的工具
2.5年前在用Python下载网页及其所有资源文件这个问题上也有人问过类似的事情,但没有得到答案,而且“请查看相关主题”其实并不是在问同样的问题。
我想下载一个页面上的所有内容,这样就可以仅通过文件来查看它。
这个命令
wget --page-requisites --domains=DOMAIN --no-parent --html-extension --convert-links --restrict-file-names=windows
正好满足我的需求。不过我们希望能把它和其他需要便携的东西结合起来,所以需要用Python来实现。
我一直在研究Beautiful Soup、scrapy,还有一些网上发布的爬虫,但这些工具似乎都是以聪明但特定的方式来获取数据或链接。用它们来实现我想要的功能,感觉会需要花很多功夫去找所有的资源,我相信一定有更简单的方法。
非常感谢!
2 个回答
2
我的同事写了这段代码,很多部分是从其他地方拼凑过来的。我觉得可能有些特别的地方是为了我们自己的系统,但这段代码应该能帮助任何想做同样事情的人。
"""
Downloads all links from a specified location and saves to machine.
Downloaded links will only be of a lower level then links specified.
To use: python downloader.py link
"""
import sys,re,os,urllib2,urllib,urlparse
tocrawl = set([sys.argv[1]])
# linkregex = re.compile('<a\s*href=[\'|"](.*?)[\'"].*?')
linkregex = re.compile('href=[\'|"](.*?)[\'"].*?')
linksrc = re.compile('src=[\'|"](.*?)[\'"].*?')
def main():
link_list = []##create a list of all found links so there are no duplicates
restrict = sys.argv[1]##used to restrict found links to only have lower level
link_list.append(restrict)
parent_folder = restrict.rfind('/', 0, len(restrict)-1)
##a.com/b/c/d/ make /d/ as parent folder
while 1:
try:
crawling = tocrawl.pop()
#print crawling
except KeyError:
break
url = urlparse.urlparse(crawling)##splits url into sections
try:
response = urllib2.urlopen(crawling)##try to open the url
except:
continue
msg = response.read()##save source of url
links = linkregex.findall(msg)##search for all href in source
links = links + linksrc.findall(msg)##search for all src in source
for link in (links.pop(0) for _ in xrange(len(links))):
if link.startswith('/'):
##if /xxx a.com/b/c/ -> a.com/b/c/xxx
link = 'http://' + url[1] + link
elif ~link.find('#'):
continue
elif link.startswith('../'):
if link.find('../../'):##only use links that are max 1 level above reference
##if ../xxx.html a.com/b/c/d.html -> a.com/b/xxx.html
parent_pos = url[2].rfind('/')
parent_pos = url[2].rfind('/', 0, parent_pos-2) + 1
parent_url = url[2][:parent_pos]
new_link = link.find('/')+1
link = link[new_link:]
link = 'http://' + url[1] + parent_url + link
else:
continue
elif not link.startswith('http'):
if url[2].find('.html'):
##if xxx.html a.com/b/c/d.html -> a.com/b/c/xxx.html
a = url[2].rfind('/')+1
parent = url[2][:a]
link = 'http://' + url[1] + parent + link
else:
##if xxx.html a.com/b/c/ -> a.com/b/c/xxx.html
link = 'http://' + url[1] + url[2] + link
if link not in link_list:
link_list.append(link)##add link to list of already found links
if (~link.find(restrict)):
##only grab links which are below input site
print link ##print downloaded link
tocrawl.add(link)##add link to pending view links
file_name = link[parent_folder+1:]##folder structure for files to be saved
filename = file_name.rfind('/')
folder = file_name[:filename]##creates folder names
folder = os.path.abspath(folder)##creates folder path
if not os.path.exists(folder):
os.makedirs(folder)##make folder if it does not exist
try:
urllib.urlretrieve(link, file_name)##download the link
except:
print "could not download %s"%link
else:
continue
if __name__ == "__main__":
main()
谢谢大家的回复。
3
你应该使用合适的工具来完成手头的工作。
如果你想抓取一个网站并把页面保存到电脑上,Python可能不是最好的选择。开源项目通常是在有人需要某个功能时才会添加这个功能,而因为wget
这个工具做得非常好,所以没有人去费心写一个Python库来替代它。
考虑到wget几乎可以在任何有Python解释器的平台上运行,你有没有什么理由不能使用wget呢?