1

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

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 对象仍然无法正确加载。有谁知道这是否可以解决?

4

2 回答 2

1

虽然我试图只使 html 文件脱机,同时使用网络上的链接资源。

这是一个两步过程:

  1. 复制 HTML 文件并将其保存到本地目录。
  2. 在该部分中添加一个BASE标签,并将其属性指向绝对 URL。HEADhref

既然你想自己学习如何做,我就这样吧。

于 2013-03-31T05:38:53.823 回答
0

@Burhan 使用<base href="...">中的标签有一个简单的答案<head>,它可以按照您的发现工作。我运行了您发布的脚本,并且页面下载正常。正如您所注意到的,一些 JavaScript 现在失败了。这可能有多种原因。

如果您将 HTML 文件作为本地file:///URL 打开,该页面可能无法正常工作。许多浏览器对本地 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,则没有简单的方法可以解决这个问题。

于 2013-04-17T00:51:39.397 回答