批量抓取网页pdf文件

任务:批量抓取网页pdf文件

有一个excel,里面有数千条指向pdf下载链接的网页地址,现在,需要批量抓取这些网页地址中的pdf文件。
python环境:

anaconda3

openpyxl

beautifulsoup4

读取excel,获取网页地址

使用openpyxl库,读取.xslx文件;
(曾尝试使用xlrd库读取.xsl文件,但无法获取超链接)

  1. 安装openpyxl

    pip install openpyxl
  2. 提取xslx文件中的超链接

    示例文件构造

公告日期证券代码公告标题
2018-04-20603999.SH读者传媒:2017年年度报告
2018-04-28603998.SH方盛制药:2017年年度报告
def  readxlsx(path):
    workbook = openpyxl.load_workbook(path)
    Data_sheet = workbook.get_sheet_by_name('sheet1')
    rowNum = Data_sheet.max_row #读取最大行数
    c =  3  # 第三列是所需要提取的数据
    server =  'http://news.windin.com/ns/'
    for  row  in  range(1, rowNum  +  1):
        link = Data_sheet.cell(row=row, column=c).value
        url = re.split(r'\"', link)[1]
        print(url)
        downEachPdf(url, server)

获取网页pdf下载地址

进入读者传媒:2017年年度报告,在chrome浏览器中可以按F12查看网页源码,以下截取部分源码:

<div class="box4"><div style='float:left;width:40px;background-color:#ffffff;'>附件:</div>  <div style=float:left;width:660px;background-color:#f3f3f3;'>  <a href=[getatt.php?id=91785868&att_id=32276645](http://news.windin.com/ns/getatt.php?id=91785868&att_id=32276645) class='big' title=603999读者传媒2017年年度报告.pdf>603999读者传媒2017年年度报告.pdf </a>&nbsp;&nbsp; (2.00M) &nbsp;&nbsp</div></div>

可见,herf下载链接在a标签中,可以通过解析html源码获取下载链接。
这里使用BeautifulSoup解析html。

Beautiful Soup 是用Python写的一个HTML/XML的解析器,它可以很好的处理不规范标记并生成剖析树(parse tree)。 它提供简单又常用的导航(navigating),搜索以及修改剖析树的操作。它可以大大节省你的编程时间。

  1. 安装BeautifulSoup4
pip install beautifulsoup4
  1. 获取pdf下载链接并下载
def  downEachPdf(target, server):
    req = requests.get(url=target)
    html = req.text
    bf = BeautifulSoup(html, features="lxml")
    a = bf.find_all('a')
    for each in a:
        url = server + each.get('href')
        print("downloading:", each.string, url)
        urllib.request.urlretrieve(url, './report/' + each.string)

同一ip重复访问同一服务器被拒绝

利用以上方法已经能够实现批量网页pdf的下载了,但是,在实际操作过程中,会发现如果同一ip频繁地访问某一服务器,访问会被拒绝(可能被误判为DOS攻击,通常做了Rate-limit的网站都会停止响应一段时间,你可以Catch这个Exception,sleep一段时间,参考)。因此,对下载逻辑进行了调整。
利用try-catch,具体逻辑是:正常情况下,按次序下载文件,如果同一文件,下载失败次数超过10,则跳过,下载下一个文件,并记录错误信息。

import os
import time
def  downloadXml(flag_exists, file_dir, file_name, xml_url):
    if  not flag_exists:
        os.makedirs(file_dir)
        local = os.path.join(file_dir, file_name)
    try:
        urllib.request.urlretrieve(xml_url, local)
    except  Exception  as e:
        print('the first error: ', e)
        cur_try =  0
        total_try =  10
        if cur_try < total_try:
            cur_try +=  1
            time.sleep(15)
            return downloadXml(flag_exists, file_dir, file_name, xml_url)
    else:
        print('the last error: ')
        with  open(test_dir +  'error_url.txt', 'a') as f:
            f.write(xml_url)
        raise  Exception(e)
    原文作者:justchenhao
    原文地址: https://segmentfault.com/a/1190000018156141
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞