• 爬虫——爬取百度贴吧每个帖子里面的图片


    现在我们用正则来做一个简单的爬虫,我们尝试爬取某个百度贴吧里面的所有帖子,并且将这个帖子里首页每个楼层发布的图片下载到本地。

    分析:以美女吧为例

      第一页:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&pn=0

      第二页:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&pn=50

      第三页:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&pn=100

      ……

    可以发现,url地址中pn及其前面的部分是相同的,改变的只是pn后面的值

    不难发现,每页中共有50个帖子,所有pn的值是以每页50的值递增。

    则第page页的pn值为:(page - 1) * 50

    而kw=%E7%BE%8E%E5%A5%B3为urllib.parse.urlencode{"kw":"美女"}

    #!/usr/bin/python3
    # -*- coding:utf-8 -*-
    __author__ = 'mayi'

    """
    用正则做一个简单的爬虫:尝试爬取某个贴吧里的所有帖子,并且将帖子里每层楼发布的图片下载到本地。
    例:美女吧(https://tieba.baidu.com/f? + kw=%E7%BE%8E%E5%A5%B3 + &pn=50)
    https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&pn=50
    其中:
    kw=%E7%BE%8E%E5%A5%B3为urllib.parse.urlencode({"kw":"美女"})
    pn为值从0开始,每页为50个帖子,故:
    第一页,pn的值为:0
    第二页,pn的值为:50
    第三页,pn的值为:100
    ……
    """

    import os
    import re
    import urllib.request

    # 一个爬虫类
    class Spider(object):
    """
    一个爬虫类
    """
    # 初始化
    def __init__(self, name):
    """
    类的初始化
    :param name: 百度贴吧名
    :return:
    """
    # User-Agent头
    self.header = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36'}
    keyword = urllib.parse.urlencode({"kw":name})
    self.url = "https://tieba.baidu.com/f?" + keyword + "&pn="

    self.run()

    # 获取帖子的最后一页
    def getLastPage(self, url):
    """
    获取url帖子的尾页的pn值
    :param url: url地址
    :return: pn值
    """
    html = self.loadPage(url)
    html = html.decode("utf-8")
    # 利用正则匹配尾页的pn值
    pattern = re.compile(r'<a href=.*?pn=(d+).*?>尾页</a>')
    try:
    pn = pattern.findall(html)[0]
    pn = int(pn)
    except:
    pn = 1

    return pn

    # 爬虫开始工作
    def run(self):
    """
    爬虫开始工作
    :return:
    """
    start_page = 1
    end_page = self.getLastPage(self.url) // 50 + 1
    print("该吧共" + str(end_page) + "页")
    for page in range(start_page, end_page + 1):
    # 计算pn的值
    pn = (page - 1) * 50
    # 拼接成完整的url地址
    full_url = self.url + str(pn)
    # 调用loadPage()函数,下载full_url的页面内容
    html = self.loadPage(full_url)
    # 调用screenPage()函数,筛选下载的页面内容
    item_list = self.screenPage(html)
    print("正在下载第" + str(page) + "页,共" + str(len(item_list)) + "个帖子")
    # 调用loadImage()函数,下载帖子里首页的图片
    self.loadImage(item_list)

    # 下载网页内容
    def loadPage(self, url):
    """
    下载url的页面内容
    :param url: 需下载页码的url地址
    :return: 页面内容
    """
    # url 连同 headers,一起构造Request请求,这个请求将附带 chrome 浏览器的User-Agent
    request = urllib.request.Request(url, headers = self.header)
    # 向服务器发送这个请求
    response = urllib.request.urlopen(request)
    # 获取网页内容:bytes
    html = response.read()

    return html

    # 筛选内容
    def screenPage(self, html):
    """
    筛选内容:筛选出每层楼帖子的链接
    :param html: 页面内容
    :return: 需下载的图片链接地址
    """
    # 转码:bytes转utf-8
    html = html.decode("utf-8")
    # 利用正则匹配每层楼帖子的链接
    pattern = re.compile(r'<a href="(/p/d+).*?>.*?</a>', re.S)
    item_list = pattern.findall(html)

    return item_list

    # 下载帖子里首页里面的图片
    def loadImage(self, item_list):
    """
    下载帖子里首页里面的图片
    :param item_list: 需下载图片的帖子的ID列表
    :return: None
    """
    for id in item_list:
    # 根据id拼接帖子链接
    link = "https://tieba.baidu.com" + id
    start_page = 1
    end_page = self.getLastPage(link)
    print("正在下载帖子:" + link + " 中图片")
    image_no = 0
    for page in range(start_page, end_page + 1):
    # 拼接完整链接
    full_link = link + "?pn=" + str(page)
    # 获取需下载图片的帖子的页面内容
    html = self.loadPage(full_link)
    # 转码:bytes转utf-8
    html = html.decode("utf-8")
    # 利用正则匹配帖子中的图片链接
    pattern = re.compile(r'<img class="BDE_Image".*?src="(.*?)".*?>', re.S)
    # 图片链接列表
    image_list = pattern.findall(html)
    for image in image_list:
    image_no = image_no + 1
    self.writeImage(image, id[3:], image_no)

    print("帖子:" + full_link + " 共下载" + str(len(image_list)) + "个图片")

    # 向本地磁盘中存储图片
    def writeImage(self, url, id, image_no):
    """
    向本地磁盘中存储图片
    :param url: 图片url
    :param id: 帖子id:本地文件夹
    :param image_no: 图片序号
    :return:
    """
    # 判断是否存在对应的文件夹
    if not os.path.exists("image/" + id):
    # 若不存在,则创建
    os.makedirs("image/" + id)
    # 图片文件名:id + "_" + 5位图片序号
    image_no = str(image_no)
    file_name = "image/" + id + "/" + id + "_" + "0" * (6 - len(image_no)) + image_no + ".jpg"
    # 以wb方式打开文件
    file = open(file_name, "wb")
    # 获取图片名为名为
    images = self.loadPage(url)
    # 写入图片
    file.write(images)
    # 关闭文件
    file.close()

    # 主函数
    if __name__ == '__main__':
    # 要爬取的百度贴吧名
    name = input("请输入您要爬取的百度贴吧名:")
    # 创建一个爬虫对象
    mySpider = Spider(name)

      

  • 相关阅读:
    Dockerfile构建
    ElasticSearch学习之集成客户端
    区块链学习之Hyperledger Fabric开发环境搭建(Go+Docker+Fabric)
    区块链学习之什么是区块链(基础入门)
    python学习之多版本管理及Python安装/卸载遇到的坑(MAC版)
    ElasticSearch学习之基本原理概述
    ElasticSearch学习之基本概念及单机/集群部署
    Kafka学习之Kafka选举机制简述
    Kafka学习之内核原理剖析
    通过idea将java项目发布到harbor仓库
  • 原文地址:https://www.cnblogs.com/mayi0312/p/7220758.html
Copyright © 2020-2023  润新知