【问题标题】:Python urllib unicode exception in 302 redirection [duplicate]302重定向中的Python urllib unicode异常[重复]
【发布时间】:2016-12-20 19:58:10
【问题描述】:

情况是: 我正在抓取一个网站,页面的 url 遵循模式:

http://www.pageadress/somestuff/ID-HERE/

没有什么不寻常的。 我有很多我需要刮掉的 id,它们中的大多数都能正常工作。 但是,页面以类似门户的方式运行。在浏览器中,当你输入这样的地址时,你会被重定向到:

http://www.pageadress/somestuff/ID-HERE-title_of_subpage

可能有问题的是,有时该标题可能包含非 ascii 字符(大约 0.01% 的情况),因此(我认为这是问题所在)我得到了例外:

  File "/usr/lib/python3.4/urllib/request.py", line 161, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.4/urllib/request.py", line 469, in open
    response = meth(req, response)
  File "/usr/lib/python3.4/urllib/request.py", line 579, in http_response
    'http', request, response, code, msg, hdrs)
  File "/usr/lib/python3.4/urllib/request.py", line 501, in error
    result = self._call_chain(*args)
  File "/usr/lib/python3.4/urllib/request.py", line 441, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.4/urllib/request.py", line 684, in http_error_302
    return self.parent.open(new, timeout=req.timeout)
  File "/usr/lib/python3.4/urllib/request.py", line 463, in open
    response = self._open(req, data)
  File "/usr/lib/python3.4/urllib/request.py", line 481, in _open
    '_open', req)
  File "/usr/lib/python3.4/urllib/request.py", line 441, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.4/urllib/request.py", line 1210, in http_open
    return self.do_open(http.client.HTTPConnection, req)
  File "/usr/lib/python3.4/urllib/request.py", line 1182, in do_open
    h.request(req.get_method(), req.selector, req.data, headers)
  File "/usr/lib/python3.4/http/client.py", line 1088, in request
    self._send_request(method, url, body, headers)
  File "/usr/lib/python3.4/http/client.py", line 1116, in _send_request
    self.putrequest(method, url, **skips)
  File "/usr/lib/python3.4/http/client.py", line 973, in putrequest
    self._output(request.encode('ascii'))
UnicodeEncodeError: 'ascii' codec can't encode characters in position 38-39: ordinal not in range(128).

奇怪的是,我被重定向到的 url 中没有任何 unicode 字符实际上位于 38-39 位置,但还有其他字符。

正在使用的代码:

import socket
import urllib.parse
import urllib.request
socket.setdefaulttimeout(30)
url = "https://www.bettingexpert.com/archive/tip/3207221"
headers = {'User-Agent': 'Mozilla/5.0'}
content = urllib.request.urlopen(urllib.request.Request(url, None, headers)).read().decode('utf-8')

有什么方法可以绕过它,最好不使用其他库?

//哦,python 的辉煌世界,如果我用 ruby​​ 编写的话,我什至不会想到可能会产生 1000 多个问题。

【问题讨论】:

  • 您提供的代码不完整(无法执行)。 id 的值是多少?实际 URL 的相同问题(此处未提供)。如果您希望其他人能够调试问题,那么您需要提供真实的 URL。
  • 您是否尝试使用urllib.parse.quote(id.__str__()) 而不是普通的id.__str__()
  • Id 是一个整数@Phillip
  • 抱歉,我认为这可能是更普遍的问题。我尝试访问的网址是:
  • @piezol 如果它适合您,请切换到 Python 3.5。他们在那里为您的问题提供了解决方法。问题是 bettingexpert 正式不会在 Location 标头中返回有效 URL,因为它没有正确引用 ß 字符。如果切换不是一个选项,您可以使用另一个库,如 requests 或安装一个自定义 urllib 打开器来缓解这个问题。参见例如this related question.

标签: python python-3.4 urllib http-status-code-302


【解决方案1】:

所以,我找到了解决我的具体问题的方法。 我刚刚从他们的 api 中收集了“url”的剩余部分,经过一些小的转换,我可以在没有任何重定向的情况下访问页面。 当然,这并不意味着我解决了一般问题——它可能会在以后出现,所以我开发了一个“解决方案”。

通过在这里发布这段代码,我基本上已经向自己保证,我永远不会被雇用为程序员,所以如果你正在吃饭,请不要看它。

需要“Capybara”宝石和恶作剧,因为为什么不呢?

#test.py
import socket
import urllib.parse
import urllib.request
import os
tip_id = 3207221
socket.setdefaulttimeout(30)
url = "http://www.bettingexpert.com/archive/tip/" + tip_id.__str__()
headers = {'User-Agent': 'Mozilla/5.0'}

try:
    content = urllib.request.urlopen(urllib.request.Request(url, None, headers)).read().decode('utf-8')
except UnicodeEncodeError:
    print("Overkill activated")
    os.system('ruby test.rb ' + tip_id.__str__())
    with open(tip_id.__str__(), 'r') as file:
        content = file.read()
    os.remove(tip_id.__str__())
print(content)

.

#test.rb
require 'capybara'
require 'capybara/dsl'
require 'capybara/poltergeist'

Capybara.register_driver :poltergeist_no_timeout do |app|
  driver = Capybara::Poltergeist::Driver.new(app, timeout: 30)
  driver.browser.url_blacklist = %w(
    http://fonts.googleapis.com
    http://html5shiv.googlecode.com
  )
  driver
end
Capybara.default_driver = :poltergeist_no_timeout
Capybara.run_server = false
include Capybara::DSL
begin
  page.reset_session!
  page.visit("http://www.bettingexpert.com/archive/tip/#{ARGV[0]}")
rescue
  retry
end
File.open(ARGV[0], 'w') do |file|
  file.print(page.html)
end

【讨论】:

    猜你喜欢
    • 2014-01-02
    • 1970-01-01
    • 2013-12-26
    • 2018-03-18
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    • 2017-09-20
    • 1970-01-01
    相关资源
    最近更新 更多