Heim > Artikel > Backend-Entwicklung > So analysieren Sie Ajax-Anfragen für von JS gerenderte Webseiten
Wenn wir Python zum Crawlen verwenden, ist uns möglicherweise aufgefallen, dass der durch direkte Anfrage von einigen Webseiten erhaltene HTML-Code nicht die Daten enthält, die wir benötigen, was wir im Browser sehen.
Dies liegt daran, dass die Informationen über Ajax geladen und durch JS-Rendering generiert werden. Zu diesem Zeitpunkt müssen wir die Anfrage dieser Webseite analysieren.
Im vorherigen Artikel wurde erklärt, was ein Cookie ist und wie die simulierte Anmeldung funktioniert. Heute zeige ich Ihnen, wie Sie die Ajax-Anfrage der Webseite analysieren.
Was ist Ajax?AJAX ist „Asynchronous Javascript And XML“ (asynchrones JavaScript und XML), was sich auf eine Erstellung bezieht Webentwicklungstechnologie für interaktive Webanwendungen.
AJAX = Asynchrones JavaScript und XML (eine Teilmenge der Standard Universal Markup Language).AJAX ist eine Technologie zur Erstellung schneller, dynamischer Webseiten.
AJAX ist eine Technologie, die Teile einer Webseite aktualisieren kann, ohne die gesamte Seite neu laden zu müssen.
Um es einfach auszudrücken: Die URL in der Adressleiste des Browsers hat sich nicht geändert. Es handelt sich um eine asynchron geladene Webseite, die Ajax sein sollte. AJAX sendet Anforderungen im Allgemeinen über die XMLHttpRequest-Objektschnittstelle, und XMLHttpRequest wird im Allgemeinen als XHR abgekürzt.
Unsere Zielwebsite wird mit Guoke.com analysiert.
Wir können sehen, dass diese Webseite keine Schaltfläche zum Umblättern hat, und wenn wir die Anfrage weiter herunterziehen, lädt die Webseite automatisch mehr Inhalte für uns. Wenn wir jedoch die URL der Webseite beobachten, stellen wir fest, dass sie sich mit der Ladeanforderung der Webseite nicht ändert. Und wenn wir diese URL direkt anfordern, können wir natürlich nur den HTML-Inhalt der ersten Seite erhalten.
Wie erhalten wir dann die Daten aller Seiten?Wir öffnen die Entwicklertools (F12) in Chrome. Wir klicken auf „Netzwerk“ und dann auf das XHR-Label. Dann aktualisieren wir die Webseite und ziehen die Anfrage herunter. Zu diesem Zeitpunkt können wir das XHR-Tag sehen und jedes Mal, wenn die Webseite geladen wird, wird eine Anfrage angezeigt.
Wenn wir auf die erste Anfrage klicken, können wir deren Parameter sehen:
retrieve_type:by_subject limit:20 offset:18 -:1500265766286
Wenn wir auf die zweite Anfrage klicken, sind die Parameter wie folgt:
retrieve_type:by_subject limit:20 offset:38 -:1500265766287
Das Limit Parameter ist Each Die Seite begrenzt die Anzahl der geladenen Artikel und Offset ist die Anzahl der Seiten. Wenn wir nach unten schauen, werden wir feststellen, dass der Offset-Parameter jeder Anfrage um 20 erhöht wird.
Wir schauen uns dann den Antwortinhalt jeder Anfrage an. Dabei handelt es sich um Daten in einem Format. Wenn wir auf die Schaltfläche „Ergebnis“ klicken, können wir die Dateninformationen von 20 Artikeln sehen. Auf diese Weise haben wir den Speicherort der benötigten Informationen erfolgreich gefunden. Wir können die URL-Adresse sehen, unter der die JSON-Daten im Anforderungsheader gespeichert sind.
Crawling-Prozess
Analysieren Sie Ajax-Anfragen, um die Artikel-URL-Informationen jeder Seite zu erhalten; analysieren Sie jeden Artikel, um die erforderlichen Daten zu erhalten; starten Sie mehrere Prozesse und crawlen Sie a große Anzahl von Pick.
StartUnser Tool verwendet weiterhin Anfragen und BeautifulSoup-Parsing.
Zuerst müssen wir die Ajax-Anfrage analysieren, um die Informationen aller Seiten zu erhalten. Durch die obige Analyse der Webseite können wir die URL-Adresse der von Ajax geladenen JSON-Daten erhalten:
http: //www. guokr.com/apis/minisite/article.json?retrieve_type=by_subject&limit=20&offset=18Wir müssen diese URL erstellen.
# 导入可能要用到的模块 import requests from urllib.parse import urlencode from requests.exceptions import ConnectionError # 获得索引页的信息 def get_index(offset): base_url = 'http://www.guokr.com/apis/minisite/article.json?' data = { 'retrieve_type': "by_subject", 'limit': "20", 'offset': offset } params = urlencode(data) url = base_url + params try: resp = requests.get(url) if resp.status_code == 200: return resp.text return None except ConnectionError: print('Error.') return None
Wir konstruieren die von der obigen Analyseseite erhaltenen Anforderungsparameter in Wörterbuchdaten und können dann die URL manuell erstellen, aber die URLlib-Bibliothek hat uns eine Codierungsmethode zur Verfügung gestellt. Verwenden Sie es direkt, um eine vollständige URL zu erstellen. Dann gibt es noch Standardanfragen zum Anfordern von Seiteninhalten.
import json # 解析json,获得文章url def parse_json(text): try: result = json.loads(text) if result: for i in result.get('result'): # print(i.get('url')) yield i.get('url') except: pass
Wir verwenden die Methode josn.loads, um JSON zu analysieren und in ein JSON-Objekt zu konvertieren. Rufen Sie dann die URL-Adresse des Artikels direkt über die Wörterbuchoperation ab. Hier wird Yield verwendet und jede Anfrage gibt eine URL zurück, um den Speicherverbrauch zu reduzieren. Da ich später einen JSON-Parsing-Fehler bekam, habe ich ihn einfach hier gefiltert.
Hier können wir versuchen zu drucken und zu sehen, ob es erfolgreich läuft.
既然获得了文章的url,那么对于获得文章的数据就显得很简单了。这里不在进行详细的叙述。我们的目标是获得文章的标题,作者和内容。
由于有的文章里面包含一些图片,我们直接过滤掉文章内容里的图片就好了。
from bs4 import BeautifulSoup # 解析文章页 def parse_page(text): try: soup = BeautifulSoup(text, 'lxml') content = soup.find('div', class_="content") title = content.find('h1', id="articleTitle").get_text() author = content.find('div', class_="content-th-info").find('a').get_text() article_content = content.find('div', class_="document").find_all('p') all_p = [i.get_text() for i in article_content if not i.find('img') and not i.find('a')] article = '\n'.join(all_p) # print(title,'\n',author,'\n',article) data = { 'title': title, 'author': author, 'article': article } return data except: pass
这里在进行多进程抓取的时候,BeautifulSoup也会出现一个错误,依然直接过滤。我们把得到的数据保存为字典的形式,方便保存数据库。
接下来就是保存数据库的操作了,这里我们使用Mongodb进行数据的存储。
import pymongo from config import * client = pymongo.MongoClient(MONGO_URL, 27017) db = client[MONGO_DB] def save_database(data): if db[MONGO_TABLE].insert(data): print('Save to Database successful', data) return True return False
我们把数据库的名字,和表名保存到config配置文件中,在把配置信息导入文件,这样会方便代码的管理。
最后呢,由于果壳网数据还是比较多的,如果想要大量的抓取,我们可以使用多进程。
from multiprocessing import Pool # 定义一个主函数 def main(offset): text = get_index(offset) all_url = parse_json(text) for url in all_url: resp = get_page(url) data = parse_page(resp) if data: save_database(data) if __name__ == '__main__': pool = Pool() offsets = ([0] + [i*20+18 for i in range(500)]) pool.map(main, offsets) pool.close() pool.join()
函数的参数offset就是页数了。经过我的观察,果壳网最后一页页码是 12758,有 637 页。这里我们就抓取 500 页。进程池的map方法和Python内置的map方法使用类似。
好了,对于一些使用Ajax加载的网页,我们就可以这么抓取了。
Das obige ist der detaillierte Inhalt vonSo analysieren Sie Ajax-Anfragen für von JS gerenderte Webseiten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!