如何使用python批量下载网站的文件_Python学习日记12|用python3多进程批量下载pdf文件...

今天是2016年6月9日,也是农历的端午节。

难得的小长假,转眼就到学期末,忙了一学期大概大家或回家过端午或在宿舍休息调养吧,8点25到实验室的时候只有一个从广西大学来学院进修的教授已经开始了一天的工作。自己是觉得没什么特别,所有的节日能让人开心就好,即使没有粽子吃。

Anyway, 还是想说一声:端午节快乐~~

最近实习还一直没有着落,周一的面试是已经gg了,然后又开始投简历以求暑假有个去处,而不至于落单无事可做,尽管自己口头上一直说着无所谓。

这次的任务是下载

于是开始看能不能构造路径,发现还是行不通,再用fiddler去监控点击下载时发生了什么,这时才有了一点眉目:在点击pdf下载时,是有提交post请求的,传入的了两个参数分别是filename和descname。这时才恍然大悟,像这种点击下载的文件,你要模拟这个点击行为,一般应该就是一个post请求。

再说一下知道是提交post请求后实际操作时有几点要注意:

1.提交到post请求中的参数,通过查看源码后发现是可以用BesutifulSoup配合正则表达式从源码中来直接提取的,正则表达式一般就用re.search(),或者re.findall()

2.提交的filename和descname参数必须先转成URL编码,这是通过fiddler截取到的form表单中发现的,所以又引入urllib库中的parse,再使用parse.quote(text)函数来实现将两个参数转化为URL编码。(自己操作时quote()函数的用法是采用的python3中的语法,若是在python2.x版本中则是直接用urllib.quote(text)即可,但是,但是python2.x版本关于中文编码真的有很多问题,动不动就报错,所以果断没有用python2.x版本)

3.在上述基础上提交了filename和descname参数,如何将pdf保存下来,由于pdf文件比较大,有的达到10M,因此这里会用到 Response.iter_content()的使用,有固定的用法,实现的功能是以流的形式保存较大的文件。具体可以参考。

( http://stackoverflow.com/questions/16694907/how-to-download-large-file-in-python-with-requests-py )

4.要再说一点的就是有时候用requests.get()去请求网址时,加上headers虽说是为了伪装成浏览器进行访问,但有时反而会没有反应,去掉headers后反而就直接出了结果,这是自己不解的地方。

最后贴上代码和抓取结果(243个pdf文件,最大有24M),如下:

#!/usr/bin/env python

# _*_ coding: utf-8 _*_

import requests

from bs4 import BeautifulSoup

from urllib import parse

import re

import time

from multiprocessing import Pool

headers={

'Host': 'www.shclearing.com',

'Connection': 'keep-alive',

'Content-Length': '478',

'Cache-Control': 'max-age=0',

'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',

'Origin': 'http://www.shclearing.com',

'Upgrade-Insecure-Requests': '1',

'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36',

'Content-Type': 'application/x-www-form-urlencoded',

'Accept-Encoding': 'gzip, deflate',

'Accept-Language': 'zh-CN,zh;q=0.8',

'Cookie': '_ga=GA1.2.1076225437.1465265795; JSESSIONID=24XcXXCb1bkkKWnKn1LLNBqGTR8qnfmcmf3p5T2pw2TwpNCytnfp!301927905; HDSESSIONID=fhwLXXLPrBqXwsvCyqKL1lCbp5QmGDxxGJ4wd8vrfhr2ksgJcpvf!1660475047; Hm_lvt_d885bd65f967ea9372fc7200bc83fa81=1465223724; Hm_lpvt_d885bd65f967ea9372fc7200bc83fa81=1465354426'

}

url1='http://www.shclearing.com/xxpl/fxpl/index.html'

url2=['http://www.shclearing.com/xxpl/fxpl/index_{}.html'.format(str(i)) for i in range(1,5,1)]

url2.insert(0,url1)

links=[]

host='http://www.shclearing.com/xxpl/fxpl/'

def get_link_list(url):

for item in url:

web_data=requests.get(item)

soup=BeautifulSoup(web_data.text,'lxml')

list=soup.select('ul.list li a')

for item in list:

link=host+item.get('href').split('./')[1]

links.append(link)

FileName=[]

DownName=[]

DownName1=[] #DownName1用于存放转码后的名称

def get_contents(link):

web_data=requests.get(link)

soup=BeautifulSoup(web_data.text,'lxml')

contents=soup.select('#content > div.attachments > script')[0].get_text()

a=str(re.findall(r"fileNames = '(.*?)'",contents,re.M)[0])

b=str(re.findall(r"descNames = '(.*?)'",contents,re.M)[0])

FileName=a.replace('./','').split(';;')

DownName=b.split(';;') #先用正则表达式提取出后面post中要用到的两个参数,但是要将中文转化为对应的URL编码

for item in DownName:

a=parse.quote(item)

DownName1.append(a)

print(FileName,'\\n',DownName,'\\n',DownName1)

for i,j,k in zip(FileName,DownName1,DownName):

download_file(i,j,k)

# link='http://www.shclearing.com/xxpl/fxpl/cp/201606/t20160608_159680.html'

# get_contents(link)

# print('The pdf have been downloaded successfully !')

def download_file(a,b,c):

data={

'FileName':a,

'DownName':b }

local_filename = c

post_url='http://www.shclearing.com/wcm/shch/pages/client/download/download.jsp'

time.sleep(0.5) #限制下载的频次速度,以免被封

# NOTE the stream=True parameter

r = requests.post(post_url, data=data, headers=headers, stream=True)

with open(local_filename, 'wb') as f:

for chunk in r.iter_content(chunk_size=1024): # 1024 是一个比较随意的数,表示分几个片段传输数据。

if chunk: # filter out keep-alive new chunks

f.write(chunk)

f.flush() #刷新也很重要,实时保证一点点的写入。

return local_filename

if __name__=='__main__':

get_link_list(url2)

pool=Pool()

pool.map(get_contents,links)

print('The documents have been downloaded successfully !')

如果要将下载下来的文档的保存的路径存入mysql中,需要再加上下面的语句:

#conn=pymysql.connect(host='localhost',user='root',passwd='root',db='mysql',charset='utf8')

#cursor = conn.cursor()

#cursor.execute('CREATE TABLE root (id int auto_increment primary key,content varchar(100))')

以及在download_file(a,b,c)函数中的return local_filename语句前加上:

cursor.execute('insert into root(content) values (%s)',local_filename)

cebf539f04d8

抓取结果截图.PNG

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值