爬虫一些常用代码的记录,根据URL下载文件,


写了一个GK2A卫星数据爬取的程序,本身不难,记录下小知识。

根据URL下载文件,有些需要cookie,大文件下载防止文件损坏

    headers = {
        "Content-Type": ContentType,
        "User-Agent": UA,
        "Cookie": cookie
    }
    response = requests.get(uri, headers = headers,stream=True)
    with open(the_file_path, "wb") as fp:
        for chunk in response.iter_content(chunk_size=1024*2):
            if chunk:
                fp.write(chunk)

 

下载zip包,zip包解压

    zipname = f"{static_uri_path[flag]}_{type}.zip"#压缩包名
    the_file_path = os.path.join(file_path, zipname)#压缩文件地址
    the_file_URL = f"{first_URL}{static_uri_path[flag]}&fileName={static_uri_path[flag]}.zip"#要下载的连接
    try:
        request_file(the_file_URL, cookie, the_file_path)#下载函数
        print(the_file_URL, the_file_path)
        
        
        #以下是zip操作
        zip_file = zipfile.ZipFile(the_file_path)#对压缩包地址操作
        zip_list = zip_file.namelist()  # 得到压缩包里所有的文件
        for f in zip_list:
            zip_file.extract(f, file_path)  # 循环解压文件到指定目录
        zip_file.close()  # 关闭文件,必须有,释放内存
    except Exception as exc:
        print("下载与解压错误", exc)

 

清理空白文件夹和压缩包

def dir_arrange(file_path):
    """
    整理文件到指定目录
    并删除空白文件夹
    """
    dirpath = rf"{file_path}\work\00" #要删除的文件路径
    filelist = os.listdir(dirpath)
    allfile = []
    for file in filelist:
        allfile.append(dirpath + '/' + file)
    for file in allfile:
        shutil.move(file,file_path) #把文件夹内文件移走
    os.removedirs(dirpath)
    print("已删除空白文件夹!")

    for files in os.listdir(file_path):
        if files.endswith(".zip"):
            os.remove(os.path.join(file_path, files))#删除zip文件
    print("已删除zip文件!")

 

用正则表达式的方式提取cookie,正则的方式应用广泛

import re
SCOUTER = re.split('[,;]',response.headers['Set-Cookie'])[2].strip()#正则提取,通过,;进行分隔,并去空格

也可以用split连写,达成同样效果

remberuser = response.headers['Set-Cookie'].split(";")[3].split(",")[1].strip()

 

已经下载的文件排列顺序会按照0,1,10,11,19,2,20,21的顺序,不满足需求,需要排序

contents = show_files(traversal_file, [])  # 循环打印show_files函数返回的文件名列表
contents.sort(key=lambda x: int(re.split('[._]',x)[3]))#按照数字顺序排序,re部分是正则表达式写法,整个int()内是文件名的数字部分即可

 

运用tqdm,实现等待时间读条

import tqdm
for i in tqdm(range(120),desc='等待缓存中'):#共120秒
    time.sleep(1)#每1秒走一次

 对于文件,tqdm下载时的进度显示

from tqdm import tqdm
import requests
url='https://dldir1.qq.com/qqtv/TencentVideo11.14.4043.0.exe'
response=requests.get(url,stream=True) # 设stream流传输方式为真
print(response.headers) # 打印查看基本头信息
data_size=round(int(response.headers['Content-Length'])/1024/1024) # 字节/1024/1024=MB,加上round上取整可以避免一种报错
with open('测试.exe','wb') as f:#测试.exe是路径下要命名的文件
    for data in tqdm(iterable=response.iter_content(1024*1024),total=data_size,desc='正在下载',unit='MB'):
        f.write(data)
"""
将iter_content(chunk_size)->chunk_size理解为一个列表的容量,
而iterable=response.iter_content(1024*1024)理解为分割字符串的函数,
将response.content分割为每个元素的长度是1024*1024大小的列表,在对每个部分进行下载。
这只是助于理解chunk_size的一个方法
而response.iter_content 是流传输(简单说就是边下载边写入磁盘),如果将chunk_size设置的很小,意味着每次
下载和存在很小的一部分,下载的速度也会很慢,如果设置的很大,则进度条的进度会错乱,因此我们在确定chunk_size
大小的时候应该对应文件大小,data_size除以多少,chunk_size就乘以多少,才能使进度条对应。
"""

 

一种从json格式中提取文件列表的简洁写法

data_list = response.json()
filesize_list = [data["fileSize"] for data in data_list["data"]]#把data中的所有fileSize数据存入到列表中

进阶写法

page_uri_list = [[data["picPath1"], data["videoPath1"], data["address"] ] for data in data_list] #从Json中读取三种数据,以元组的形式保存进列表
static_uri_path.extend(page_uri_list)#在while循环中,合并到一个整体列表中

for index, (img_uri, video_uri, address) in enumerate(static_uri_path , start=index_):
    #static_uri_path中有三个元素,分别读取
    #加入index序列循环
    #start可以设定初始值
    if img_uri is not None :
        abs_img_path = os.path.join(imgs_path, f"{d_date.split('-')[0]}_{d_date.split('-')[1]}_{d_date.split('-')[2]}_{index}.jpeg")
        request_file(img_uri, abs_img_path)
        print(abs_img_path)
    if video_uri is not None and IS_VIDEO:
        abs_video_path = os.path.join(videos_path, f"{d_date.split('-')[0]}_{d_date.split('-')[1]}_{d_date.split('-')[2]}_{index}.mp4")
        request_file(video_uri, abs_video_path)
    

 

Xpath路径读取的一些相关操作

headers = {
        "Cookie": abs_cookies,
        "User-Agent": UA
    }
    response = requests.get(f"http://219.239.221.20:8088/cffm20/Monitoring/Details/{imageId}", headers=headers).text
    tree = etree.HTML(response)
    mar_b_10_div = tree.xpath('//div[@class="pad_15 jbxx_section"]/div[@class="clearfix mar_b_10"]')
    #选取所有div元素,是拥有"pad_15 jbxx_section"class属性的div元素中的拥有"clearfix mar_b_10"class属性的所有div元素
    img_url = mar_b_10_div[1].xpath("./div[2]/a/@href")[0]#最后这个[0],加的话是读取列表中元素,不加的话是个列表
    txt_url = mar_b_10_div[2].xpath("./div[2]/a/@href")[0]
    #./是当前目录,当前目录下第2个div元素,div中的a元素,然后选取a元素中所有的href属性

    clearfix_mar_b_10_div = tree.xpath('//div[@class= "pad_15 tpxx_section"]/div[@class = "clearfix mar_b_10"]')
    file_date = clearfix_mar_b_10_div[3].xpath("./div[2]/text()")[0]  #text()可以获得><之间的标签,

 

评论关闭