如何在 Python 中模拟 post 表单来上传文件

Python014

如何在 Python 中模拟 post 表单来上传文件,第1张

在机器上安装了Python的setuptools工具,可以通过下面的命令来安装 poster:

easy_install poster

装完之后,安装下面代码就可以实现post表单上传文件了:

from poster.encode import multipart_encode

from poster.streaminghttp import register_openers

import urllib2

 

# 在 urllib2 上注册 http 流处理句柄

register_openers()

 

# 开始对文件 "DSC0001.jpg" 的 multiart/form-data 编码

# "image1" 是参数的名字,一般通过 HTML 中的 <input> 标签的 name 参数设置

 

# headers 包含必须的 Content-Type 和 Content-Length

# datagen 是一个生成器对象,返回编码过后的参数

datagen, headers = multipart_encode({"image1": open("DSC0001.jpg", "rb")})

 

# 创建请求对象(localhost服务器IP地址,5000服务器端口)

request = urllib2.Request("http://localhost:5000/upload_image", datagen, headers)

# 实际执行请求并取得返回

print urllib2.urlopen(request).read()

以下实例是一个完整的代码,实现了从博客获取内容发布至百度,分别实践抓取博客内容、模拟登录、表单提交这几步;

#注意,以下程序是一个完全程序,如果只需要实现模拟登录,提交表单,删除抓取部分即可,相关的代码已经清楚标注,可以根据自己实际情况修改。

代码如下:

# -*- coding: utf-8 -*-

import re

import urllib

import urllib2

import cookielib

#第一步,获取博客标题和正文 ,“IP”可以改为实际地址;

url = "IP"

sock = urllib.urlopen(url)

html = sock.read()

sock.close()

content = re.findall('(?<=blogstory">).*(?=<p class="right artical)', html, re.S)

content = re.findall('<script.*>.*</script>(.*)', content[0], re.S)

title = re.findall('(?<=<title>)(.*)-.* - CSDN.*(?=</title>)', html, re.S)

#根据文章获取内容新建表单值

blog = {'spBlogTitle': title[0].decode('utf-8').encode('gbk'), #文章标题

'spBlogText': content[0].decode('utf-8').encode('gbk'),#文章内容

'ct': "1",

'cm': "1"}

del content

del title

#第二步,模拟登录百度;

cj = cookielib.CookieJar()

#登陆百度的用户名和密码

post_data = urllib.urlencode({'username': '[username]', 'password': '[password]', 'pwd': '1'})

#登录地址路径

path = 'https://passport.baidu.com/?login'

opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))

opener.addheaders = [('User-agent', 'Opera/9.23')]

urllib2.install_opener(opener)

req = urllib2.Request(path, post_data)

conn = urllib2.urlopen(req)

#获取百度登陆认证令牌

bd = urllib2.urlopen(urllib2.Request('http://hi.baidu.com/[username]/creat/blog')).read()

bd = re.findall('(?<=bdstoken\" value=\").*(?=ct)', bd, re.S)

blog['bdstoken'] = bd[0][:32]

#设置分类名

blog['spBlogCatName'] = 'php'

#第四步,比较表单,提交表单;req2 = urllib2.Request('http://hi.baidu.com/[username]/commit', urllib.urlencode(blog))

#最后,查看表单提交后返回内容,检验;

print urllib2.urlopen(req2).read()

#注意:将[username]/[password]替换为自己真实用户名和密码