Python异步编程--获取girlypic写真集

2023-11-07 03:36

本文主要是介绍Python异步编程--获取girlypic写真集,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在日常生活中,无论是网络配置、文件整理、web开发还是工具,时常用到Python写些脚本。

这次主要是分享下异步编程的经验,就拿获取girlypic的图片举例吧,也希望能给一些同学带来思考。

  • 使用argparse而不是os.args,这个库能够优雅地获取命令行参数,不再需要os.args判断个数或者类型。
  • 使用pathlib而不是os.path,这个库能够高效地处理各种文件操作,创建、修改、删除、路径拼接等。
  • 使用logging而不是print,个人更加习惯用日志的方式打印信息。
  • 使用aiohttp而不是requests,当你决定用异步的方式发送网络请求时,就用这个库吧。
  • 使用aiofiles而不是open,当你决定用异步的方式读写文件时,就用这个库吧。
  • 使用lxml,这个库能够使用Xpath语法帮助我们解析html内容。
  • 使用asyncio.create_task而不是for循环,当一组任务不是顺序相关时,不必循环await执行,通过创建任务的方式异步执行。
  • 使用类型提示,标注变量的类型,方便IDE检索。

以上是常用的库或者提示,没有好坏之分,主要是看个人的习惯,一旦一处异步,那就处处异步

Python版本

当前稳定版本是:3.10.11

Python依赖

aiohttp==3.8.6
aiofiles==23.2.1
lxml==4.9.3

Python源码

import asyncio
import logging
import argparse
from pathlib import Pathimport aiohttp
import aiofiles
from lxml import etreelogger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(console)PROXY = "http://127.0.0.1:10808"
SAVE_FOLDER = Path("Downloads")
PICTURE_HOST = "https://girlygirlpic.com"
PICTURE_GATHER = PICTURE_HOST + "/ax/"
PICTURE_SEARCH = PICTURE_HOST + "/sx/"
PICTURE_URL = '//div[@class="post-media-body"]//a[@class="figure-link os-lightbox-activator"]/@href'
ALBUM_NAMES = '//div[@class="post-content-body"]/h4[@class="post-title entry-title"]/a[@class="on-popunder"]'
HEADER = {"Origin": PICTURE_HOST,"Connection": "close","Cookie": "_user_language=Cn","X-Requested-With": "XMLHttpRequest","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0"
}async def download_picture(url: str, save_folder: Path) -> None:async with aiohttp.ClientSession() as session:try:async with session.get(url, proxy=PROXY, headers=HEADER) as response:picture_name = url[url.rfind("/") + 1:]async with aiofiles.open(save_folder / picture_name, "wb") as handle:async for chunk in response.content.iter_chunked(1024):await handle.write(chunk)except Exception as exception:logger.error(f"{exception} [URL] {url}")async def parse_album(url: str, save_folder: Path) -> None:album_id = url[url.rfind("/") + 1:]header = {**HEADER, **{"Referer": url}}async with aiohttp.ClientSession() as session:requests_body = {"album_id": album_id}async with session.post(PICTURE_GATHER, json=requests_body, proxy=PROXY, headers=header) as response:html_content = await response.text()image_href = etree.HTML(html_content).xpath(PICTURE_URL)logger.info(f"{len(image_href):03d} photos of album [{save_folder.name}]")task_list = [asyncio.create_task(download_picture(pic_url, save_folder)) for pic_url in image_href]await asyncio.wait(task_list) if len(task_list) > 0 else Nonelogger.info(f"album saved [{save_folder.name}]")async def get_albums(name: str) -> None:async with aiohttp.ClientSession() as session:requests_body = {"search_keys_tag": name}async with session.post(PICTURE_SEARCH, json=requests_body, proxy=PROXY, headers=HEADER) as response:html_content = await response.text()album_content = etree.HTML(html_content).xpath(ALBUM_NAMES)logger.info(f"{len(album_content):03d} albums about {name}")task_list = []for album in album_content:href = album.get("href")text = album.textsave_folder = SAVE_FOLDER / name / textsave_folder.mkdir(parents=True) if not save_folder.exists() else Nonetask_list.append(asyncio.create_task(parse_album(href, save_folder)))await asyncio.wait(task_list) if len(task_list) > 0 else Noneasync def main(names: [str]) -> None:await asyncio.wait([asyncio.create_task(get_albums(name)) for name in names])logger.info("done")if __name__ == "__main__":parser = argparse.ArgumentParser(description="download pictures")parser.add_argument("name", type=str, nargs='+', help="girls name list")args = parser.parse_args()asyncio.run(main(args.name))

其中PICTURE_HOST就是域名,需要科学访问,所以PROXY自己配置吧。

运行方法很简单:python main.py xxxx xxxx xxxx,其中xxxx为姓名,多个人名按照空格隔开。

获取完毕后会在当前创建一个Downloads目录,图片会按照姓名以及相册名归类在里面。

运行结果

这就是异步的魅力,同步的方式只能一次发送一个请求,然后阻塞在网络IO上,异步则会在这种情况下让出CPU资源执行其他的代码。

效果图不方便放,大家可以自己试试

图片过多,访问过于频繁时,请求有可能会被BAN,所以可以适当地延迟下载任务,由于是异步,就不要用time.sleep()了,而是要用asyncio.sleep()

这篇关于Python异步编程--获取girlypic写真集的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/360972

相关文章

python中各种常见文件的读写操作与类型转换详细指南

《python中各种常见文件的读写操作与类型转换详细指南》这篇文章主要为大家详细介绍了python中各种常见文件(txt,xls,csv,sql,二进制文件)的读写操作与类型转换,感兴趣的小伙伴可以跟... 目录1.文件txt读写标准用法1.1写入文件1.2读取文件2. 二进制文件读取3. 大文件读取3.1

使用Python实现一个优雅的异步定时器

《使用Python实现一个优雅的异步定时器》在Python中实现定时器功能是一个常见需求,尤其是在需要周期性执行任务的场景下,本文给大家介绍了基于asyncio和threading模块,可扩展的异步定... 目录需求背景代码1. 单例事件循环的实现2. 事件循环的运行与关闭3. 定时器核心逻辑4. 启动与停

基于Python实现读取嵌套压缩包下文件的方法

《基于Python实现读取嵌套压缩包下文件的方法》工作中遇到的问题,需要用Python实现嵌套压缩包下文件读取,本文给大家介绍了详细的解决方法,并有相关的代码示例供大家参考,需要的朋友可以参考下... 目录思路完整代码代码优化思路打开外层zip压缩包并遍历文件:使用with zipfile.ZipFil

Python处理函数调用超时的四种方法

《Python处理函数调用超时的四种方法》在实际开发过程中,我们可能会遇到一些场景,需要对函数的执行时间进行限制,例如,当一个函数执行时间过长时,可能会导致程序卡顿、资源占用过高,因此,在某些情况下,... 目录前言func-timeout1. 安装 func-timeout2. 基本用法自定义进程subp

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4:

Python运行中频繁出现Restart提示的解决办法

《Python运行中频繁出现Restart提示的解决办法》在编程的世界里,遇到各种奇怪的问题是家常便饭,但是,当你的Python程序在运行过程中频繁出现“Restart”提示时,这可能不仅仅是令人头疼... 目录问题描述代码示例无限循环递归调用内存泄漏解决方案1. 检查代码逻辑无限循环递归调用内存泄漏2.