zoukankan      html  css  js  c++  java
  • python爬虫从小白到高手 Day2 动态页面的爬取

    今天我们说说动态页面的抓取,动态页面的概念不是说网页上的内容是活动的,而是刷新的内容由Ajax加载,页面的URL没有变化,具体概念问度娘。
    就以男人都喜欢的美女街拍为例,对象为今日头条。
    chrome打开今日头条 ->搜索
    https://www.toutiao.com/search/?keyword=街拍
    开发者工具->network选项卡
    图2-1
    很多条目,各种请求,但Ajax其实有其特殊的请求类型,它叫作xhr。在图6-3中,我们可以发现一个名称以getIndex开头的请求,其Type为xhr,这就是一个Ajax请求。用鼠标点击这个请求,可以查看这个请求的详细信息。
    图2-2
    选中这个xhr请求后,我们可以看到Request Headers中X-Requested-With:XMLHttpRequest,这就标记了此请求是Ajax请求。
    点击一下Preview,即可看到响应的内容,它是JSON格式的。这里Chrome为我们自动做了解析,点击箭头即可展开和收起相应内容,初步分析这里返回的是页面上显示出来的前二十条信息。
    图2-3
    切换回第一个请求,我们发现Response中的信息是这样的
    图2-4
    这就是原始链接 https://www.toutiao.com/search/?keyword=街拍 所返回的内容,只有六十多行代码,执行了一些JavaScript,所以我们最终看到的页面不是由初始页面返回的,而是后来执行的JavaScript向服务器发送了Ajax请求,收到返回的真实数据后才显示出来的。这就是动态页面渲染的流程。
    明白了整个流程后,我们要做的最重要的事就是分析返回数据的内容,用python模拟Ajax请求,拿到我们所希望抓取的数据。
     
     
    get_page'offset',
    'format''json''keyword''街拍''autoload''true''count''20''cur_tab''1''from''search_tab'}
    'https://www.toutiao.com/search_content/?'
    try, =params)
    if 200return except return None
     
     
    下滑几次后,发现只有offset参数变化,所以,构造url,requests获得数据
    这里拿到的数据是json格式的
     
     
    download_imageif 'data'for in 'data'if and in title 'title''article_url'
    if '''
     
    取出数据中的data段,发现只有前四张图片的地址可以取到,剩下的图片必须进入文章页才能获得,我们取出文章页的url,requests获得文章页数据
     
    get_real_image_path'user-agent''Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36', =headers)
    , )
    'title'0'gallery: JSON.parse("(.*?)"),'re.S)
    ,
    if 1''''
    if and in 'sub_images''url'for in for in
    return 'title',
    'url' ,
    'image_urls'
    这里需要加入UA头,否则返回不了数据,拿到数据后,发现图片地址位于
    图2-5
     
    这里用正则表达式
    匹配符合条件的,gallery: JSON.parse("")中的数据()这里在正则中表达的是转义字符,有兴趣的可以学习一下正则表达式,这里就不赘述了
     
    我们从sub_images中拿到了所有图片地址,下载过程就很简单了
    requests图片地址,获得的response中的content就是图片的数据
     
    download_real_imageprint'downloading---'url)
    tryif 200return None
    RequestException:
    print'request image fail---'url)
    return None
     
    save_image'{0}/{1}', )
    if not
    '{0}/{1}.{2}', , )
    if not with (file_path'wb'as
    我们还可以把图片的标题和地址写入数据库
     
    save_to_mongoif print'save success'result)
    return True
     
    完整代码:
     jrtt.py
     
    import requests
    import re
    import json
    from hashlib import md5
    import os
    from bs4 import BeautifulSoup
    import pymongo
    from config import *
    import time
    
    
    
    client = pymongo.MongoClient(MONGO_URL, connect=False)
    db = client[MONGO_DB]
    
    def get_page(offset):
        params = {
            'offset': offset,
            'format': 'json',
            'keyword': '街拍',
            'autoload': 'true',
            'count': '20',
            'cur_tab': '1',
            'from': 'search_tab',
        }
        url = 'https://www.toutiao.com/search_content/?'
        try:
            response = requests.get(url, params=params)
            if response.status_code == 200:
                return response.json()
        except requests.ConnectionError:
            return None
    
    def save_to_mongo(result):
        if db[MONGO_TABLE].insert(result):
            print('save success', result)
            return True
        return False
    
    def download_real_image(url):
        print('downloading---', url)
        try:
            response = requests.get(url)
            if response.status_code == 200:
                save_image(response.content)
            return None
        except RequestException:
            print('request image fail---', url)
            return None
    
    
    def save_image(content):
        files_path = '{0}/{1}'.format(os.getcwd(), 'tupian')
        if not os.path.exists(files_path):
            os.mkdir(files_path)
    
        file_path = '{0}/{1}.{2}'.format(files_path, md5(content).hexdigest(), 'jpg')
        if not os.path.exists(file_path):
            with open(file_path, 'wb') as f:
                f.write(content)
    
    
    def get_real_image_path(article_url):
        headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}
        response = requests.get(article_url, headers=headers)
        soup = BeautifulSoup(response.text, "lxml")
        title = soup.select('title')[0].get_text()
        image_pattern = re.compile('gallery: JSON.parse("(.*?)"),', re.S)
        result = re.search(image_pattern, response.text)
    
    
        if result:
            result = result.group(1).replace('\', '')
            data = json.loads(result)
    
            if data and 'sub_images' in data.keys():
                sub_images = data.get('sub_images')
                images_urls = [item.get('url') for item in sub_images]
                for image_url in images_urls: download_real_image(image_url)
    
                return {
                    'title': title,
                    'url' : article_url,
                    'image_urls': images_urls
                }
    
    
    
    def download_image(jsonData):
        if jsonData.get('data'):
            for item in jsonData.get('data'):
                if item and 'article_url' in item.keys():
                    title = item.get('title')
                    article_url = item.get('article_url')
                    result = get_real_image_path(article_url)
    
                    if result: save_to_mongo(result)
                '''
                另外一种数据格式cell,cell type太多,主要分析上面一种
                else:
                    #original_page_url
                    data = item.get('display')
                    #print(display)
                    #data = json.loads(display)
                    #print(data)
                    if data and 'results' in data.keys():
                        results = data.get('results')
                        original_page_urls = [item.get('original_page_url') for item in results]
                    # .get('results').get('original_page_url')
                    #title = item.get('display').get('title')
                    #print(title)
                    #print(original_page_urls)'''
    
    
    def main():
    
        STARTPAGE = 1
        ENDPAGE = 2
    
        for i in range(STARTPAGE, ENDPAGE):
            time.sleep(1)
            offset = i * 20
            jsonData = get_page(offset)
            download_image(jsonData)
    
    if __name__ == "__main__":
        main()

    config.py

    MONGO_URL = 'localhost'
    
    MONGO_DB = 'jiepai'
    
    MONGO_TABLE = 'jiepai'
    
    GROUP_START = 0
    
    GROUP_END = 20
    
    KEYWORD = '街拍'
     
  • 相关阅读:
    环境是如何建立的 启动文件有什么
    环境中存储的是什么
    串行 并行 异步 同步
    TPC-H is a Decision Support Benchmark
    进程通信类型 管道是Linux支持的最初Unix IPC形式之一 命名管道 匿名管道
    删除环境变量
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
  • 原文地址:https://www.cnblogs.com/dmpang/p/9215322.html
Copyright © 2011-2022 走看看