ajax抓取网页内容(本篇文章我们来研究一下怎么分析网页的Ajax请求(图))
优采云 发布时间: 2022-02-25 16:11ajax抓取网页内容(本篇文章我们来研究一下怎么分析网页的Ajax请求(图))
在本文文章中,我们将研究如何分析网页的Ajax请求。
我们平时爬网页的时候,可能会遇到一些网页直接请求的HTML代码,并没有我们需要的数据,也就是我们在浏览器中看到的内容。
这是因为信息是通过 Ajax 加载并通过 js 渲染生成的。这时,我们需要分析这个网页的请求。
什么是阿贾克斯
AJAX 代表“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),指的是一种用于创建交互式 Web 应用程序的 Web 开发技术。
AJAX = 异步 JavaScript 和 XML(标准通用标记语言的子集)。
AJAX 是一种用于创建快速和动态网页的技术。
AJAX 是一种无需重新加载整个网页即可更新部分网页的技术。
简单地说,就是加载了网页。浏览器地址栏中的 URL 没有改变。是javascript异步加载的网页,应该是ajax。AJAX一般通过XMLHttpRequest对象接口发送请求,一般简称为XHR。
分析简而言之网站点
我们的目标网站是用壳网来分析。地址
我们可以看到这个网页没有翻页按钮,当我们不断拉下请求时,网页会自动为我们加载更多内容。但是,当我们查看网页 url 时,它并没有随着页面加载请求而改变。而当我们直接请求这个url时,显然只能获取到第一页的html内容。
那么我们如何获取所有页面的数据呢?
我们在Chrome中打开开发者工具(F12)。我们点击Network,点击XHR选项卡。然后我们刷新页面并拉下请求。这时候我们可以看到XHR选项卡,每次页面加载会弹出一个请求。
我们点击第一个请求,可以看到他的参数:
检索类型:按主题
限制:20
偏移量:18
-:86
点击第二个请求后,参数如下:
检索类型:按主题
限制:20
偏移量:38
-:87
limit参数是网页每页被限制加载的文章个数,offset是页数。然后往下看,我们会发现每次请求的offset参数都会增加20。
然后我们查看每个请求的响应内容,这是一个格式化的数据。我们点击结果按钮,可以看到20条文章的数据信息。这样我们就成功找到了我们需要的信息的位置,在请求头中可以看到json数据存放的url地址。;limit=20&offset=18
爬取过程开始
我们的工具仍然使用 BeautifulSoup 解析的请求。
首先,我们需要对Ajax请求进行分析,获取所有页面的信息。通过上面网页的分析,我们可以得到ajax加载的json数据的url地址:;limit=20&offset=18
我们需要构造这个 URL。
# 导入可能要用到的模块
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
我们将从上面分析页面得到的请求参数构造成字典数据,然后我们可以手动构造url,但是urllib库已经为我们提供了编码方式,我们可以直接使用它来构造完整的url。然后是请求页面内容的标准请求。
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
我们使用 josn.loads 方法解析 json 并将其转换为 json 对象。然后直接通过字典的操作,得到文章的url地址。这里使用yield为每个请求返回一个url,以减少内存消耗。由于后面爬的时候会弹出一个json解析错误,这里直接过滤就好了。
这里我们可以尝试打印看看是否运行成功。
既然获取了文章的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()
该函数的参数偏移量是页数。经过我的观察,国科网的最后一个页码是12758,有637页。在这里,我们抓取了 500 个页面。进程池的map方法类似于Python内置的map方法。
那么对于一些使用Ajax加载的网页,我们可以这样爬取。
项目地址
这里
如果觉得有帮助,请star。
谢谢阅读
系列文章