学号 2019-2020-2 《Python程序设计》实验四报告
课程:《Python程序设计》
班级: 1831
姓名: 陈介
学号:20183122
实验教师:王志强
实验日期:2020年6月7日
必修/选修: 公选课
1.实验内容
1) 爬取豆瓣院线电影信息,编写GUI用户图形界面展示信息
2) 添加文件操作内容以及网络编程,使结果可写入文件也可从文件读出之前的结果,也能上传至服务器
2. 实验过程及结果
1) 编写爬虫从豆瓣主页爬取相关信息并使用BeautifulSoup解析,剥离出有用的数据
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/83.0.4103.61 Safari/537.36'
}
re = requests.get(url, headers=headers)
soup = BeautifulSoup(re.text, 'html.parser')
# 信息存储在li标签下的list-item类下
movies = soup.findAll('li', {'class': 'list-item'})
# 数据处理过程较为冗长,请移步码云查看
2) 编写可视化图形界面
首先建立GUI框架
def Win_build():
app = QApplication(sys.argv)
frame = Frame()
frame.init_text()
frame.show()
sys.exit(app.exec_())
其中Frame是一个自定义的继承自QMainWindow的类;
接着在自定义类中创建一系列的函数,其中需要初始显示的控件可以放在__init__函数下自动执行;
class Frame(QMainWindow):
def __init__(self):
super().__init__()
self.init_MainWin()
self.setFixedSize(self.width(), self.height())
self.init_buttons()
再逐步绑定各种信号和槽,使界面完善。
3) 将信息展示添加到图形化界面中
我使用的方法是定义全局变量,用列表嵌套字典的方式存储处理过后的信息,在自定义类中使用的时候就不用考虑参数的传递问题;
def init_text(self, string=' '):
"""
这个函数更新在文本框中显示的内容,同时限定此文本框为只读模式,不允许用户修改查询到的地方
:param string: 想在文本框中显示的内容
:return: None
"""
mo_text = QTextEdit(self)
mo_text.setFont(QFont("fangsong", 12))
mo_text.clear()
mo_text.setPlainText(string)
mo_text.setToolTip("这个文本框显示了爬虫爬取的即将上映或正在上映的电影信息")
mo_text.setGeometry(100, 100, 800, 450)
mo_text.setReadOnly(True)
mo_text.show()
其中string为存储电影信息的字符串,设定默认值是为了防止用户未爬取就查询时由于内容为空会报错。
4) 添加文件操作,可写入数据,保存海报,读出之前数据
打开文件并将数据写入文件
def openfile(self):
"""
选择并打开文件,将爬取到的结果写入文件
:return: None
"""
global string
filename = QFileDialog.getOpenFileName(self, '打开文件', './', "txt(*.txt)")
if filename[0]:
with open(filename[0], 'w', encoding="utf-8") as f:
f.write(string)
QMessageBox.information(self, "提示", "院线电影信息成功写入指定文件>_<")
打开.txt类型的文件并将文本提取出来显示到GUI界面中
def readfile(self):
"""
让用户选择并打开.txt文件并将其内容显示到文本栏中
:return: None
"""
filename = QFileDialog.getOpenFileName(self, '打开文件', './', "txt(*.txt)")
if filename[0]:
with open(filename[0], 'r', encoding='utf-8') as f:
read_info = f.read()
detail_text = QTextEdit(self)
detail_text.setGeometry(950, 200, 600, 500)
detail_text.setToolTip("这个文本框显示了读取到的文件的内容")
detail_text.setReadOnly(False)
detail_text.show()
detail_text.setText(read_info)
查看电影海报时会先将海报缓存到本地文件中,再从本地读取,设定不同颜色的边框区分不同类型的电影
def show_picture_up(self):
"""
展示即将上映的电影的海报
:return: None
"""
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/83.0.4103.97 Safari/537.36 Edg/83.0.478.45 '
}
try:
res = requests.get(list_show_up[up_index]['img'], headers=headers)
root = "F://python全栈//python程序设计大实验//"
path = root + '1.jpg'
if not os.path.exists(root):
os.mkdir(root)
with open(path, 'wb') as f:
f.write(res.content)
f.close()
except:
QMessageBox.information(self, "提示", "海报资源请求错误")
pix = QPixmap('1.jpg')
picture_lab = QLabel(self)
picture_lab.setGeometry(950, 400, 600, 300)
picture_lab.setPixmap(pix)
picture_lab.setStyleSheet("border: 2px solid red")
picture_lab.setScaledContents(True)
picture_lab.show()
5) 网络编程,可将数据上传到运行服务器端的主机上
调用自定义函数上传数据,反馈上传结果到GUI界面中
def ftp_push(self):
"""
调用自定义模块上传文件
:return:布尔值,上传成功为True,上传失败为False
"""
bool1 = ftp.push(sys.argv)
if bool1:
QMessageBox.information(self, "提示", "文件上传成功")
else:
QMessageBox.information(self, "提示", "文件上传失败")
6) 临时起意,添加了文本文件的编辑和保存功能,在程序中实现了记事本的功能,不仅局限于电影信息,可处理任何.txt文件
实验结果:
3. 实验过程中遇到的问题和解决过程
- 问题1:豆瓣反爬
- 问题1解决方案:添加头部伪装为浏览器,豆瓣的电影搜索信息在网页源码中是可以看到的,但是爬取下来之后是没有的,需要一系列的解密过程,较为复杂,涉及加密css和js,于是我选择了加密较为简单的院线电影信息作为爬取对象。
- 问题2:读文件的时候编码不正确
- 问题2解决方案:打开文件的时候获取其编码方式,写入文件的时候指定编码方式
- 问题3:自定义模块不能正常使用
- 问题3解决方案:将自定义模块所在的文件夹改为sources root