美文网首页
大师兄的Python学习笔记(二十三): 爬虫(四)

大师兄的Python学习笔记(二十三): 爬虫(四)

作者: superkmi | 来源:发表于2020-07-24 17:01 被阅读0次

    大师兄的Python学习笔记(二十二): 爬虫(三)
    大师兄的Python学习笔记(二十四): 爬虫(五)

    五、爬取Ajax数据

    • 为了实现前后端分离,越来越多的网站使用Ajax制作动态页面。
    • 在这种情况下,原始页面获取不到有效数据,需要模拟Ajax请求获取数据。
    1. 关于Ajax
    • Ajax即异步的JavaScript和XML(Asynchronous JavaScript and XML), 是一种创建交互式网页应用的网页开发技术。
    • Ajax利用JS实现在页面不刷新,链接不改变的情况下与服务器交换数据并更新部分网页的能力。
    • 前台:HTML + JS + AJAX
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>sample</title>
        <script type="text/javascript">
            var xmlHttp;
    
            function createXmlHttpRequest()
            {
                //创建XMLHttpRequest对象的方法
                xmlHttp = new XMLHttpRequest();
                xmlHttp.onreadystatechange = readyStateChangeHandle;
                xmlHttp.open("GET","helloworld.xml",true);
                xmlHttp.send(null);
            }
    
            function readyStateChangeHandle()
            {   //如果完成读取
                if(xmlHttp.readyState == 4)
                {   //如果请求状态码为200
                    if(xmlHttp.status == 200)
                    {
                        var div = document.getElementById("div");
                        //接收服务器响应
                        var xmlDoc = xmlHttp.responseXML;
                        //解析服务器响应
                        var data = xmlDoc.getElementsByTagName("data")[0].firstChild.nodeValue;
                        div.innerHTML = "<i>"+data+"</i>";
                    }
                }
            }
        </script>
      </head>
      <body>
        <div id="div" style="display:flex;align-items: center;justify-content: center"></div>
        <div align="center" style="width:100%">
          <input type="button" value="获取后台数据" id="btn1" onclick="createXmlHttpRequest()">
        </div>
      </body>
    </html>
    
    • 后台:xml
    <?xml version="1.0" encoding="UTF-8"?>
    <HelloWorld>
        <data>
            HelloWorld from server!
        </data>
    </HelloWorld>
    
    • 效果


    2. 观察Ajax请求
    • Ajax请求的类型为XHR,在header中可以找到x-requested-with: XMLHttpRequest
    • 打开浏览器 -> 打开网页 -> 按f12 - > 切换到netword选项卡 -> 切换到xhr子选项卡 -> 触发Ajax- > 获得请求
    • 以头条网搜索(https://www.toutiao.com/search)为例。
    • 通过观察请求内容,可以获得请求的url和参数。


    4. 爬取Ajax数据
    • 用Python模拟浏览器发出Ajax请求:
    >>>import requests
    >>>from urllib.parse import urlencode
    
    >>>base_url = 'https://www.toutiao.com/api/search/content/?'
    >>>headers={
    >>>    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
    >>>    'x-Requested-With':'XMLHttpRequest'
    >>>}
    
    >>>def get_page():
    >>>    # 获取ajax数据
    >>>    params = {
    >>>        'aid':'24',
    >>>        'app_name':'web_search',
    >>>        'offset':'0',
    >>>        'format':'json',
    >>>        'keyword':'天问',
    >>>        'autoload':'true',
    >>>        'count':'20',
    >>>        'en_qc':'1',
    >>>        'cur_tab':'1',
    >>>        'from':'search_tab',
    >>>        'pd':'synthesis',
    >>>        'timestamp':'1595555856284',
    >>>        '_signature':'dmnSBgAgEBCwPmuLZGUZj3ZokxAACl20erea8yVotjl6bt0QyPm3C0IitmjZPdNLeqVl - m. - Anc.JeDoNUPwmgSxIQAjLH87GiPqebGl3ewifL.FLPgoxpud29vpujvqaIt'
    >>>    }
    >>>    url = base_url + urlencode(params)
    >>>    try:
    >>>        response = requests.get(url,headers=headers)
    >>>        if(response.status_code == 200):
    >>>            return response.json()
    >>>    except requests.ConnectionError as e:
    >>>        print('Error',e.args)
    
    >>>if __name__ == '__main__':
    >>>    data = get_page()
    >>>    print(len(data))
    26
    
    • 解析数据:
    >>>import requests
    >>>from urllib.parse import urlencode
    
    >>>base_url = 'https://www.toutiao.com/api/search/content/?'
    >>>headers={
    >>>    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
    >>>    'x-Requested-With':'XMLHttpRequest'
    >>>}
    
    >>>def parse_page(func):
    >>>    # 解析数据
    >>>    def deco(*args, **kwargs):
    >>>        data = filter(lambda x:x.get('abstract'),func(*args, **kwargs).get('data')) # 获取并过滤数据
    >>>        result = []
    >>>        for d in data:
    >>>            message = {}
    >>>            message['title'] = d.get('title')
    >>>            message['from'] = d.get('media_name')
    >>>            message['datetime'] = d.get('datetime')
    >>>            message['read_count'] = d.get('read_count')
    >>>            result.append(message)
    >>>        return result
    >>>    return deco
    
    >>>@parse_page
    >>>def get_page():
    >>>    # 获取ajax数据
    >>>    params = {
    >>>        'aid':'24',
    >>>        'app_name':'web_search',
    >>>        'offset':'0',
    >>>        'format':'json',
    >>>        'keyword':'天问',
    >>>        'autoload':'true',
    >>>        'count':'20',
    >>>        'en_qc':'1',
    >>>        'cur_tab':'1',
    >>>        'from':'search_tab',
    >>>        'pd':'synthesis',
    >>>        'timestamp':'1595555856284',
    >>>        '_signature':'dmnSBgAgEBCwPmuLZGUZj3ZokxAACl20erea8yVotjl6bt0QyPm3C0IitmjZPdNLeqVl - m. - Anc.JeDoNUPwmgSxIQAjLH87GiPqebGl3ewifL.FLPgoxpud29vpujvqaIt'
    >>>    }
    >>>    url = base_url + urlencode(params)
    >>>    try:
    >>>        response = requests.get(url,headers=headers)
    >>>        if(response.status_code == 200):
    >>>            return response.json()
    >>>    except requests.ConnectionError as e:
    >>>        print('Error',e.args)
    
    >>>if __name__ == '__main__':
    >>>    data = get_page()
    >>>    for index,value in enumerate(data):
    >>>        print(f'第{index}条 标题:<<{value.get("title")}>> 媒体:{value.get("from")} 日期:{value.get("datetime")} 阅读量:{value.get("read_count")} ')
    第0条 标题:<<屈原的天问及译文>> 媒体:律界诗者 日期:2020-07-23 21:14:28 阅读量:181 
    第1条 标题:<<上古奇文《天问》原文,屈原向上苍叩问宇宙本源>> 媒体:水煮歷史 日期:2018-10-24 14:21:55 阅读量:6850 
    第2条 标题:<<千古奇文:屈原《楚辞》中的《天问》>> 媒体:泽光书院 日期:2020-05-01 19:43:47 阅读量:491 
    第3条 标题:<<火星探测器为什么取名“天问”?第一时间解读火星探索 4 大问题>> 媒体:科学声音 日期:2020-07-24 10:27:47 阅读量:18 
    第4条 标题:<<屈原《天问》原文与释文>> 媒体:书画鉴赏典评收藏 日期:2019-05-04 21:05:38 阅读量:835 
    第5条 标题:<<天问一号成功发射,马斯克发推祝贺:令人惊叹>> 媒体:观察者网 日期:2020-07-23 18:01:08 阅读量:7764 
    第6条 标题:<<中国历史性一天!火星探测器“天问一号”发射成功,领先美国>> 媒体:智东西 日期:2020-07-23 14:03:21 阅读量:9509 
    第7条 标题:<<中国首次火星探测任务“天问一号”探测器成功发射,马斯克发推:令人惊叹>> 媒体:环球网 日期:2020-07-23 20:00:44 阅读量:1718 
    

    参考资料



    本文作者:大师兄(superkmi)

    相关文章

      网友评论

          本文标题:大师兄的Python学习笔记(二十三): 爬虫(四)

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