Python学习笔记-遍历URL链接文件多线程下载

 

功能代码记录:

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

import os
import sys
import time
import urllib
import Queue
import random
import requests
import threading
import threadpool
from bs4 import BeautifulSoup

default_encoding = 'utf-8'
if sys.getdefaultencoding() != default_encoding:
    reload(sys)
    sys.setdefaultencoding(default_encoding)

DOWNLOAD_DIR = '/home/xxxxxx/files'
ROOT_URL = 'https://www.xxxxxx.org/file/'
FILE_SIZE_LIMIT = 10 * 1024 * 1024


class Task(threading.Thread):

    def __init__(self, t_index, input_queue, error_queue):
        super(Task, self).__init__()
        self.thread_name = "task-%s" % t_index
        self.input_queue = input_queue
        self.error_queue = error_queue
        self.daemon = True

    def run(self):
        while True:
            try:
                print '%s run task!' % self.thread_name
                func, args = self.input_queue.get(block=False)
            except Queue.Empty:
                break
            try:
                func(*args)
            except Exception as e:
                self.error_queue.put((func, args, str(e)))
        print "%s finished!" % self.thread_name


class TaskPool(object):

    def __init__(self, size):
        self.input_queue = Queue.Queue()
        self.error_queue = Queue.Queue()
        self.tasks = [Task(i, self.input_queue, self.error_queue) for i in range(size)]

    def add_task(self, func, args):
        if not isinstance(args, tuple):
            raise TypeError('args must be tuple type!')
        self.input_queue.put((func, args))

    def add_tasks(self, tasks):
        if not isinstance(tasks, list):
            raise TypeError('tasks must be list type!')
        for (func, args) in tasks:
            self.add_task(func, args)

    def get_error_result(self):
        while not self.error_queue.empty():
            func, args, msg = self.error_queue.get()
            print "error result func %s args %s msg %s" % (func, args, msg)

    def run(self):
        print len(self.tasks)
        for task in self.tasks:
            task.run()
        for task in self.tasks:
            if task.isAlive():
                task.join()


def find_download_url(parent_url, download_url_list):
    resp = requests.get(parent_url)
    if resp.ok:
        html = BeautifulSoup(resp.content, 'html.parser')
        a_tags = html.select('pre a')
        start_tag = 0
        for a_tag in a_tags:
            start_tag = start_tag + 1
            path = parent_url + str(a_tag.text)
            print '%s %s' % (start_tag, path)
            if path.endswith('../'):
                continue
            elif path.endswith('/'):
                print '%s continue finding' % path
                find_download_url(path, download_url_list)
            else:
                download_url_list.append(parent_url + str(a_tag['href']))


def download_url_link(download_url):
    download_url = str(download_url).strip()
    print 'start download url link %s' % download_url
    resp = requests.get(download_url)
    if resp.ok:
        file_size = long(resp.headers['content-length'])
        if file_size > FILE_SIZE_LIMIT:
            return
        download_url_suffix = download_url.replace(ROOT_URL, '')
        last_index = download_url_suffix.rindex('/')
        download_dir = DOWNLOAD_DIR + download_url_suffix[:last_index + 1]
        if not os.path.exists(download_dir):
            os.makedirs(download_dir)
        with open(DOWNLOAD_DIR + download_url_suffix, 'wb') as df:
            df.write(resp.content)
        #urllib.urlretrieve(download_url, filename=DOWNLOAD_DIR + download_url_suffix)
    else:
        print resp.status_code
        print resp.content


def gen_download_url_txt():
    download_url_list = []
    find_download_url(ROOT_URL, download_url_list)
    with open('/home/xxxx/project/xxxxxx/download_url.txt', 'wb') as df:
        for download_url in download_url_list:
            print download_url
            df.write(download_url)
            df.write('\n')


if __name__ == '__main__':
    # taskPool = TaskPool(5)
    # with open('/home/xxxx/project/xxxxxx/download_url.txt', 'r') as df:
    #     for download_url in df.readlines():
    #         taskPool.add_task(download_url_link, (download_url,))
    # taskPool.run()
    # taskPool.get_error_result()

    taskPool = threadpool.ThreadPool(5)
    args_list = []
    with open('/home/xxxx/project/xxxxxx/download_url.txt', 'r') as df:
        for download_url in df.readlines():
            args_list.append(download_url)
    request_list = threadpool.makeRequests(download_url_link, args_list, None)
    [taskPool.putRequest(request) for request in request_list]
    taskPool.wait()

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 Python 的 `threading` 模块来实现多线程遍历和处理文件。 首先,需要将文件遍历的任务分解成多个子任务,然后将这些子任务分配给不同的线程来执行。可以使用 Python 的 `Queue` 来实现任务队列,每个子任务就是一个文件名,可以将文件名压入任务队列中。 接下来,创建多个线程,每个线程从任务队列中取出一个任务,处理完后再取下一个任务,直到任务队列为空。可以使用 Python 的 `threading` 模块来创建线程,将任务队列作为参数传递给线程函数。 下面是一个简单的示例代码: ```python import os import threading from queue import Queue # 定义线程数 THREAD_COUNT = 4 # 定义任务队列 task_queue = Queue() # 定义线程函数 def process_file(): while True: # 从队列中取出一个任务 file_name = task_queue.get() if file_name is None: # 如果任务队列为空,线程退出 break # 处理文件 with open(file_name, 'r') as f: # TODO: 处理文件内容 pass # 标记任务完成 task_queue.task_done() # 遍历文件目录,将文件名压入任务队列 def walk_dir(dir_path): for root, dirs, files in os.walk(dir_path): for file_name in files: task_queue.put(os.path.join(root, file_name)) if __name__ == '__main__': # 创建线程 threads = [] for i in range(THREAD_COUNT): thread = threading.Thread(target=process_file) threads.append(thread) thread.start() # 遍历文件目录,将文件名压入任务队列 walk_dir('/path/to/your/directory') # 等待任务队列中所有任务完成 task_queue.join() # 停止线程 for i in range(THREAD_COUNT): task_queue.put(None) for thread in threads: thread.join() ``` 在上面的示例代码中,首先定义了线程数和任务队列。然后定义了线程函数 `process_file`,该函数从任务队列中取出一个任务(即文件名),处理文件内容,然后标记任务完成。接下来,遍历文件目录,将文件名压入任务队列中。然后创建多个线程,每个线程从任务队列中取出一个任务,处理完后再取下一个任务,直到任务队列为空。最后,等待任务队列中所有任务完成,停止线程。 需要注意的是,在多线程处理文件时,需要考虑文件的并发读写问题。可以使用 Python 的 `with open(file_name, 'r') as f:` 语句来打开文件,这样可以确保文件在使用完毕后会被自动关闭。另外,如果需要对文件进行写操作,可以使用 Python 的 `with open(file_name, 'w') as f:` 语句,并且在写操作时需要使用线程锁来确保文件的独占性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值