Python 机械化提交表单字符编码问题

Python 机械化提交表单字符编码问题,python,encoding,mechanize,scraper,Python,Encoding,Mechanize,Scraper,我正在努力拼凑,特别是你从选择市/省得到的所有表格。我正在将python与lxml.html和mechanize一起使用。到目前为止,我的刮板工作正常,但在提交市政当局[19]“Peñarrubia,Abra”时,我收到了HTTP错误500:内部服务器错误。我怀疑这是由于字符编码。我猜是ene字符(上面有一个波浪号的n)导致了这个问题。我怎样才能解决这个问题 下面是我脚本这一部分的工作示例。由于我刚刚开始使用python(并且经常使用我在上面找到的代码片段),因此非常感谢您的进一步评论 from

我正在努力拼凑,特别是你从选择市/省得到的所有表格。我正在将python与lxml.html和mechanize一起使用。到目前为止,我的刮板工作正常,但在提交市政当局[19]“Peñarrubia,Abra”时,我收到了
HTTP错误500:内部服务器错误。我怀疑这是由于字符编码。我猜是ene字符(上面有一个波浪号的n)导致了这个问题。我怎样才能解决这个问题

下面是我脚本这一部分的工作示例。由于我刚刚开始使用python(并且经常使用我在上面找到的代码片段),因此非常感谢您的进一步评论

from BeautifulSoup import BeautifulSoup
import mechanize
import lxml.html
import csv



class PrettifyHandler(mechanize.BaseHandler):
    def http_response(self, request, response):
        if not hasattr(response, "seek"):
            response = mechanize.response_seek_wrapper(response)
        # only use BeautifulSoup if response is html
        if response.info().dict.has_key('content-type') and ('html' in response.info().dict['content-type']):
            soup = BeautifulSoup(response.get_data())
            response.set_data(soup.prettify())
        return response

site = "http://www.nscb.gov.ph/ggi/database.asp"

output_mun = csv.writer(open(r'output-municipalities.csv','wb'))
output_prov = csv.writer(open(r'output-provinces.csv','wb'))

br = mechanize.Browser()
br.add_handler(PrettifyHandler())


# gets municipality stats
response = br.open(site)
br.select_form(name="form2")
muns = br.find_control("strMunicipality2", type="select").items
# municipality #19 is not working, those before do
for pos, item in enumerate(muns[19:]): 
    br.select_form(name="form2")
    br["strMunicipality2"] = [item.name]
    print pos, item.name 
    response = br.submit(id="button2", type="submit")
    html = response.read()
    root = lxml.html.fromstring(html)
    table = root.xpath('//table')[1]
    data = [
               [td.text_content().strip() for td in row.findall("td")] 
               for row in table.findall("tr")
           ]
    print data, "\n"
    for row in data[2:]:
        if row: 
            row.append(item.name)
            output_mun.writerow([s.encode('utf8') if type(s) is unicode else s for s in row])
    response = br.open(site) #go back button not working

# provinces follow here
多谢各位

编辑:具体来说,错误发生在这一行

response = br.submit(id="button2", type="submit")
快速和肮脏的黑客:

def _pairs(self):
    return [(k, v.decode('utf-8').encode('latin-1')) for (i, k, v, c_i) in self._pairs_and_controls()]

from mechanize import HTMLForm
HTMLForm._pairs = _pairs
或者一些侵入性较小的方法(我认为没有其他解决方案,因为类项保护“name”字段)

以前

br["strMunicipality2"] = [item.name]

好的,找到了。这是一个转换为unicode并在默认情况下返回utf-8的漂亮汤。 你应使用:

response.set_data(soup.prettify(encoding='latin-1'))

有趣的问题。我试图解决它,但一无所获。在我看来,问题不在您自己的代码中,好像您更改了
项的编码一样。name
mechanize将抛出
名为“whatever\u here”的项不足。
。因此,使用
item.name
表单选择似乎是正确的,但在“发送”时,错误的数据被传递到服务器。我注意到您正在抓取的页面位于
iso-8859-1
,而不是
utf-8
,但是将编码更改为拉丁语也不起作用。好奇地想看看是否有人会解决!我还试图通过设置
br.\u factory.encoding=“iso-8859-1”
br.\u factory.\u forms\u factory.encoding=“iso-8859-1”
br.\u factory.\u links\u factory.\u encoding=“iso-8859-1”
,来更改mechanize的编码,但它不起作用。请弄清楚如何设置“内容类型”响应头并将值放入“文本/html;charset=iso-8859-1”。我尝试了mechanize文档中的解决方案,但没有成功。奇怪的是,提交表单时出现错误。使用这些值嗅探浏览器请求,并使用代码嗅探请求(您可以使用wireshark)也许您应该以服务器在页面的内容类型标题中告诉您的相同编码发送表单数据(服务器发送的内容类型:text/html,不带字符集),因此浏览器通常从页面中拾取内容(拉丁语1)执行浏览器请求,这两种解决方案都有效。(唯一的区别是,对于第二个解决方案,ene字符在终端中显示为灰色空白)。但是,您能否解释一下这些解决方案的确切功能以及它们的工作原理?我对所有这些都是新手,我尝试过
br[“strMunicipality2”]=[item.name.decode('utf-8')。encode('latin-1')]
,它不起作用。
item.\uu dict\uuu['name']=item.name.decode('utf-8')。encode('latin-1')
不同?事实上,第二种解决方案不起作用。它只在我使用特定的市政
为pos启动循环时起作用,如果我删除
[19:]中的item(muns[19:]):
和其他市政当局在提交相关项目之前提交,我仍然收到
名为“Pe\xf1arrubia+Abra”的项目不足。
第一个解决方案似乎确实有效。mechanize从页面中选择选项,我不确定原因,但它会在utf8中转换项目名称,然后选择一个br['xxx']=['abc']它在表单值中进行查找,因此您应该按照它在其项列表中的方式传递名称。当它创建post时,所有键对都是urlencoded的,请按原样机械化urlquotes值(但它已转换为utf8)。页面正在查询拉丁语中的expect值要查看终端中的正确字符,您应该使用区域设置(检查LANG环境变量)使用拉丁文1(iso-8859-1),并且终端应显示为拉丁文1(很可能您的终端具有utf8)第二个解决方案可能不起作用,或者更可能是第一个解决方案,因为它利用了mechanize的内部结构,在不同的版本中可能会有所不同,我需要深入研究,看看是否有可能在不高举mechanize代码的情况下进行修复。我已经完全忘记了beautiful soup。非常感谢!
response.set_data(soup.prettify(encoding='latin-1'))