美文网首页网络爬虫天地
今日头条爬虫解析

今日头条爬虫解析

作者: 探索者_逗你玩儿 | 来源:发表于2018-10-05 15:43 被阅读0次

    如今自媒体风生水起,很多人开始入住各大自媒体平台进行自媒体创作。想要持续的输出高质量的文章太难了,于是很多人就开始搞起了伪原创,拿别人比较热的文章过来改一改,不仅轻松还能收获一票粉丝,偏题了,我不是鼓励大家搞伪原创。今天我们的主题是爬虫,既然自媒体平台有这么多高质量的文章,想要一一收藏太难了,于是就想出了通过网络爬虫将感兴趣的文章爬取下来然后进行收藏,岂不是很爽,于是开始动手。今天拿今日头条练手。

    第一步分析入口,今日头条的文章入口主要分为频道入口,搜索入口,用户主页入口,那么我们就一一开始破解。

    首先从频道入口下手,分析网页结构,发现所有的文章都是通过ajax动态加载,那么第一想法是通过selenium模拟浏览器进行网页提取,虽然目的可以达到但是效果不理想,需要处理分页去重而且效率不高,故这个方案放弃,在接着进行分析ajax接口,貌似行得通,架起代码开始测试,在处理ajax接口是发现需要处理as,cp,_signature 三个参数,接口如下

    https://www.toutiao.com/api/pc/feed/?category=news_tech&utm_source=toutiao&widen=1&max_behot_time=0&max_behot_time_tmp=0&tadrequire=true&as=A125AB7BC7F0F59&cp=5BB7802FF5896E1&_signature=NOFpxAAAb1yLl5gie2NwDTThad

    as,cp网上已经有大神破解了算法如下;

        def getASCP(self):
            t = int(math.floor(time.time()))
            e = hex(t).upper()[2:]
            m = hashlib.md5()
            m.update(str(t).encode(encoding='utf-8'))
            i = m.hexdigest().upper()
    
            if len(e) != 8:
                AS = '479BB4B7254C150'
                CP = '7E0AC8874BB0985'
                return AS, CP
    
            n = i[0:5]
            a = i[-5:]
            s = ''
            r = ''
            for o in range(5):
                s += n[o] + e[o]
                r += e[o + 3] + a[o]
    
            AS = 'A1' + s + e[-3:]
            CP = e[0:3] + r + 'E1'
            return AS, CP
    

    比较难搞的是signature参数,虽然网上也有很多人发文怎么破解,但是效果都不理想,只能拿到第一次请求的signature,第二次请求就直接不行了。分析js发现signature的请求是通过window.TAC.sign方法产生,而这个方法是动态绑定的,由一堆看不清逻辑的字符串通过一定的算法解密后得到,着手分析了一下,发现里面用到了Date ,Convas 相关的函数,姑且进行了一下推断,判断入参的时间戳跟当前的时间戳进行对比,肯定不能大于当前的时间,但是范围也不能相差太远否则一个频道页内容直接就爆了,对于Convas 可能就是为了限定上下文,否则为什么我们通过python直接执行TAC.sign方法产生的signature在第二次就会失效,虽说第一次能请求成功那么我们是不是每次都模拟第一次请求,虽说也能得到数据,但不能连续采集还是有点失望的。那有没有其他的办法可以解决了,在经过一下午的思考过后发现,既然在保证上下文的情况下可以连续采集(通过chrome的console生成的signature是可以的)那么我们通过selenium方案来模拟上下文,负责产生signature,剩下的就是通过urllib来请求接口获取数据进行解析是否可以行了?经过一番验证结果是可喜的,功夫不负有心人达到目的。直接贴代码。代码中有些自有逻辑没有贴出来,但是逻辑思路基本上都有了。今天到此为止,下次说怎么爬详情

    
        def get_channel_data(self, page):  #获取数据
            req = self.s.get(url=self.url, verify=False, proxies=get_proxy_ip())
            #print (self.s.headers)
            #print(req.text)
            headers = {'referer': self.url}
            max_behot_time='0'
            signature='.1.hXgAApDNVcKHe5jmqy.9f4U'
            eas = 'A1E56B6786B47FE'
            ecp = '5B7674A7FF2E9E1'
            self.s.headers.update(headers)
            item_list = []
            browser = webdriver.Chrome()
            browser.implicitly_wait(10)
            browser.get(self.url)
            for i in range(0, page):
    
                Honey = json.loads(self.get_js())
                # eas = self.getHoney(int(max_behot_time))[0]
                # ecp = self.getHoney(int(max_behot_time))[1]
                eas = Honey['as']
                ecp = Honey['cp']
                signature = Honey['_signature']
                if i > 0:
                    signature = browser.execute_script("return window.TAC.sign("+ max_behot_time +")")
                url='https://www.toutiao.com/api/pc/feed/?category={}&utm_source=toutiao&widen=1&max_behot_time={}&max_behot_time_tmp={}&tadrequire=true&as={}&cp={}&_signature={}'.format(self.channel,max_behot_time,max_behot_time,eas,ecp,signature)
                req=self.s.get(url=url, verify=False, proxies=get_proxy_ip())
                time.sleep(random.random() * 2+2)
                # print(req.text)
                # print(url)
                j=json.loads(req.text)
                for k in range(0, 10):
                    item = toutiaoitem()
                    now=time.time()
                    if j['data'][k]['tag'] != 'ad' or j['data'][k]['tag'] != 'ad.platform.site':
                        item.title = j['data'][k]['title']  ##标题
                        item.source = j['data'][k]['source']  ##作者
                        item.source_url = 'https://www.toutiao.com/'+j['data'][k]['source_url']   ##文章链接
                        item.media_url = 'https://www.toutiao.com/'+j['data'][k]['media_url']  #作者主页
                        item.article_genre = j['data'][k]['article_genre']  #文章类型
                        try:
                            item.comments_count = j['data'][k]['comments_count']  ###评论
                        except:
                            item.comments_count = 0
    
                        item.tag = j['data'][k]['tag']  ###频道名
                        try:
                            item.chinese_tag = j['data'][k]['chinese_tag']   ##频道中文名
                        except:
                            item.chinese_tag = ''
                        try:
                            item.label = j['data'][k]['label']  ## 标签
                        except:
                            item.label = []
                        try:
                            item.abstract = j['data'][k]['abstract']  ###文章摘要
                        except:
                            item.abstract = ''
                        behot = int(j['data'][k]['behot_time'])
                        item.behot_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(behot))  ####发布时间
                        item.collect_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(now))  ##抓取时间
                        item.item_id = j['data'][k]['item_id']
                        try:
                            item.image_list = j['data'][k]['image_list']
                        except:
                            item.image_list = []
                        item.image_url = j['data'][k]['image_url']
                        item.middle_image = j['data'][k]['middle_image']
                    item_list.append(item)
                toutiaodb.save(item_list)
                time.sleep(2)
                max_behot_time = str(j['next']['max_behot_time'])
    

    相关文章

      网友评论

        本文标题:今日头条爬虫解析

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