使用Python自动下载论文

批量下载某个研究领域的相关论文,尤其是会议论文,一篇一篇下载太慢,故写此代码自动下载所有论文。

会议论文列表有很多种形式,比如说:

由此可见,在最后一步是相同的,不同的是论文列表集合来源。本篇博客暂时考虑了第一种情况

环境要求

下述python包直接装就行。

python 3.6 
BeautifulSoup # 解析html网页
requests_html # 爬取网页,试过requests库,感觉比较麻烦
urllib.request # 下载pdf

第一种情况:他人给出了关于某个研究领域的论文列表

这种情况常出现在他人通过某种方式,将某个研究领域的论文都整合到一起,方便日后查看。这时候,我们可以利用这个列表提供的链接下载论文。

例如,本文从知乎链接中,自动下载该博主整理的与对抗样本有关的论文。

具体代码如下:

from bs4 import BeautifulSoup as bf
from requests_html import HTMLSession
import os
import urllib.request

# 博客链接
url = "https://zhuanlan.zhihu.com/p/419951814?utm_source=com.alibaba.android.rimet&utm_medium=social&utm_oi=1112035085750071296"

使用request_html库爬取网页

r = session.get(url)
absolute_links = r.html.absolute_links  # 得到网页中所有的超链接地址

接着遍历超链接地址,去掉无关地址

for i, item in enumerate(absolute_links):
    # 如果是论文,超链接地址中必定含有以下字符(这部分有点不自动)
	if "content/ICCV2021" in item:
		get_paper_pdf_from_url(args, item)
		print(f"{i} completed!!")

函数get_paper_pdf_from_url的定义为

def get_paper_pdf_from_url(args, url):
	'''此处args.conference为https://openaccess.thecvf.com'''
    # 这里也有点不自动,主要是知乎链接跳转需要确认,为了方便直接使用了以下的方式
    url = url.replace("//link.zhihu.com/?target=https%3A//", "//")
    sub_r = session.get(url)  # 爬取论文页面网页
    resp = bf(sub_r.html.html, "html.parser")
    ahref_list = resp.find_all('a')  
    pdf_url = [i for i in ahref_list if "pdf" in i.text][0].attrs['href'] # 找到论文下载的链接
    pdf_url = args.conference + pdf_url  # 组成论文下载的链接
    download_file(pdf_url, args.save_dir)

函数download_file的定义为

def download_file(download_url, save_dir):
    response = urllib.request.urlopen(download_url)
    filename = os.path.basename(download_url)
    filepath = os.path.join(save_dir, filename)
    # 这里做判断主要是因为网络不好,下载会中断,所以要重复运行代码,为了避免重复下载。这里应该有更好的解决办法
    if os.path.exists(filepath) is False:
        file = open(filepath, 'wb')
        file.write(response.read())
        file.close()

另外,还新增了一个下载bibtex的方法

def get_bib(url):
    url = url.replace("//link.zhihu.com/?target=https%3A//", "//")
    sub_r = session.get(url)
    resp = bf(sub_r.html.html, "html.parser")
    bib_text = resp.find(name='div', attrs={"class":'bibref pre-white-space'}).text
    return bib_text

(未完待续….)

Table of Contents