前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【python爬虫】PyQuery实战:爬取镜像p站每日榜单图片

【python爬虫】PyQuery实战:爬取镜像p站每日榜单图片

原创
作者头像
远方的星
发布2022-01-24 10:53:53
1.5K0
发布2022-01-24 10:53:53
举报

一、构造url

先取网站一页的url进行观察:

https://www.vilipix.com/ranking?date=20220122&mode=daily&p=2

可以发现,是由四部分组成,简单拆分一下:

base_url=https://www.vilipix.com 日期 date 榜单类型mode 页码p

于是可以构造url为:

代码语言:python
复制
url = f'{base_url}/ranking?date={today_str}&mode=daily&p={page}'
   '''
   base_url:https://www.vilipix.com
   today_str:获取当天网站榜单日期
   page:榜单页码
   '''

二、页面爬取

可以定义一个函数,用于页面的爬取:

代码语言:python
复制
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}不可爬取!')

函数返回的是页面的爬取结果

三、页面解析

爬取到页面,但信息有很多,需要筛选出对自己有用的信息

这里也可以构建一个函数来完成

代码语言:python
复制
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的用法,这位博主讲的很清晰,有需要的小伙伴可以参考一下:

python中yield的用法详解——最简单,最清晰的解释

四、下载图片

这个函数写的时候是最后写的,但是后来完善代码的时候,被提前调用了,就先写出来了,非常的简单,且很实用。

代码语言:python
复制
def download(path, name, image):
    save_path = path + name + '.jpg'
    with open(save_path, 'wb') as f:
        f.write(image)

path:图片下载的目标文件夹路径 name:文件名 image:需要下载的图片

五、详情页的处理

在第三步时,对页面进行处理得到的链接,访问即可得到详情页。

对于详情页的处理,分为两部分:

①、仅含一张图片

②、含有多张图片

什么意思呢?下图来说明一下:

在这里插入图片描述
在这里插入图片描述

右上角,有数字的为第②种情况,没数字的则为第①种情况。

为什么要分类呢?

为了容易区分,我是将含多张图片详情页中获取的图片放在一个文件夹里,详细可见后续。

函数如下:

  • 第①种情况:
代码语言:python
复制
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)  # 调用下载函数
  • 第②种情况:
代码语言:python
复制
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:文件名

六、完整代码

代码语言:python
复制
# -*- 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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、构造url
  • 二、页面爬取
  • 三、页面解析
  • 四、下载图片
  • 五、详情页的处理
  • 六、完整代码
  • 七、运行结果展示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档