ZSXQ爬虫

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

网上找类似教程

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

一切从手机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&爬虫,第一次派上用场,边摸索边试错,虽不甚完美,但自我感觉可以及格啦,希望以后继续多学、多用!

  • 报错信息,直接谷歌百度,依旧是最直接有效的解决方式;
  • 不要急于去运行代码,准备个纸笔,多画画写写,厘清逻辑,多看几遍,自我检查,更有助于少走弯路、节省时间、提高效率。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 一. Java基础部分.................................................
    wy_sure阅读 3,788评论 0 11
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,084评论 1 32
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,357评论 0 17
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,169评论 0 9
  • 打手心、罚站、罚扫地、蹲马步是小时候上学常有的事, 禁止体罚,对儿童来说是一件好事。 最近几年,体罚成了教育上的高...
    华年冉冉阅读 1,127评论 0 1