IEEE论文爬虫及数据统计
1. IEEE论文爬虫
爬虫代码网上有很多了,这部分是直接用的网上可以跑通的[1]。使用的时候直接调用
get_article_info()
,其中参数 conferenceID
需要手动在 IEEE 上查询会议的 ID 号,参数 saceFileName
为希望保存的 csv
文件名。
1 |
|
2. IEEE论文数据统计
3. 写一个图形界面
3.1 弹出提示窗口
在写代码过程中有时候需要测试功能是否成功实现,于是想要加一个弹出窗口的函数可以显示调试信息,用以验证想要的功能是否正常实现。主要难点在于根据内容自动调整窗口大小,以获得较好的显示效果。
采用的方法是利用 QLabel.adjust()
函数获取文本显示的宽度,并据此调整窗口的大小[2]。
1 |
|
3.2 文本框显示爬取日志
我希望在窗口中增加一个文本框,将爬取过程中的日志信息打印出来,便于用户实时监测。
采用的思路是定义一个
logging.Logger
,将其日志信息同时输出到窗口的文本框和控制台中打印,通过自定义
logging.Handler
可以实现这一功能[3][5][6]。实现方式为:
继承
logging.Handler
类,并初始化阶段将整个窗口(QWidget
类)作为参数传入,便于后续修改窗口的信息;自定义实现
emit
函数,在emit
函数中将 log 信息同时输出到窗口文本框、打印到控制台;创建
logger
的时候设置 Handler[4]1
2
3
4ex = PaperCollector()
logger = logging.getLogger("logger")
handler = LogHandler(ex)
logger.addHandler(handler)
下面是这部分功能相关的代码。
1 |
|
爬取论文的主函数如下,其中一个参数为
logger
,在函数内部需要打印日志信息的地方添加
logger.info(...)
即可。
1 |
|
3.3 多线程避免卡顿
上述打印日志的方法不能做到实时输出信息到窗口文本框,而是会等到所有论文爬取完毕之后再一股脑的更新,这是因为PyQt的界面线程是主线程,当爬虫开始工作时,也是运行在主线程中,这时主界面就无法更新,看起来就像是卡死了。解决方法就是开一个子线程运行爬虫工作<span class="hint--top hint--rounded" aria-label="PyQt - 使用多线程避免界面卡顿 - bailang zhizun的博客 - CSDN博客 ">[7]。
具体实现细节为:
- 新建类
SpiderThread
继承QObject
,自定义run
函数,在其中运行爬虫程序; - 在
SpiderThread
类中定义一个_spider_finish = pyqtSignal()
,该信号用于告知主线程爬虫子线程已完成工作 - 在
PaperCollector
类中定义一个_start_spider = pyqtSignal(str, str, logging.Logger)
,该信号用于启动爬虫子线程[8][9]; - 通过
pyqtSignal.connect
分别将各个信号连接到对应的槽(处理函数)上;
下面是这部分功能相关的代码。
1 |
|
3.4 流畅中止子线程
有时候我们需要中途停止爬虫工作,比如发现会议ID设置错误、希望先对已经爬取的部分数据进行统计分析等。在上面的实现中,尽管线程正常运行很流畅,但是如果在爬虫运行中途点击停止按钮,程序就会卡死。
在原本的爬虫脚本中,get_article_info()
函数内部的爬虫采用了 while(True)
死循环,主线程中直接用
self.thread.quit()
强制退出,从控制台来看这样确实可以停掉,但是Qt窗口却总是会卡死。原因我也不太清楚,采用的解决方法是:
- 定义一个爬虫类
IEEESpider
,设置成员变量flag_running
,将函数get_article_info
也设置为类成员函数; - 将
get_article_info
中的循环改为while(self.flag_running)
; - 在主线程中想要停止爬虫子线程的时候,只需要首先设置
flag_running=False
,那么爬虫子线程在当前一次循环结束后就自动结束,这个时候主线程调用self.thread.quit()
就不会导致界面卡死。需要注意的是设置flag_running=False
一定要sleep
一段时间,以保证爬虫子线程能够结束当前循环,否则还是容易卡死。
下面是这部分功能的代码。
1 |
|
1 |
|
3.5 增加侧边导航栏
前面只有爬取论文的页面,现在我想加上数据分析的页面,那么就需要设置一个侧边导航栏,以切换两种不同的任务。
实现方式为左侧设置多个按钮,右侧添加一个
QTabWidget()
,将不同的页面设置为子标签页,通过按钮的点击回调函数切换不同的标签页[10]。
1 |
|
3.6 next ...
接下来考虑:写数据分析页面 ......
Referencce
这里关于参考文献的部分,本来我想按照下面格式来写,希望实现的效果是都像[2][10]一样,每一条引用列出来的是超链接,而不是直接写出来链接地址,但是我发现除了第[2][10]条,其他条这么写话都会像现在的第<span class="hint--top hint--rounded" aria-label="PyQt - 使用多线程避免界面卡顿 - bailang zhizun的博客 - CSDN博客 ">[7]条一样,格式会乱,也不知道为什么。有人知道的话可以告诉我嘛 >_<
1 |
|
- https://blog.csdn.net/wp7xtj98/article/details/112711465 ↩︎
- PyQt 中文教程 (gitbook.io) ↩︎
- https://zhuanlan.gitbook.io/p/360306588 ↩︎
- https://blog.csdn.net/qq_37541097/article/details/108317762 ↩︎
- https://stackoverflow.com/questions/41176319/python-logging-output-on-both-gui-and-console ↩︎
- https://stackoverflow.com/questions/24371274/how-to-dynamically-update-qtextedit ↩︎
- PyQt - 使用多线程避免界面卡顿 - bailang zhizun的博客 - CSDN博客 ↩︎
- https://blog.csdn.net/gong_xufei/article/details/89786272 ↩︎
- https://blog.csdn.net/qq_39560620/article/details/105711799 ↩︎
- PyQt5 侧边栏布局 • Chang Luo (luochang.ink) ↩︎