简单爬虫Ajax数据爬取——今日头条图片爬取

一、Ajax简介

什么是Ajax?

Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。

通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。

我们在浏览很多网页,比如微博,我们点击进去某条微博,底下可以加载出网友的评论,但是我们可以看到网址是没有改变的,这就是使用了ajax技术。这次以爬取今日头条的图片为例来进行Ajax数据爬取的实战演示。本文也是学习自崔庆才博主的书籍。

二、逻辑分析

首先打开今日头条的网站:https://www.toutiao.com/,在搜索框内可以输入任意的内容,比如我爬取的是关于风景的图片。这里我使用的是谷歌浏览器,右键检查,选择NetWork,查看所有的网络请求。可以看到第一条网络请求就是当前的链接。点击这条请求,查看Response。如果我们这个网页是由这个请求的结果渲染出来的,那么这个请求的源代码中肯定会包含网页结果中的文字。这边可以使用搜索验证,比如搜索一下标题结果中的“破万”两个字,可以发现在这个请求中没有匹配的的结果。说明这些内容是由Ajax所加载的。

下面就可以分析Ajax请求了,Ajax的数据类型为xhr,这边可以在上面选择XHR,这样显示出来的就都是ajax请求,将网页从上拉到最下,可以看见请求逐渐变多。点击第一个请求,可以在右边看到显示出了不同的信息。

复制一下右边的Request URL,可以看到返回了json数据,所以我们的第一步就是分析请求url,获取返回的json数据。

三、加载单个Ajax请求

点击每个Ajax请求,可以看到他们的Request URL参数基本相同,唯一有变化的是offset,变化规律为每次+20,所以我们在实现方法是,传入offset作为参数。然后请求的方式为GET。

以第一个请求的url为例子:

https://www.toutiao.com/api/search/content/?aid=24&app_name=web_search&offset=0&format=json&keyword=%E9%A3%8E%E6%99%AF&autoload=true&count=20&en_qc=1&cur_tab=1&from=search_tab&pd=synthesis&timestamp=1557652705403

可以看到所有的参数,由次可以构造URL,然后请求这个链接,如果返回的状态码为200,那么就使用respnse.json()方法来将结果转化为json模式并返回。

#  唯一的变化就是offset
def get_page(offset):
    params = {
        'aid': '24',
        'offset': offset,
        'format': 'json',
        'autoload': 'true',
        'count': '20',
        'cur_tab': '1',
        'from': 'search_tab',
        'pd': 'synthesis'
    }
    base_url = 'https://www.toutiao.com/api/search/content/?keyword=%E9%A3%8E%E6%99%AF'  #这一部分都是相同的参数
    url = base_url + urlencode(params) # 构造请求的GET参数
    print(url) # 可以打印出url看自己构建的是否有效
    try:
        resp = requests.get(url)
        if 200 == resp.status_code:
            print(resp.json()) # 看下返回结果是否正确
            return resp.json()
    except requests.ConnectionError:
        return None

四、解析结果

我们在获取json结果后,就要从中解析提取出我们所要爬取的数据。点击data可以看见很多条数据,每条数据里都有一个image_list字段,包含了我们所要爬取的图片url,所以我们要在刚才返回的结果内将图片url提取出来,通过构造一个生成器,将图片链接和标题返回。

# 提取图片链接和图片标题
def get_images(json): # 将刚才的json传入
    if json.get('data'): # 找到data
        data = json.get('data')
        for item in data: # 找到data中标题和图片链接列表
            title = item.get('title')
            images = item.get('image_list')
            for image in images: # 构造生成器
                yield {
                    'image':  image.get('url'),
                    'title': title
                }

五、保存图片

将所有图片的url返回后,我们就需要一个方法来下载图片并保存。首先我们要根据返回的title值创建文件夹,然后请求这个图片链接,获取数据,以二进制形式写入文件。图片名称可以根据其内容的MD5值来命名。

# 保存图片方法
# 根据title创建文件夹,然后根据图片链接获取图片二进制文件,写入文件,图片名称为其内容的MD5值
def save_image(item):
    img_path = 'img' + os.path.sep + item.get('title') # os.path.sep这是路径分割符
    print(img_path)
    if not os.path.exists(img_path): # 如果不存在文件夹就创一个
        os.makedirs(img_path)
    try:
        resp = requests.get(item.get('image'))
        if codes.ok == resp.status_code:
            # 使用format方法格式化,生成文件路径
            file_path = img_path + os.path.sep + '{file_name}.{file_suffix}'.format(
                file_name=md5(resp.content).hexdigest(), # 将文件保存时,通过哈希函数对每个文件进行文件名的自动生成
                file_suffix='jpg')
            if not os.path.exists(file_path):
                with open(file_path, 'wb') as f: # 还未下载则写入文件内容
                    f.write(resp.content) 
                print('Downloaded image path is %s' % file_path)
            else:
                print('Already Downloaded', file_path)
    except requests.ConnectionError:
        print('Failed to Save Image,item %s' % item)

六、传入offset参数,多进程下载

def main(offset):
    json = get_page(offset)  # 获得json的返回结果
    for item in get_images(json):  # 解析json获得包括标题以及图片链接的词典item
        print(item)  # 打印处词典信息
        save_image(item)  # 保存图片


GROUP_START = 0 #offset最多到120
GROUP_END = 6

if __name__ == '__main__':
    pool = Pool()  # python多进程,创建进程池
    groups = ([x * 20 for x in range(GROUP_START, GROUP_END + 1)])  # 传入1到20的参数
    pool.map(main, groups)  # main表示要执行的方法, 后面表示被操作的数据列表
    pool.close()  # 关闭进程池,不再接受新的进程
    pool.join()  # 主进程阻塞等待子进程的退出

七、查看结果

在当前路径下会发现生成了一个img文件夹,点击进去就可以看见以title命名的各个文件夹,文件内就是以MD5值命名的图片。

这是一个简单的爬虫,也是我学习爬虫后第一次爬取ajax请求,大家也可以尝试爬取其他网站的图片。

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值