zoukankan      html  css  js  c++  java
  • 使用正则表达式爬取500px上的图片

     网址:https://500px.com/seanarcher,seanarcher是一个up主的名字

    打开这个网址,会发现有好多图片,具体到每一个图片的url地址 https://500px.com/photo/273383049/galya-by-sean-archer,其中273383049为图片的id

     

     

     使用https://api.500px.com/v1/photos?ids=图片id,也就是https://api.500px.com/v1/photos?ids=273383049可以访问每一个图片的详情json信息

     

    那是不是可以通过如下思路来获取图片信息呢?

    1.访问索引页,获得每个图片的id

    2.根据图片id构造新的url地址,

    3.访问每个图片的url地址,获得图片链接

    4.使用图片链接下载图片

     

    我起初也是这样想的,可以第一步确实现不了,访问索引页后获得的数据中根本就没有所有的图片id信息,有关的只有这部分数据,还是在script标签里,处理这些数据后发现只有50个图片数据信息.

     

    然后再继续分析,调试模式到XHR,发现一个有意思的现象

     

     发现这个请求有返回的json数据,是直接从第二页开始的,总共8页,photos参数中就是各个图片的具体信息,跟使用https://api.500px.com/v1/photos?ids=图片id访问的结果差不多

    但是有一个问题,直接访问这个地址会报错:

     

    结合上述的情况分析,可以得到大致的结论: 该网站的 首页信息是静态加载的,从第 2 页开始是采用了 Ajax 动态加载,URL 不同,需要分别进行解析提取。

    1.初次请求网站是直接在html中使用script的标签返回50条数据信息

    2.页面继续往下拉,使用的是ajax加载页面的方式,每次加载一页,又50条数据,直到第8页图片信息加载完才结束

    3.结合以上分析,差不多也就400多条数据,算是符合要求

     

    那么现在的问题是如何获取ajax加载出来的数据信息?

    很遗憾,我也暂时还没找到有啥解决的办法.

     

    唯一想到的笨办法是使用浏览器获取返回的json数据,保存下来,然后分析这些json数据,从而获得图片下载链接,进而下载图片

     

    一:只下载首页50个图片

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import csv
    import json
    import os
    import re
    from _md5 import md5
    
    import pymongo
    import requests
    from requests.exceptions import RequestException
    
    MONGO_URL = 'localhost'
    MONGO_DB = 'maoyan'
    MONGO_TABLE = 'gril'
    
    client = pymongo.MongoClient(MONGO_URL, connect=False)
    db = client[MONGO_DB]
    
    
    def get_one_page(url):
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0'
        }
        try:
            response = requests.get(url, headers=headers)
            if response.status_code == 200:
                return response.text
            else:
                return None
        except RequestException:
            print('请求失败')
            return None
    
    
    def parse_one_page(html):
        pattern = re.compile("<script id='bootstrap_data'>.*?{}.*?App.bootstrap = (.*?)</script>", re.S | re.M)
        items = re.findall(pattern, html)
        image_data = json.loads(items[0])['userdata']['photos']
        # print(image_data)
        # print(type(image_data))
        for i in range(len(image_data)):
            yield {
                'id': image_data[i]['id'],
                'name': image_data[i]['name'],
                'taken_at': image_data[i]['taken_at'],
                'image_url': image_data[i]['image_url'][-3], # 图片链接有多种大小格式,选择格式最大的
            }
    
    
    # 数据存储到csv
    def write_to_file3(item):
        with open('gril.csv', 'a', encoding='utf_8_sig', newline='') as f:
            # 'a'为追加模式(添加)
            # utf_8_sig格式导出csv不乱码
            fieldnames = ['id', 'name', 'taken_at', 'image_url']
            w = csv.DictWriter(f, fieldnames=fieldnames)
            # w.writeheader()
            w.writerow(item)
    
    
    # 保存到数据库中
    def save_to_mongo(result):
        if db[MONGO_TABLE].insert(result):
            print('Successfully Saved to Mongo', result)
            return True
        return False
    
    
    # 请求图片url,获取图片二进制数据
    def download_image(url):
        try:
            response = requests.get(url)
            if response.status_code == 200:
                save_image(response.content)  # response.contenter二进制数据 response.text文本数据
            return None
        except RequestException:
            print('请求图片出错')
            return None
    
    
    def save_image(content):
        file_path = 'D:\pachong\gril\{1}.{2}'.format(os.getcwd(), md5(content).hexdigest(), 'jpg')
        if not os.path.exists(file_path):
            with open(file_path, 'wb') as f:
                f.write(content)
    
    
    def main():
        url = 'https://500px.com/seanarcher'
        html = get_one_page(url)
        for item in parse_one_page(html): # 只有50个图片,实际有400多个,还有待进一步研究
            # write_to_file3(item) # 保存到csv文件
            # save_to_mongo(item) # 保存到数据库
            download_image(item['image_url'])
    
    if __name__ == '__main__':
        main()

     

     

     效果截图:

    二:获取剩余图片

    复制其他也返回的json数据,构造如下形式:

     

    def parse_page_detail(data):
        image_data = data['photos']
        for i in range(len(image_data)):
            yield {
                'image_url': image_data[i]['image_url'][-3], # 图片链接有多种大小格式,选择格式最大的
            }
    
    # 请求图片url,获取图片二进制数据
    def download_image(url):
        try:
            response = requests.get(url)
            if response.status_code == 200:
                save_image(response.content)  # response.contenter二进制数据 response.text文本数据
            return None
        except RequestException:
            print('请求图片出错')
            return None
    
    
    def save_image(content):
        file_path = 'D:\pachong\500px_all\{1}.{2}'.format(os.getcwd(), md5(content).hexdigest(), 'jpg')
        if not os.path.exists(file_path):
            with open(file_path, 'wb') as f:
                f.write(content)
    
    
    def get_other(data):
        for item in parse_page_detail(data):
            download_image(item['image_url'])
    
    
    get_other(data_2)
    get_other(data_3)
    get_other(data_4)
    get_other(data_5)
    get_other(data_6)
    get_other(data_7)
    get_other(data_8)

    实际效果:
     
  • 相关阅读:
    python Unittest中setUp与setUpClass的区别
    Python的range和xrange的区别
    Python列表中的列表元素(嵌套列表)访问
    python字符串转为列表
    python正则匹配
    Python自动化测试用例设计--自动化测试用例与手工测试用例区别与联系
    Python+Selenium学习--自动化测试模型
    Python+Selenium学习--cookie处理
    Python+Selenium学习--控制浏览器控制条
    Python+Selenium学习--下载文件
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/10267790.html
Copyright © 2011-2022 走看看