先取网站一页的url进行观察:
https://www.vilipix.com/ranking?date=20220122&mode=daily&p=2
可以发现,是由四部分组成,简单拆分一下:
base_url=https://www.vilipix.com 日期 date 榜单类型mode 页码p
于是可以构造url为:
url = f'{base_url}/ranking?date={today_str}&mode=daily&p={page}'
'''
base_url:https://www.vilipix.com
today_str:获取当天网站榜单日期
page:榜单页码
'''
可以定义一个函数,用于页面的爬取:
def scrap_page(url):
try:
response = requests.get(url=url, headers=ua_random())
if response.status_code == 200:
response.encoding = 'utf-8' #提前了解到网页的编码格式,所以直接写
return response.text
except requests.RequestException:
print(f'{url}不可爬取!')
函数返回的是页面的爬取结果
爬取到页面,但信息有很多,需要筛选出对自己有用的信息
这里也可以构建一个函数来完成
def parse_index(html):
doc = pq(html)
links = doc('#__layout .illust-content li .illust a')
for link in links.items():
href = link.attr('href')
name = href.split('/')[-1] # 详情页名字,由图片id构成,以防重名
detail_url = urljoin(base_url, href) # 详情页url
page_count = link('.page-count span').text()
yield detail_url, page_count, name
对于yield的用法,这位博主讲的很清晰,有需要的小伙伴可以参考一下:
这个函数写的时候是最后写的,但是后来完善代码的时候,被提前调用了,就先写出来了,非常的简单,且很实用。
def download(path, name, image):
save_path = path + name + '.jpg'
with open(save_path, 'wb') as f:
f.write(image)
path:图片下载的目标文件夹路径 name:文件名 image:需要下载的图片
在第三步时,对页面进行处理得到的链接,访问即可得到详情页。
对于详情页的处理,分为两部分:
①、仅含一张图片
②、含有多张图片
什么意思呢?下图来说明一下:
右上角,有数字的为第②种情况,没数字的则为第①种情况。
为什么要分类呢?
为了容易区分,我是将含多张图片详情页中获取的图片放在一个文件夹里,详细可见后续。
函数如下:
def detail_index_1(html, name, path):
doc = pq(html)
link = doc('.illust-pages li a img').attr('src')
image = requests.get(url=link, headers=ua_random()).content # 将要下载的图片
download(path, name, image) # 调用下载函数
def detail_index_more(html, name, path):
doc = pq(html)
links = doc('.illust-pages li a img')
i = 1
for link in links.items():
src = link.attr('src')
image_name = name + f'_{i}' # 进行图片命名
image = requests.get(url=src, headers=ua_random()).content # 将要下载的图片
download(path, image_name, image) # 调用下载函数
i += 1
html:页面解析的结果
path:图片下载的目标文件夹路径 name:文件名
# -*- coding: UTF-8 -*-
"""
# @Time: 2022/1/22 16:43
# @Author: 远方的星
# @CSDN: https://blog.csdn.net/qq_44921056
"""
import requests
from pyquery import PyQuery as pq
from fake_useragent import UserAgent
import os
import datetime
from urllib.parse import urljoin
from concurrent.futures import ThreadPoolExecutor
# 随机请求头
ua = UserAgent(verify_ssl=False, path='D:/Pycharm/fake_useragent.json')
# 网站url
base_url = 'https://www.vilipix.com'
# 获取当前日期
today = datetime.date.today()
# 获取昨天的日期,并用于构建url
today_str = (datetime.date.today() + datetime.timedelta(days=-1)).strftime('%Y%m%d')
# 分布创建属于当日榜单的文件夹
path_1 = 'D:/vilipix每日榜单'
if not os.path.exists(path_1):
os.mkdir(path_1)
path_2 = f'D:/vilipix每日榜单/{today}/'
if not os.path.exists(path_2):
os.mkdir(path_2)
def ua_random():
headers = {
'use_agent': ua.random
}
return headers
def scrap_page(url):
try:
response = requests.get(url=url, headers=ua_random())
if response.status_code == 200:
response.encoding = 'utf-8'
return response.text
except requests.RequestException:
print(f'{url}不可爬取!')
def scrap_index(page):
url = f'{base_url}/ranking?date={today_str}&mode=daily&p={page}'
'''
base_url:https://www.vilipix.com
today_str:获取当天网站榜单日期
page:榜单页码
'''
return scrap_page(url)
# 对页面进行解析
def parse_index(html):
doc = pq(html)
links = doc('#__layout .illust-content li .illust a')
for link in links.items():
href = link.attr('href')
name = href.split('/')[-1] # 详情页名字,由图片id构成,以防重名
detail_url = urljoin(base_url, href) # 详情页url
page_count = link('.page-count span').text()
# print(page_count)
yield detail_url, page_count, name
# 下载图片
def download(path, name, image):
save_path = path + name + '.jpg'
# print(save_path)
with open(save_path, 'wb') as f:
f.write(image)
# 详情页内仅有一张图片时调用
def detail_index_1(html, name, path):
doc = pq(html)
link = doc('.illust-pages li a img').attr('src')
image = requests.get(url=link, headers=ua_random()).content
download(path, name, image)
# 详情页内有超过一张图片时调用
def detail_index_more(html, name, path):
doc = pq(html)
links = doc('.illust-pages li a img')
i = 1
for link in links.items():
src = link.attr('src')
image_name = name + f'_{i}'
image = requests.get(url=src, headers=ua_random()).content
download(path, image_name, image)
i += 1
def main(page):
html = scrap_index(page)
details = parse_index(html)
for detail in details:
detail_url = detail[0] # 详情页的url
num = detail[1] # 详情页内图片的数量
name = detail[2] # 给详情页命的名
detail_html = scrap_page(detail_url)
if num == '1': # 第①种情况
detail_index_1(detail_html, name, path_2)
else: # 第②种情况
path_3 = f'D:/vilipix每日榜单/{today}/{name}/'
if not os.path.exists(path_3):
os.mkdir(path_3)
detail_index_more(detail_html, name, path_3)
print('*'*10, f'{name}下载完毕!', '*'*10)
if __name__ == '__main__':
pages = list(range(1, 11))
# 使用多线程进行加速
with ThreadPoolExecutor(max_workers=5) as executor:
executor.map(main, pages)
每日榜单的信息是滞后一天的。
今天是1.23
爬取的则是1.22的榜单
如有不足之处可以在评论区👇多多指正,我会在看到的第一时间进行修正
作者:远方的星 CSDN:https://blog.csdn.net/qq_44921056 本文仅用于交流学习,未经作者允许,禁止转载,更勿做其他用途,违者必究。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。