前言
前些天在逛论坛的时候突然发现了一篇文章,标题是通过编程自动化提高自己博客访问量的。我想了下,突然感觉可以用学过的Python的简单知识来实现这一目的。主要原理就是BeautifulSoup+urllib的组合,通过BS解析网页,获取目录,然后深入,获取文章的url,通过urllib.request模块尝试连接CSDN的服务器。说干就干
脚本实现
1 | from bs4 import BeautifulSoup |
UI实现
用PyQt5将程序的大致控件摆放完成了:
将pyqt生成的ui文件直接通过命令生成.py文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57pyuic5.bat -o layout.py untitled.ui
#代码如下
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.5.1
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
self.label = QtWidgets.QLabel(Form)
self.label.setGeometry(QtCore.QRect(20, 30, 81, 21))
self.label.setObjectName("label")
self.username = QtWidgets.QPlainTextEdit(Form)
self.username.setGeometry(QtCore.QRect(110, 20, 341, 41))
self.username.setObjectName("username")
self.label_2 = QtWidgets.QLabel(Form)
self.label_2.setGeometry(QtCore.QRect(30, 80, 61, 31))
self.label_2.setObjectName("label_2")
self.times = QtWidgets.QPlainTextEdit(Form)
self.times.setGeometry(QtCore.QRect(110, 80, 151, 41))
self.times.setObjectName("times")
self.beginBtn = QtWidgets.QPushButton(Form)
self.beginBtn.setGeometry(QtCore.QRect(300, 80, 61, 41))
self.beginBtn.setObjectName("beginBtn")
self.progressBar = QtWidgets.QProgressBar(Form)
self.progressBar.setGeometry(QtCore.QRect(30, 350, 461, 41))
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName("progressBar")
self.listView = QtWidgets.QListView(Form)
self.listView.setGeometry(QtCore.QRect(30, 180, 431, 151))
self.listView.setObjectName("listView")
self.info = QtWidgets.QLabel(Form)
self.info.setGeometry(QtCore.QRect(30, 140, 421, 31))
self.info.setText("")
self.info.setObjectName("info")
self.exitBtn = QtWidgets.QPushButton(Form)
self.exitBtn.setGeometry(QtCore.QRect(390, 80, 61, 41))
self.exitBtn.setObjectName("exitBtn")
self.retranslateUi(Form)
self.exitBtn.clicked.connect(Form.close)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", " CSDN用户名"))
self.label_2.setText(_translate("Form", "设置次数"))
self.beginBtn.setText(_translate("Form", "Start"))
self.exitBtn.setText(_translate("Form", "Exit"))
UI、逻辑处理
遇到的一些问题
在这次编写GUI的过程中,我遇到了原来没有的问题。
以往的时候,如上篇文章,通过Python的QR模块生成QR二维码,因为逻辑非常简单,只是单纯的将所需要转换的数据变换成为相应的0、1二进制码,然后放到图片中的相应位置上,所以不会花费太多的时间,逻辑部分与界面部分就直接写在了一起没有问题。
这次刚开始的时候,我也没注意,直接就还是写在一块,由于牵扯到了url网络连接部分,所以不可避免的出现了阻塞现象。几乎在所有的GUI设计中,如果当长时间出现阻塞、无状态回应情况,都会出现界面的未响应状态,所以我想到了在Android开发中相当常规的子线程与UI线程通信,Handler的使用,在PyQt中也有类似的机制,也就是Qt的核心机制,信号槽机制,更多的内容可以看我另外的文章,我会详细的介绍下。
下面是我修改完成后的代码,可以顺利完成我预设的功能:
1 | import urllib.request |
总结
由于使用了designer默认的绝对布局方式,代码比较杂乱。总的来说也就分3个模块:
网页获取、解析工作类 Grab
界面布局、实时数据展现类 Ui_Form
逻辑控制、监控与沟通类 MyThread
各个模块相互合作,实现功能.
通过Requests、Xpath改写
这是后来补上的.
在我完成这篇文章之前的部分的时候,还是对python刚入门,使用了比较经典的一些网络模块。后来通过一些实例练习,接触到了一些简洁、优雅的模块,通过这些模块继续完善。
Grab类
1 | class Grab(): |
- Request模块
在上网认证这篇文章有过大概的介绍。模块通过提供极其简单的方法名称接口,隐藏了复杂的网络工作,大大简化了代码。
- Xpath
Xpath介绍Xpath不是一个模块,而是活跃在众多平台的一种工具,也可以称她是一种语言。通过对网页源代码解析,内部构建路径,轻松获取想要的内容。在BeautifulSoup太沉重复杂、又不想使用正则的情况下,是一种很棒的解决方案。
MyThread类
1 | class MyThread(QtCore.QThread): |
去掉time.sleep(seconds)
推迟线程调用之后,会出现网络模块报错,这应该是所有网络模块都会碰到的情况。