【发布时间】:2011-09-30 09:54:29
【问题描述】:
我正在尝试抓取http://www.nscb.gov.ph/ggi/database.asp,特别是您从选择市/省获得的所有表格。我正在使用带有 lxml.html 和机械化的 python。到目前为止,我的刮刀工作正常,但是在提交市政当局[19]“Peñarrubia,Abra”时,我得到了HTTP Error 500: Internal Server Error。我怀疑这是由于字符编码。我的猜测是 ene 字符(上面带有波浪号的 n)会导致这个问题。我该如何解决这个问题?
我的脚本这部分的一个工作示例如下所示。由于我刚开始使用 python(并且经常使用我在 SO 上找到的 sn-ps),因此非常感谢任何进一步的 cmets。
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")
【问题讨论】:
-
有趣的问题。我想办法解决它,但一无所获。在我看来,问题不在于您自己的代码,因为如果您更改
item.name的编码,mechanize 会抛出insufficient items with name 'whatever_here'。所以似乎通过使用item.name表单选择正确发生,但是在“发送”时错误的数据被传递到服务器。我注意到您正在抓取的页面位于iso-8859-1,而不是utf-8,但是将编码更改为拉丁文也不起作用。很想知道是否有人会解决! -
我也尝试通过设置
br._factory.encoding = "iso-8859-1"、br._factory._forms_factory.encoding = "iso-8859-1"、br._factory._links_factory._encoding = "iso-8859-1"来改变mechanizeas suggested here的编码,但是没有成功。 -
弄清楚如何设置“Content-Type”响应头并将值设置为“text/html; charset=iso-8859-1”。
-
我已经尝试了机械化文档中的解决方案,但无济于事。奇怪的是,提交表单时出现错误。
-
嗅探带有这些值的浏览器请求和带有您的代码的请求(您可以使用wireshark)也许您应该以服务器在页面的Content-Type标头中告诉您的相同编码发送表单数据具有表单(服务器发送 Content-Type: text/html without charset),因此浏览器通常会从页面(latin1)中选择内容,浏览器请求是否有效
标签: python encoding mechanize scraper