江川~ 2022-04-09 22:19 采纳率: 100%
浏览 55
已结题

关于python 爬虫 项目 多线程的问题!

问题遇到的现象和发生背景

程序运行的比较慢,想要提速。能帮忙封装一下就最好了

相关代码
 ```python

# 多线程头像抓取
# 封装函数 并完美运行

import requests
from lxml import etree
import os
import threading
import time

def get_respose_text(url):
    #通过url 获取 respose 文本
    global session
    session = requests.sessions.Session()
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36'

    }
    response = session.get(url=url, headers=headers)
    response.encoding = "utf-8"

    return response.text

def get_Date(response,a_urls_xpath,a_names_xpath):
    #抓取并返回 子链接,名称字典
    html = etree.HTML(response)
    a_urls = html.xpath(a_urls_xpath)  # 抓取<a>标签
    a_names = html.xpath(a_names_xpath)

    new_a_urls = {}
    for (a_url, a_name) in zip(a_urls, a_names):
        a_name = a_name.text
        a_url = index_url + a_url
        new_a_urls[a_name] = a_url #将子链接以及对应名称放入字典

    return new_a_urls

def save_date(src, s_path):
    # 保存一个数据
    src = "https:" + src
    src_name = src[-17:-13]
    src_path = s_path + '\%s.%s' % (src_name, src.split('.')[-1])
    src_date = session.get(src)
    with open(src_path, 'wb')as f:
        f.write(src_date.content)
        print("正在下载     >>>     %s" % src_path)

def url_name_replace(url_name):
    url_name = url_name.replace(' ','')
    url_name = url_name.replace('/', '')
    url_name = url_name.replace(':', '')
    url_name = url_name.replace('?', '')
    url_name = url_name.replace(',', '')
    url_name = url_name.replace('·', '')
    url_name = url_name.replace("‘", '')
    url_name = url_name.replace('”', '')
    url_name = url_name.replace('|', '')
    url_name = url_name.replace('?', '')
    url_name = url_name.replace('', '')
    url_name = url_name.replace('"', '')
    url_name = url_name.replace('<', '')
    url_name = url_name.replace('>', '')
    url_name = url_name.replace(':',"")
    url_name = url_name.replace('.','')


    return  url_name

def multi_thread(srcs, s_path):
    # 多线程
    threads = []
    for src in srcs:
        threads.append(
            threading.Thread(target=save_date, args=(src, s_path))
        )
    for thread in threads:
        thread.start()

    for thread in threads:
        thread.join()

def single_thread(srcs,s_path):
    #单线程
    for src in srcs :
        save_date(src,s_path)




def main():
    global  index_url
    index_url = "https://www.woyaogexing.com"
    #1.爬取主页面
    index_respose = get_respose_text(index_url)

    # 2.根据主页面响应抓取 数据
    urls = get_Date(index_respose,'//*[@id="indexMain"]/div[1]/div[1]/div[3]/div/a/@href','//*[@id="indexMain"]/div[1]/div[1]/div[3]/div/a')
    print(urls)

    for i,n in  urls.items():
        # 3.创建第一层目录
        i = url_name_replace(i)
        save_path = str(os.getcwd()) + r"\%s" % i
        if os.path.exists(save_path) == False:
            os.mkdir(save_path)
        print("在 %s 目录下保存数据" % save_path)

        #抓取第第一层页面下 数据
        list2_respose = get_respose_text(n)
        urls_1 = get_Date(list2_respose,'//*[@id="main"]/div[3]/div[1]/div[2]/div[*]/a[2]/@href','//*[@id="main"]/div[3]/div[1]/div[2]/div[*]/a[2]')
        # print(urls_1)

        for j,k in urls_1.items():
            #创建第二层目录
            j = url_name_replace(j)
            save_path1 = save_path + r"\%s" % j
            if os.path.exists(save_path1) == False:
                os.mkdir(save_path1)

            #抓取第三层节目的数据
            list3_respose = get_respose_text(k)
            html = etree.HTML(list3_respose)
            image_srcs = html.xpath('//*[@id="main"]/div[3]/div[1]/div[1]/ul/li[*]/a/img/@src')

            #多线程保存
            multi_thread(image_srcs,save_path1)

            #单线程保存
            # single_thread(image_srcs,save_path1)


if __name__ == '__main__':
    start = time.time()
    main()
    end = time.time()
    print("总运行时间为:%d",end-start,"秒")
# 多线程总运行时间为:%d 59.41753435134888 秒
# 单线程总运行时间为:%d 96.5646162033081 秒


  • 写回答

2条回答 默认 最新

  • ningzip 2022-04-09 22:32
    关注

    用pypy,namba(需重构,加装饰器),cython(需重构,显式声明类型)
    用正则表达式更快,但适用性会降低
    灵活运用异步
    减少中间值的使用
    少用for循环
    控制线程数量,考虑协程、多进程,因为有GIL的存在,python的多线程无法发挥和其他语言一样的(理论上的)效果
    导入库的时候注意使用from ... import ...,如非必要,不全导入
    格式化字符串用f"string"更快

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 4月19日
  • 已采纳回答 4月11日
  • 创建了问题 4月9日

悬赏问题

  • ¥50 gki vendor hook
  • ¥15 centos7中sudo命令无法使用
  • ¥15 灰狼算法和蚁群算法如何结合
  • ¥15 这是一个利用ESP32自带按键和LED控制的录像代码,编译过程出现问题,请解决并且指出错误,指导如何处理 ,协助完成代码并上传代码
  • ¥20 stm32f103,hal库 hal_usart_receive函数接收不到数据。
  • ¥20 求结果和代码,sas利用OPTEX程序和D-efficiency生成正交集
  • ¥50 adb连接不到手机是怎么回事?
  • ¥20 抓取数据时发生错误: get_mooncake_data() missing 1 required positional argument: 'driver'的问题,怎么改出正确的爬虫代码?
  • ¥15 vs2022无法联网
  • ¥15 TCP的客户端和服务器的互联