美文网首页
ZSXQ爬虫

ZSXQ爬虫

作者: kkjusdoit | 来源:发表于2019-11-15 15:13 被阅读0次

    加入了几个知识星球,鉴于精华帖阅读体验较差,想一次性爬下来,细细品读。于是开始了此次的爬虫任务:

    网上找类似教程

    原本打算网页端爬取,结果没找到合适的。(刚才又搜了下,好像这个是我真正想要的,看来还是的明确目标,多多搜索

    一切从手机APP抓取实战——知识星球开始的。

    按照基本步骤:

    • 配置Charles(顺利)
    • APP抓包(因华为手机问题,无法信任已安装证书,改为IPad)
    • 模拟请求(图片问题卡壳了好久)

    话不多说,上代码吧。
    事先声明,拙劣的代码别质疑,质疑就是我菜。

    先导入必要的模块
    import requests 
    import os
    import time
    import urllib.request
    import urllib
    requests.packages.urllib3.disable_warnings()  #防止警告
    import ssl
    ssl._create_default_https_context = ssl._create_unverified_context #全局取消证书验证
    from datetime import date,timedelta
    

    其中关于ssl._create_default_https_context = ssl._create_unverified_context #取消证书验证这个解决了我烦恼一时的图片无法下载问题。

    使用python3.6进行 request请求时【出现问题的原因是“SSL:CERTIFICATE_VERIFY_FAILED”】的类似错误

    请求头

    等同于Pad访问,从Charles获取,重点是X-Request-Id和Authorization。

    headers={
     'Host': 'api.zsxq.com' ,
        'X-Version': '1.10.30' ,
        'Accept': '*/*' ,
        'User-Agent': 'xiaomiquan/4.7.0 iOS/Pad/13.1.3',
        'Accept-Language': 'zh-Hans-CN;q=1',
        'X-Request-Id': 'XXXXXXXXXXX',
        'Authorization': 'XXXXXXXXXXX',
    }
    
    精华帖日期范围
    start_to_end = []
    
    #给定相差的天数,返回从开始到结束的全部天
    def get_range(delta_days):
        start = date(2017,12,2)  #开始日期
        for i in range(delta_days):
            start_to_end.append(start)
            start += timedelta(days=1)
        return start_to_end
    
    date_range =get_range(543) #从开始到543天后的每一天集合
    
    str_daterange = [i.strftime(format='%Y %m %d') for i in date_range] #日期范围
    right_date = str_daterange[1:]  #左  用于嵌入网址
    left_date = str_daterange[:-1]  #右
    

    重点:从给定链接下载精华帖的文字、评论及图片

    据观察试验,链接形式如下:https://api.zsxq.com/v1.10/groups/2123521721/topics?count=20&begin_time={开始年份}%2D{月}%2D{日} T00%3A00%3A00%2E000%2B0800&end_time={结束年份}%2D{月}%2D{日}T23%3A59%3A59%2E000%2B0800&scope=digests'.
    从某年某月某日到某年月日,按时间阶段搜此区间内的所有帖子。
    但每条链接最大显示数量40个。

    原本打算以周为间隔,每7天集结成一个文件夹。但存在2个问题:

    1. 昨天晚上,运行一段时间发现,有的文件夹空空如也。经查,发现是日期转换搞的鬼,date形式的2019-01-01转换为字符串成了2019-1-1,于是链接里月、日哪里少了0,因此无效链接,无法爬取数据;
    2. 大多数周的帖子总数远超40,甚至单日就将近40;
    • 解决方案:1.用strftime函数,确保字符串转化后依然带0;2改成以为单位,每天一个文件夹。
    def crawl_from_url(url,dir_name):    #传入链接和一个文件夹名称
        if not os.path.exists(dir_name):    #是否存在名为dir_name的文件夹
            os.makedirs(dir_name)            #没有就新建个
        res = requests.get(url, headers=headers, verify=False)
        try:
            content = res.json()['resp_data']['topics']
            my_text = []
            m = n = 0
    
            for i in content:
                comments=[]
                img = 0
                #爬取主题文字和评论
                talk = i['talk']
                text =talk['text']
                try:
                    for j in i['show_comments']:
                        comments.append(j['text'])
                    my_text.append('\r\n'+'\r\n'+'【第{}个精华帖】'】[{}]'.format(n,i['create_time'])+'\r\n'+'\r\n'+'\r\n'+text+'\r\n')
                    my_text = my_text+['\r\n'+'\r\n'+'【评论:】''\r\n'+'\r\n']+comments
                except KeyError:
                    print('这个帖子没评论')
                print('第{}个精华帖下载完成'.format(n))
                n +=1
    
              
                try:                  #爬取图片
                    for j in i['talk']['images']:
                        time.sleep(0.5)
                        dir = dir_name+'//'+str(n)+'_'+str(m)+'_'+'.jpg'
                        urllib.request.urlretrieve(j['large']['url'], dir)
                        print('下载成功第{}个精华帖的第{}个图片'.format(n,m))
                        m +=1
                except KeyError:
                    print('第{}个精华帖没有图哦'.format(n))
                n +=1
            print('{}全部下载完成!'.format(dir_name))
            txt_path = dir_name+'//'+'dir_name.txt'
            with open(txt_path, 'w',encoding='utf-8') as f:
                f.writelines(my_text)
        except KeyError:
            print('当前日期没有帖子,下一个~')
    

    这个函数是整个代码的核心,主要就是从json中找到文字、图片、评论等关系,然后一一提取即可。

    可以注意到有好几个try...except...结构,这也是其中一个大坑:有的日期没帖子,有的帖子没评论,有的帖子没图,因此直接爬取会遭遇KeyError,用了try...except...后就可以跳过这些不存在的继续往下遍历。

    还有个小坑是,往txt文件中写入换行符\n要带上\r\n,转义字符。

    按每天来下载帖子

    left_date: [2018 01 01... ... 2019 11 07]
    right_date: [2018 01 02 ... ... 2019 11 08]
    将left_date和right_date的年月日插入网址,形成链接,并以left_date日期为名新建文件夹。

    for l,r in zip(left_date, right_date):
        url_by_day = 'https://api.zsxq.com/v1.10/groups/222588821821/topics?count=20&begin_time={}%2D{}%2D{}T00%3A00%3A00%2E000%2B0800&end_time=
    {}%2D{}%2D{}T23%3A59%3A59%2E000%2B0800&scope=digests'.format(l[0:4],l[5:7],l[8:10],r[0:4],r[5:7],r[8:10])
        crawl_from_url(url_by_day,l[0:4]+l[5:7]+l[8:10])
    
    历经1个半小时,终于下载完成!

    [图片上传失败...(image-afd38-1573222234053)]

    小结

    学的零零散散的Python&爬虫,第一次派上用场,边摸索边试错,虽不甚完美,但自我感觉可以及格啦,希望以后继续多学、多用!

    • 报错信息,直接谷歌百度,依旧是最直接有效的解决方式;
    • 不要急于去运行代码,准备个纸笔,多画画写写,厘清逻辑,多看几遍,自我检查,更有助于少走弯路、节省时间、提高效率。

    相关文章

      网友评论

          本文标题:ZSXQ爬虫

          本文链接:https://www.haomeiwen.com/subject/rdbwbctx.html