Python Webクローラー研究ノート(11):Ajaxデータクロール


リクエストを使用してページを取得すると、取得する結果がブラウザに表示されるものと異なる場合があります。通常はブラウザに表示されるページデータを表示できますが、リクエストを使用して取得した結果は表示されません。これは、取得したリクエストがすべて元のHTMLドキュメントであり、ブラウザのページがJavaScriptでデータを処理した後に生成された結果であるためです。これらのデータのソースは多数あり、Ajaxを介して読み込まれ、HTMLに含まれる場合があります。ドキュメント内のドキュメントは、JavaScriptおよび特定のアルゴリズムによる計算後に生成される場合もあります。

前者の場合、データの読み込みは非同期の読み込み方法です。元のページには最初は一部のデータが含まれていません。元のページが読み込まれた後、サーバーにインターフェイスを要求してデータを取得し、データを処理して表示します。 Webページでは、これは実際にはAjaxリクエストです。

Web開発の動向によると、このフォームのページはますます増えています。Webページの元のHTMLドキュメントにはデータが含まれていません。データはAjaxを介して均一にロードされた後に表示されるため、Web開発でフロントエンドとバックエンドを分離でき、サーバーがページを直接レンダリングする際の負荷を軽減できます。

したがって、このようなページに遭遇した場合、リクエストや他のライブラリを直接使用して元のページを取得でき、有効なデータを取得できません。現時点では、ウェブページのバックエンドからインターフェースに送信されたAjaxリクエストを分析する必要があります。リクエストを使用してAjaxリクエストをシミュレートできる場合は、正常にクロールできます。

1.基本的な紹介

Ajax、フルネームは非同期JavaScriptとXML、つまり非同期JavaScriptとXMLです。これはプログラミング言語ではありませんが、JavaScriptを使用してサーバーとデータを交換し、Webページの一部を更新すると同時に、ページが更新されず、ページリンクが変更されないようにするテクノロジです。

一部のWebページでは、下にスライドし続けると、読み込まれたページが表示されます。しばらくすると、新しいコンテンツが引き続き下に表示されます。このプロセスは、実際にはAjaxの読み込みプロセスです。

ページが完全に更新されていないことに気付きました。つまり、ページのリンクは変更されていませんが、ページに新しいコンテンツがあります。これは、後で投稿された新しいWeiboです。これは、新しいデータを取得し、Ajaxを介して提示するプロセスです。

2.基本原則

Ajaxを事前に理解した後、その基本原則について詳しく学びましょう。AjaxリクエストをWebページの更新に送信するプロセスは、次の3つのステップに簡単に分けることができます。

(1)リクエストを送信します;(2)コンテンツを分析します;(3)Webページをレンダリングします。

これらのプロセスを以下に詳しく紹介します。

リクエストの送信
JavaScriptはページのさまざまなインタラクティブ機能を実装でき、Ajaxも例外ではありません。JavaScriptによっても実装されます。実際には、次のコードが実行されます。

var xmlhttp;
if (window.XMLHttpRequest) {
    
    
    // code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp=new XMLHttpRequest();
} else {
    
    // code for IE6, IE5
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function() {
    
    
    if (xmlhttp.readyState==4 && xmlhttp.status==200) {
    
    
        document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
    }
}
xmlhttp.open("POST","/ajax/",true);
xmlhttp.send();

これは、JavaScriptのAjaxの最下位レベルの実装です。実際、新しいXMLHttpRequestオブジェクトを作成し、onreadystatechangeプロパティを呼び出してリスナーを設定し、open()メソッドとsend()メソッドを呼び出してリンク(つまりサーバー)に要求を送信します。Pythonでリクエストを送信した後、レスポンスの結果を取得できますが、JavaScriptでリクエストの送信を完了します。モニタリングが設定されているため、サーバーがレスポンスを返すと、onreadystatechangeに対応するメソッドがトリガーされ、このメソッドで応答の内容を解析するだけです。

したがって、実際のデータはAjaxリクエストから何度も何度も取得されることがわかっています。このデータを取得する場合は、これらのリクエストがどのように送信されるか、どこに送信されるか、どのパラメータが送信されるかを知る必要があります。これがわかっている場合は、Pythonを使用してこの送信操作をシミュレートし、結果を取得できます。

3.実際の戦闘

プログラムを使用してこれらのAjaxリクエストをシミュレートし、Weiboの最初の10ページをクロールします

from urllib.parse import urlencode
import requests
base_url = 'https://m.weibo.cn/api/container/getIndex?'
 
headers = {
    
    
    'Host': 'm.weibo.cn',
    'Referer': 'https://m.weibo.cn/u/2830678474',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest',
}
 
def get_page(page):
    params = {
    
    
        'type': 'uid',
        'value': '2830678474',
        'containerid': '1076032830678474',
        'page': page
    }
    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)

まず、ここではbase_url、要求されたURLの前半を表すように定義されています。次に、パラメータ辞書を作成します。ここtype、、valueおよびcontaineridは固定パラメータとpage可変パラメータです。次に、このフォームurlencode()と同様にメソッドを呼び出してパラメーターをURLGET要求パラメーターに変換しますtype=uid&value=2830678474&containerid=1076032830678474&page=2その後、base_urlパラメータ組み合わせて新しいURLを形成します。次に、requestsこのリンクリクエストしてheadersパラメータを追加します。次に、応答のステータスコードを決定します。200の場合は、json()メソッドを直接呼び出してコンテンツを解析し、JSONとして返します。そうでない場合、情報は返されません。例外が発生した場合は、その例外情報を取得して出力します。

後で、結果から必要な情報を抽出するための解析方法を定義する必要があります。たとえば、WeiboのID、本文、いいねの数、コメントの数、再投稿の数のコンテンツを保存する場合は、最初にカードをトラバースできます。 、次に、mblogで各情報を取得し、それを新しい辞書に割り当てて返します。

from pyquery import PyQuery as pq

def parse_page(json):
    if json:
        items = json.get('data').get('cards')
        for item in items:
            item = item.get('mblog')
            weibo = {
    
    }
            weibo['id'] = item.get('id')
            weibo['text'] = pq(item.get('text')).text()
            weibo['attitudes'] = item.get('attitudes_count')
            weibo['comments'] = item.get('comments_count')
            weibo['reposts'] = item.get('reposts_count')
            yield weibo

ここでは、pyqueryを使用して本文のHTMLタグを削除します。

最後に、合計10ページのページをトラバースし、抽出された結果を印刷します。

if __name__ == '__main__':
    for page in range(1, 11):
        json = get_page(page)
        results = parse_page(json)
        for result in results:
            print(result)
{'id': '4544491111844364', 'text': '老婆真好啊,今天感觉工作有点累不太开心,然后老婆晚上和我开了一下视频对我笑了笑撒了撒娇,我瞬间又开心又好了,感觉心里暖暖的,我老婆最好了!', 'attitudes': 12, 'comments': 3, 'reposts': 0}
{'id': '4543259479641769', 'text': '我老婆最好看了', 'attitudes': 12, 'comments': 0, 'reposts': 0}
{'id': '4543252072761828', 'text': '不知道大家是否已经对抖音有了一种厌倦?最早的时候我觉得内容质量还行,现在没刷几个视频,很多都是广告、带货、博人眼球、摆拍、空洞的内容,质量越来越差,越看越没劲,卸了卸了,还是撸代码好玩。', 'attitudes': 10, 'comments': 8, 'reposts': 0}
{'id': '4541086507209784', 'text': '铁窗爱情3', 'attitudes': 23, 'comments': 3, 'reposts': 1}
{'id': '4541085119162017', 'text': '即便没收费,那直播搞这个操作也是太服了。', 'attitudes': 3, 'comments': 0, 'reposts': 0}
{'id': '4539580352832042', 'text': '铁窗爱情2', 'attitudes': 3, 'comments': 4, 'reposts': 0}
{'id': '4538323178106309', 'text': '老婆返校了,但是出不来,于是就有了铁窗爱情。@长泽牙妹 北京', 'attitudes': 20, 'comments': 6, 'reposts': 0}

おすすめ

転載: blog.csdn.net/qq_43328040/article/details/108850338
おすすめ