虎扑《不冷笑话》爬虫实战,顺带说说最近学写爬虫的经历(一)

前言

楼主16年毕业,工作内容目前主要以ETL开发为主。有一段时间逛知乎,经常看到有人分享一些数据分析的文章,比如美团上的点餐分析、豆瓣的评分分析,还有网易云音乐热评分析之类的。感觉这些文章都是有实打实的东西在,而且作者们的文笔也深得我心。后来也知道,这些数据大部分是用python爬虫爬取的,所以我也开始断断续续在看相关的内容。本帖就是我在做其中一部分实战的心路历程了,权当记录一下,水平较低莫怪。

1.起因

虎扑是广大jrs的家园,步行街是这个家园里最繁华的地段。据称广大jrs平均学历985,步行街街薪30w起步。
大学时经舍友安利,开始了解虎扑,主要是看看NBA的一些资讯。
偶尔也上上这个破街,看看jrs虐虐狗,说说家长里短等等,别的不说,jr们的三观都是特别正的。
《不冷笑话》基本是我每天必看的帖子,感觉《不冷笑话》的几位老伙计非常敬业,每天都会有高质量的输出,帖子下的热帖也很给力,福利满满。
正学python,突发奇想想把《不冷笑话》的图都爬下来。

引用自我的博客园文章:
爬取虎扑NBA首页主干道推荐贴的一只小爬虫,日常爬不冷笑话解闷

另外随着我学习内容的增加,一个爬虫也由最简单的流水线式的结构,变为模块化的设计思路,之后又变为使用成熟的框架。下面就切入正题了。

2.经过

版本1:模块化的简单实现

其实python的上手非常简单,原因有两个,python语言就很简洁,python的包非常丰富。我在B站上跟着小甲鱼的视频没学个十几节课,就开始对照着别人最简单的爬虫例子在做了。
新手无非就是requests + BeautifulSoup,一个负责HTTP请求,一个负责HTML解析。就小规模爬虫来讲,主要时间还是用来定位爬取目标在页面中的位置。所以,先看一下最low的爬虫是什么样子。

# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
import os, time
import re
link = r'https://www.qiushibaike.com/pic/'
r = requests.get(link)
x = 1
soup = BeautifulSoup(r.text,'lxml')
for content in soup.find_all(class_ = 'thumb'):
    xpath = content.find('img').get('src')
    image = requests.get('http:' + xpath)
    open('qiubai %d.jpg' % x,'wb').write(image.content)
    x += 1

除去导入包和编码声明,十行代码就能写一个爬虫,用来爬取糗事百科网站上的图片,并保存成本地文件。

实际上,一开始要准备爬取《不冷笑话》时,帖子地址的获取是一个非常困扰我的问题。后来经过我长期观察发现,《不冷笑话》总是在 虎扑NBA 的固定位置出现,所以我只要在这个页面定位好就可以进去了。

这里写图片描述

一开始我也是用最简单的结构去做《不冷笑话》的爬虫,但是又觉得这样做好像是重用很低,所以,按照模块化的思路,划定了几个功能点:

  • 1、定位不冷笑话在首页的位置,获取链接和标题
  • 2、建立以标题命名的目录,如果目录存在,说明已下载,程序结束
  • 3、进入不冷笑话的界面,获取正文中的图片链接,存入列表
  • 4、获取亮贴中的图片链接,存入列表
  • 5、保存图片,根据传入参数为正文或评论进行命名,区分图片来源
  • 6、大功告成

最终基本都按照了功能划分了模块,写出来的是这个样子的。

#-*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
import os, time
import re

url = (r'https://nba.hupu.com/')

#获取不冷笑话在首页的位置,返回url和标题
def get_buleng_title_url(url):
    index_html = requests.get(url)
    index_html_s = BeautifulSoup(index_html.text,'lxml')
    main_street = index_html_s.find(class_ = 'gray-list main-stem max250')
    url_list = []
    url_name_list = []
    for dd in main_street.find_all('dd',limit = 5):
        url_list.append(dd.a.get('href'))
        url_name_list.append(dd.a.get_text())
    return [url_list[4],url_name_list[4]] 

#获取不冷笑话正文中的图片列表,利用set去重
def get_pic_url(buleng_list):
    pic_url_list = set()
    buleng_html = requests.get(buleng_list[0])
    buleng_html_s = BeautifulSoup(buleng_html.text,'lxml')
    buleng_content = buleng_html_s.find(class_='quote-content')
    for pic_url in buleng_content.find_all('img'):
        try:
            original_url = pic_url.get('data-original')
            pic_url_list.add(original_url.split('?')[0])
        except:
            pic_url_list.add(pic_url.get('src'))
    return pic_url_list

#创建以标题命名的文件夹,并返回是否创建成功
def makedir(buleng_list):
    path = ('E:\\pic\\buleng\\%s' % buleng_list[1])
    if os.path.exists(path):
        return 0
    else:
        os.makedirs(path)
        return path

#获取亮贴中的图片列表,set去重
def get_comment_pic_url(buleng_list):
    comment_pic_url_list = set()
    buleng_html = requests.get(buleng_list[0])
    buleng_html_s = BeautifulSoup(buleng_html.text,'lxml')
    buleng_comment = buleng_html_s.find(id='readfloor')
    for floor in buleng_comment.find_all('table'):
        for pic_url in floor.find_all('img'):           
            try:
                original_url = pic_url.get('data-original')
                comment_pic_url_list.add(original_url.split('?')[0])
            except:
                comment_pic_url_list.add(pic_url.get('src'))
    return comment_pic_url_list


#下载图片,可下载gif、jpg、png格式
def download_pic(pic_url_list,path,pic_from = '正文'):
    a = 1
    for url in pic_url_list :
        if url.endswith('.gif'):
            pic = requests.get(url)
            with open((path+('\\%s-%s.gif' % (pic_from,a))),'wb') as f:
                f.write(pic.content)
                f.close
                print('下载一张%s动图' % pic_from)
            a += 1
        if url.endswith('.jpg'):
            pic = requests.get(url)
            with open((path+('\\%s-%s.jpg' % (pic_from,a))),'wb') as f:
                f.write(pic.content)
                f.close
                print('下载一张%sjpg图' % pic_from)
            a +=1
        if url.endswith('.png'):
            pic = requests.get(url)
            with open((path+('\\%s-%s.png' % (pic_from,a))),'wb') as f:
                f.write(pic.content)
                f.close
                print('下载一张%spng图' % pic_from)
            a +=1

if __name__ == "__main__":
    buleng = get_buleng_title_url(url)
    path = makedir(buleng)
    if path != 0:
        pic_url_list = get_pic_url(buleng)
        comment_pic_url_list = get_comment_pic_url(buleng)
        download_pic(pic_url_list,path)
        download_pic(comment_pic_url_list,path,'评论')
    else:
        print('目录已存在,等待虎扑更新')

版本2:模块化的简单实现plus

后来我一想,反正都是获取了主干道所有的推荐贴,为啥不自定义要下载的帖子呢,这样的话,这十几个推荐贴想下哪个下哪个,不是功能更上一层楼了?
多亏了模块化的设计,博主略一沉吟,部分修改如下:

#获取热帖在首页的位置,返回url和标题
def get_retie_title_url(url):
    index_html = requests.get(url)
    index_html_s = BeautifulSoup(index_html.text,'lxml')
    main_street = index_html_s.find(class_ = 'gray-list main-stem max250')
    url_list = []
    url_name_list = []
    for dd in main_street.find_all('dd',limit = 14):
        url_list.append(dd.a.get('href'))
        url_name_list.append(dd.a.get_text())
    return [url_list,url_name_list] 
    #return [url_list[4],url_name_list[4]]  源代码对比 

#获取热帖正文中的图片列表,利用set去重
def get_pic_url(retie_list,num): #新加num参数
    pic_url_list = set()
    retie_html = requests.get(retie_list[0][num-1])
    retie_html_s = BeautifulSoup(retie_html.text,'lxml')
    retie_content = retie_html_s.find(class_='quote-content')
    for pic_url in retie_content.find_all('img'):
        try:
            original_url = pic_url.get('data-original')
            pic_url_list.add(original_url.split('?')[0])
        except:
            pic_url_list.add(pic_url.get('src'))
    return pic_url_list

if __name__ == "__main__":
    retie = get_retie_title_url(url)
    a = 1
    for retie_title in retie[1]:
        print(a,'  ',retie_title)
        print('--------------------------------')
        a += 1
    num = int(input('请输入要下载的热帖排序(1-14)')) #获取输入序号
    if num < 1 or num > 14:
        print('不合法')
    else:
        path = makedir(retie[1][num-1])
        if path != 0:
            pic_url_list = get_pic_url(retie,num)
            comment_pic_url_list = get_comment_pic_url(retie,num)
            download_pic(pic_url_list,path)
            download_pic(comment_pic_url_list,path,'评论')
        else:
            print('目录已存在,等待虎扑更新')

然后效果就是这样啦

这里写图片描述

3.总结

好了,今天的无干货流水账就先告一段落,欲知后事如何,且听下回分解

单田芳先生于2018年9月11日在北京去世,享年84岁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值