脚本拉动HTML并完全去相关它。 (单个文件离线)

时间:2013-03-25 01:19:10

标签: python parsing web-applications web lxml

我正在尝试学习python并创建一个Web实用程序。我想要完成的一项任务是创建一个可以在本地运行的单个html文件,但链接到它需要看起来像原始网页的所有内容。 (如果你要问为什么我想要这个,那是因为它可能是我正在创造的实用工具的一部分,或者如果没有,仅仅用于教育)所以我有两个问题,理论问题和实际问题: / p>

1)对于视觉(与功能相反)的目的,这是否可能?一个html页面可以脱机工作,同时链接到它在线所需的一切吗?或者如果他们的基本知识是让html文件本身在Web服务器上执行而不允许这样做?我能走多远?

2)我已经启动了一个python脚本,该脚本在html页面上去相关(将其中一个)链接元素,但我是一个菜鸟,所以我很可能错过了一些元素或属性,这些元素或属性也会链接到外部资源。我注意到在尝试几页后,下面的代码中的一个不能正常工作,它们似乎是一个没有正确链接的.js文件。 (即将出现的许多问题中的第一个)假设我的第一个问题的答案至少是部分答案,是否有人可以帮我修复本网站的代码?

谢谢。

更新,我错过了这个脚本标签,但即使我添加它之后仍然无法正常工作。

import lxml
import sys
from lxml import etree
from StringIO import StringIO
from lxml.html import fromstring, tostring
import urllib2
from urlparse import urljoin

site = "www.script-tutorials.com/advance-php-login-system-tutorial/"
output_filename = "output.html"

def download(site):
    response = urllib2.urlopen("http://"+site)
    html_input = response.read()
    return html_input

def derealitivise(site, html_input):

    active_html = lxml.html.fromstring(html_input)

    for element in tags_to_derealitivise:

        for tag in active_html.xpath(str(element+"[@"+"src"+"]")):
            tag.attrib["src"] = urljoin("http://"+site, tag.attrib.get("src"))

        for tag in active_html.xpath(str(element+"[@"+"href"+"]")):
            tag.attrib["href"] = urljoin("http://"+site, tag.attrib.get("href"))

    return lxml.html.tostring(active_html)

active_html = ""
tags_to_derealitivise = ("//img", "//a", "//link", "//embed", "//audio", "//video", "//script")

print "downloading..."
active_html = download(site)

active_html = derealitivise(site, active_html)

print "writing file..."

output_file = open (output_filename, "w")
output_file.write(active_html)
output_file.close() 

此外,我可以通过检查所有元素来使代码更加完整......

看起来有点像这样,但我不知道迭代所有元素的确切方法。这是一个单独的问题,我很可能会在任何人回应时弄清楚......:

def derealitivise(site, html_input):

active_html = lxml.html.fromstring(html_input)

for element in active_html.xpath:

    for tag in active_html.xpath(str(element+"[@"+"src"+"]")):
        tag.attrib["src"] = urljoin("http://"+site, tag.attrib.get("src"))

    for tag in active_html.xpath(str(element+"[@"+"href"+"]")):
        tag.attrib["href"] = urljoin("http://"+site, tag.attrib.get("href"))

return lxml.html.tostring(active_html)

更新

感谢Burhan Khalid的解决方案,这看起来太简单了,乍一看不太可行,我让它发挥作用。代码非常简单,大多数人很可能不会要求它,但无论如何我都会发布它有帮助:

import lxml
import sys
from lxml import etree
from StringIO import StringIO
from lxml.html import fromstring, tostring
import urllib2
from urlparse import urljoin

site = "www.script-tutorials.com/advance-php-login-system-tutorial/"
output_filename = "output.html"

def download(site):
    response = urllib2.urlopen(site)
    html_input = response.read()
    return html_input

def derealitivise(site, html_input):

    active_html = html_input.replace('<head>', '<head> <base href='+site+'>')

    return active_html
active_html = ""


print "downloading..."
active_html = download(site)

active_html = derealitivise(site, active_html)

print "writing file..."

output_file = open (output_filename, "w")
output_file.write(active_html)
output_file.close()

尽管如此,并且它非常简单,我在脚本中列出的网站上运行的.js对象仍然无法正确加载。有谁知道这是否可以解决?

2 个答案:

答案 0 :(得分:1)

  

而我正在尝试使html文件脱机,同时使用   通过网络链接资源。

这是一个两步过程:

  1. 复制HTML文件并将其保存到本地目录。
  2. HEAD部分添加BASE标记,并将其href属性指向绝对网址。
  3. 既然你想学习如何自己动手,我会留下它。

答案 1 :(得分:0)

@Burhan在<base href="...">中使用<head>标记可以轻松回答,并且您可以找到它。我运行了你发布的脚本,页面下载得很好。正如您所注意到的,现在有些JavaScript失败了。这可能有多种原因。

如果您要将HTML文件作为本地file:///网址打开,该页面可能无效。许多浏览器严重沙箱本地HTML文件,不允许它们执行网络请求或检查本地文件。

该页面可能会对远程站点执行XmlHTTPRequests或其他网络操作,由于跨域脚本原因,这些操作将被拒绝。查看JS控制台,我发现您发布的脚本存在以下错误:

XMLHttpRequest cannot load http://www.script-tutorials.com/menus.php?give=menu. Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin.

不幸的是,如果您无法控制www.script-tutorials.com,那么就没有简单的方法。