- 1. 页面分析
- 2.代码大体构思
- 3.源码分析
- 3.1 完成效果
- 4.异步协程的优势
- 5.难点分析
- 6.可扩展性
- 欢迎私信或评论区交流
爬取网址 : https://www.bcy.net/item/detail/7086637143778401318
1、免职申明 :内容仅供参考学习使用,侵删
2、图片可能存在侵权风险均打码处理 望谅解 1. 页面分析
1.查看原页面
2.查看响应数据源码页面
3.查看是否为ajax异步加载
经判断非异步加载
翻看源代码,发现图片来源于源码中js渲染如下图:
太长截不完,明白就行
懒得画流程图了将就看【笑】
实现很简单
"""
函数共6个:
get_img_src(url) # 获取网页标题及图片地址
check_title(title) # 修改文件夹标题以符合windows文件夹的命名规范
download_img(session, url, path) # 异步函数爬取图片
run_tasks(task_list) # 执行异步任务
error_download(url, path) # 异步任务错误的图片重新爬取
main(url) # 主函数
"""
3.源码分析
# 目标 :https://www.bcy.net/item/detail/7086637143778401318
import os
import re
import time
import js2py
import requests
from bs4 import BeautifulSoup
import ua
import asyncio
import aiohttp
error_src_list = list()
def get_img_src(url):
response = requests.get(url, headers=ua.headers())
response.encoding = 'utf-8'
html = response.text
soup = BeautifulSoup(html, 'lxml')
title = check_title(soup.find('title').string)
script = 'var window = Object();%s;function show(){return window.__ssr_data}' % soup.find_all('script')[-5].string
js = js2py.EvalJs()
js.execute(script)
result = js.show()
img_src_list = [i['original_path'] for i in result['detail']['post_data']['multi']]
return [title, img_src_list]
"""
get_img_src(url)
获取网页源代码
BeautifulSoup()解析网页
script 重构js代码
运行js代码{
可以使用的方法:
1.调用node.js :麻烦
2.使用execjs库 :问题:兼容性不佳,编码问题,速度慢
3.使用js2py库:问题:兼容性不佳, 速度中等
......
还有很多 自己搜索
}
"""
def check_title(title):
rep = re.compile(r'[\\/:*?"<>|\r\n]+')
change_name = rep.findall(title)
if change_name:
name = ''
for i in change_name:
name = title.replace(i, "_")
return name
else:
return title
"""
check_title(title)
修改标题
正则查找,遍历修改
"""
async def download_img(session, url, path):
async with semaphore:
async with session.get(url, headers=ua.headers()) as response:
if response.status == 200:
with open(path, 'wb') as f:
while True:
buffer = await response.content.read(4096)
if not buffer:
break
f.write(buffer)
f.flush()
print('成功 : ' + url)
else:
print('失败 : ' + url)
error_src_list.append([url, path])
"""
def download_img(session, url, path)
异步函数不会的自学
"""
async def run_tasks(task_list):
async with aiohttp.ClientSession() as session:
title = task_list[0]
try:
os.mkdir(f'./img/{title}')
except os.error:
pass
urls = task_list[1]
tasks = [download_img(session, url, './img/{}/{}.jpg'.format(title, p)) for p, url in enumerate(urls)]
await asyncio.wait(tasks)
"""
run_tasks(task_list)
异步函数
aiohttp库重点
异步中无法使用requests库
不会的自学
"""
def error_download(url, path):
response = requests.get(url, headers=ua.headers(), stream=True)
if response.status_code == 200:
with open(path, 'wb') as f:
for data in response.iter_content(4096):
f.write(data)
f.flush()
print('重试成功 : ' + url)
else:
time.sleep(5)
error_download(url, path)
"""
error_download(url, path)
失败后重新下载
异步高并发,同时请求大量数据会失败
失败后添加到error_src_list列表异步协程任务完成后调用普通下载
"""
def main(url):
tasks_list = get_img_src(url)
loop = asyncio.get_event_loop()
loop.run_until_complete(run_tasks(tasks_list))
for url, path in error_src_list:
error_download(url, path)
"""
main()
获取任务列表运行协程任务
"""
if __name__ == '__main__':
semaphore = asyncio.Semaphore(50) # 控制任务并发数
main('https://www.bcy.net/item/detail/7086637143778401318')
3.1 完成效果
4.异步协程的优势
协程本质上是个单进程,协程相对于多进程来说,无需线程上下文切换的开销,无需原子 *** 作锁定及同步的开销,编程模型也非常简单。
我们可以使用协程来实现异步 *** 作,比如在网络爬虫场景下,我们发出一个请求之后,需要等待一定的时间才能得到响应,但其实在这个等待过程中,程序可以干许多其他的事情,等到响应得到之后才切换回来继续处理,这样可以充分利用 CPU 和其他资源,这就是异步协程的优势。
1.寻找图片出处
2.解析源码运行js代码获得json数据,提取列表
3.异步协程的实现及错误后的重试
6.可扩展性可以把总任务数量增加
爬取日榜, 周榜,单独标签爬取
# 伪代码
# 一个函数 爬取日榜,周榜的链接地址
# 一个函数 循环 给main()函数传递任务
还可以连接数据库传入任务给主函数
# 伪代码
# 一个函数 连接数据库读取数据
# 一个函数 循环 给main()传递任务
欢迎私信或评论区交流
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)