Python《通过解析http请求搞定动态加载,爬取toutiao图片》

今天我们下载头条的图片内容。
进入头条首页,我们根据关键词搜索。
在这里插入图片描述

发现有搜索出很多的条目,而且条目是根据鼠标往下滑动的时候就会动态加载出来,是动态更新的,之前我们曾使用过Selenium进行模拟鼠标滑动,一次性获得了很多的条目,最后再把所有页面的对应图片组的入口找出来,而今天我们试图用分析http request请求的方式来搞一次,每一次动态加载都是一次请求,所以我们来试图分析分析请求,看看能不能做出来。

每一个条目点击进去能看到相应的文章里面有很多图片,说明是一个图片组。
在这里插入图片描述

好了,看了大概的内容展示后,言归正传,我们进入正题。
首先我们得来分析下每一次动态加载得http请求,看看能不能找到什么item规律,于是打开开发者窗口,请按“F12”。然后不断下滑下滑进行动态加载,我们再network窗口进行观察。
如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我们连续请求四次,发现四次得请求在数据请求上很有规律。
在这里插入图片描述

每一次都是offset不一样,offset就是分页得偏移,count是每一次分页得总数,整个是保持不变,
每一次得timestamp和_signature也是不一样得,但是经过测试发现,这俩可以不用加上,也就是对于爬取数据来说没啥用处,可以忽略掉。

每一次请求后,得到的数据是:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

每一个组图都有一个groupId,我们拿到这个ID后,打开json中的article_url,发现会跳转到另外一个地址,比如地址会从

输入:https:// toutiao.com/group/6887210541710836232/
跳转到:https://www.toutiao.com/a6887210541710836232/

这样我们通过groupid来拼装出组图的文章地址,使用Selenium来打开页面,找到所有的img,进行下载!
在这里插入图片描述

组图页面的每个图片的class都是 “syl-page-img”。嗯,这就不难了,不错!
好了整个过程就是这样的。现在给出完整代码:

import requests
from urllib.parse import urlencode
import time
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import  Options
import os
from concurrent.futures import ThreadPoolExecutor

chromeExeLoc = 'D:/software/chrome/chromedriver_win32/chromedriver.exe'
rootrurl = 'https://www.toutiao.com/api/search/content/?'
ERROR_SELF_DEF = "ERROR"
save_dir = 'D:/estimages/'
headers = {
    'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
    'Accept-Language': 'en-US,en;q=0.8',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive'}  # 伪装成浏览器

# 根据某个url和一堆参数去获得某个json数据
def request_url_data(url):
    # 获得json数据
    try:
        resp = requests.get(url,headers=headers)
        if resp.status_code == 200:
            return resp.text
    except requests.RequestException as e:
        print('fail to get json data.')
        return ERROR_SELF_DEF

def saveOneImg(dir, img_url):
    new_headers = {
        "Referer": img_url,
        'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
        'Accept-Language': 'en-US,en;q=0.8',
        'Cache-Control': 'max-age=0',
        'Connection': 'keep-alive'
    }  ###设置请求的头部,伪装成浏览器,实时换成新的 header 是为了防止403 http code问题,防止反盗链,

    try:
        img = requests.get(img_url, headers=new_headers)  # 请求图片的实际URL
        if (str(img).find('200') > 1):
            with open(
                    '{}/{}.jpg'.format(dir, img_url.split('/')[-1].split('?')[0]), 'wb') as jpg:  # 请求图片并写进去到本地文件
                jpg.write(img.content)
                print(img_url)
                jpg.close()
            return True
        else:
            return False
    except Exception as e:
        print('exception occurs: ' + img_url)
        print(e)
        return False

def downloadAllImgs(imgs, dir):
    if not os.path.exists(dir):
        os.makedirs(dir)

    for img in imgs:
        saveOneImg(dir, img.get_attribute('src'))
    pass

# 再一个字符串s中找到所有的字串substr
def find_all(sub, s):
    index_list = []
    index = s.find(sub)
    while index != -1:
        index_list.append(index)
        index = s.find(sub, index + 1)

    if len(index_list) > 0:
        return index_list
    else:
        return -1

# 得到所有的文章的groupId
def parseArticles(json):
    json = json.replace(' ','')
    li = find_all('"group_id"', json)
    urls = []
    for item in li:
        beg = json.find(':', item)+2
        # beg = json.find('http', item)
        end = json.find(',', item)-1
        urls.append(json[beg:end])

    return urls


def searchKeyWord(offset, keyword, browser):
    ts = str(time.time()).replace('.', '')[0:13]
    params = {
        'aid': 24,
        'app_name': 'web_search',
        'offset': offset,
        'format': 'json',
        'keyword': keyword,
        'autoload': 'true',
        'count': 20,
        'en_qc': 1,
        'cur_tab': 1,
        'from': 'search_tab',
        'pd': 'synthesis',
        'timestamp': ts,
    }

    # 拼装url
    url = rootrurl + urlencode(params)
    # 通过url去异步请求json数据
    json = request_url_data(url)
    # 解析json然后得到所有的文章的groupId
    groupIds = parseArticles(json)

    for groupId in groupIds:
        article = '{}{}/'.format('https://www.toutiao.com/a', groupId)
        print(article)
        browser.get(article)  # get the
        imgs = browser.find_elements_by_class_name('syl-page-img')

        downloadAllImgs(imgs, '{}{}/{}'.format(save_dir, keyword, groupId))


def tagSpider(keyword):

    # 无头浏览器 这样浏览器就不会弹出那个chrome的web浏览器界面
    options = Options()
    options.add_argument('--headless')

    browser = webdriver.Chrome(chromeExeLoc)
    browser.maximize_window()
    browser.implicitly_wait(10)

    # 别贪心,只抓取几次即可。
    for offset in range(20, 100, 20):
        print('start.............., offset=%s' % offset)
        searchKeyWord(offset, keyword, browser)
        print('end.................')

    browser.close()
    browser.quit()

if __name__ == '__main__':
    # 获得所有标签
    taglist = ['动漫', '街拍美女', '林珍娜', '火影忍者']

    #
    # 给每个标签配备一个线程
    with ThreadPoolExecutor(max_workers=15) as t:  # 创建一个最大容纳数量为20的线程池
        for tag in taglist:
            t.submit(tagSpider, tag)

    # 单个连接测试下下
    # tagSpider('三吉彩花')

    # 等待所有线程都完成。
    while 1:
        print('-------------------')
        time.sleep(1)

效果图如下:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值