对不起菜鸟问题。我想知道在python中是否有一个有效的url opener类来处理重定向。我目前正在使用简单的urllib.urlopen(),但它不起作用。这是一个例子:
http://thetechshowdown.com/Redirect4.php
对于此网址,我使用的类不遵循重定向:
并且只显示:
"您将被自动重定向到B& H.
Page Stuck?点击这里。"
提前致谢。
答案 0 :(得分:4)
使用模块requests
- 它将重定向视为默认值。
但是页面可以通过javascript重定向,因此没有任何模块会遵循这种重定向。
在浏览器中关闭javascript并转到http://thetechshowdown.com/Redirect4.php
以查看是否将您重定向到其他页面
我查看了此页面 - 有javascript重定向和HTML重定向(标记为"刷新"参数)。两者都不是由服务器发送的正常重定向 - 因此任何模块都不会遵循此重定向。您必须阅读页面,在代码中找到网址并与该网址连接。
import requests
import lxml, lxml.html
# started page
r = requests.get('http://thetechshowdown.com/Redirect4.php')
#print r.url
#print r.history
#print r.text
# first redirection
html = lxml.html.fromstring(r.text)
refresh = html.cssselect('meta[http-equiv="refresh"]')
if refresh:
print 'refresh:', refresh[0].attrib['content']
x = refresh[0].attrib['content'].find('http')
url = refresh[0].attrib['content'][x:]
print 'url:', url
r = requests.get(url)
#print r.text
# second redirection
html = lxml.html.fromstring(r.text)
refresh = html.cssselect('meta[http-equiv="refresh"]')
if refresh:
print 'refresh:', refresh[0].attrib['content']
x = refresh[0].attrib['content'].find('http')
url = refresh[0].attrib['content'][x:]
print 'url:', url
r = requests.get(url)
# final page
print r.text
答案 1 :(得分:0)
因为软重定向而发生这种情况。 urllib
未遵循重定向,因为它不会识别它们。实际上,会发布HTTP响应代码200(找到的页面),并且会在浏览器中通过某种副作用进行重定向。
第一页有HTTP响应代码200,但包含以下内容:
<meta http-equiv="refresh" content="1; url=http://fave.co/1idiTuz">
指示浏览器关注该链接。第二个资源向另一个资源发出HTTP响应代码301或302(重定向),其中发生第二次软重定向,这次使用Javascript:
<script type="text/javascript">
setTimeout(function () {window.location.replace(\'http://bhphotovideo.com\');}, 2.75 * 1000);
</script>
<noscript>
<meta http-equiv="refresh" content="2.75;http://bhphotovideo.com" />
</noscript>
不幸的是,您必须手动提取网址。但是,这并不困难。这是代码:
from lxml.html import parse
from urllib import urlopen
from contextlib import closing
def follow(url):
"""Follow both true and soft redirects."""
while True:
with closing(urlopen(url)) as stream:
next = parse(stream).xpath("//meta[@http-equiv = 'refresh']/@content")
if next:
url = next[0].split(";")[1].strip().replace("url=", "")
else:
return stream.geturl()
print follow("http://thetechshowdown.com/Redirect4.php")
我将把错误处理留给你:)还要注意,如果目标页面也包含<meta>
标签,这可能会导致无限循环。这不是你的情况,但你可以添加一些检查来防止这种情况:在n
重定向后停止,查看页面是否重定向到自身,无论你认为哪个更好。
您可能需要安装lxml
库。
答案 2 :(得分:0)
来自html的元刷新重定向网址可能看起来像以下任何一种:
相对网址:
<meta http-equiv="refresh" content="0; url=legal_notices_en.htm#disclaimer">
引号内有引号:
<meta http-equiv="refresh" content="0; url='legal_notices_en.htm#disclaimer'">
标签content
中的大写字母:
<meta http-equiv="refresh" content="0; URL=legal_notices_en.htm#disclaimer">
要点:
lower()
和两个split()
来获取网址部分shelves
的本地文件中(如果您要测试很多网址,则非常有用)。用法:
print get_redirections('https://www.google.com')
返回类似的内容:
{'final': u'https://www.google.be/?gfe_rd=fd&ei=FDDASaSADFASd', 'history': [<Response [302]>]}
代码:
from urlparse import urljoin, urlparse
import urllib, shelve, lxml, requests
from lxml import html
def get_redirections(initial_url, url_id = None):
if not url_id:
url_id = initial_url
documents_checked = shelve.open('tested_urls.log')
if url_id in documents_checked:
print 'cached'
output = documents_checked[url_id]
else:
print 'not cached'
redirecting = True
history = []
try:
current_url = initial_url
while redirecting:
r = requests.get(current_url)
final = r.url
history += r.history
status = {'final':final,'history':history}
html = lxml.html.fromstring(r.text.encode('utf8'))
refresh = html.cssselect('meta[http-equiv="refresh"]')
if refresh:
refresh_content = refresh[0].attrib['content']
current_url = refresh_content.lower().split('url=')[1].split(';')[0]
before_stripping = ''
after_stripping = current_url
while before_stripping != after_stripping:
before_stripping = after_stripping
after_stripping = before_stripping.strip('"').strip("'").strip()
current_url = urljoin(final, after_stripping)
history += [current_url]
else:
redirecting = False
except requests.exceptions.RequestException as e:
status = {'final':str(e),'history':[],'error':e}
documents_checked[url_id] = status
output = status
documents_checked.close()
return output
url = 'http://google.com'
print get_redirections(url)