抓取ajax动态网页java(大多数网页数据都是通过动态渲染加载的,即常说的Ajax方式 )
优采云 发布时间: 2021-09-29 20:19抓取ajax动态网页java(大多数网页数据都是通过动态渲染加载的,即常说的Ajax方式
)
目前的网页数据大部分是通过动态渲染加载的,也就是通常所说的Ajax方式。在这种类型的网站 爬取数据中通常是没有网页加载数据的。一般是找到动态加载页面然后获取数据,本文分析今日头条网站,搜索关键词获取搜索页面的图片和标题,最后通过简单的多线程保存到本地下载。
1:打开今日头条主页,网址:今日头条主页
页面右上角有一个搜索框,搜索关键词加载关键词信息。
2:分析页面
点击搜索后,页面重新加载并返回关键字信息界面。此页面未找到具体内容信息。由此可以判断它是一个Ajax加载页面。我们可以通过网络上的XHR查看加载信息。
这里可以看到加载信息的url,也可以看到下面的请求头信息。
我们在响应中观察返回网页的源代码,可以发现所有的数据都在这里。
页面信息的数据中是具体的信息,如标题、图片列表等,我们可以通过这里获取信息来获取数据。
3:多页面数据分析
当页面向下滑动到最后时,会自动加载新的一页数据。这里我们观察后续链接的参数。我们可以发现唯一改变的参数是offset。第一次请求时偏移量为0,第二次请求时偏移值是20,第三次是40,第四次是60,所以我们可以找到规则,这个偏移值就是反向页偏移,然后我们可以推断count参数就是一次获取的数据个数,所以我们可以使用offset参数来控制数据分页。这样我们就可以通过接口批量获取数据,然后解析数据下载图片。
其实通过传入URL关键词,还可以进一步实现关键词下载头条图片。
4:程序实现
只下载第一页
import requests
from urllib.parse import urlencode #用 urlencode() 方法构造请求的 GET 参数
import os
from hashlib import md5
headers = {
'Host': 'www.toutiao.com',
'Referer': 'https://www.toutiao.com/search/?keyword=香港',
'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',
'Cookie': 'tt_webid=6704808321848215043; WEATHER_CITY=武汉; UM_distinctid=16b77e85ac24d7-006d237c790a88-4a5568-1fa400-16b77e85ac344b; CNZZDATA1259612802=1104480020-1561079689-%7C1561079689; __tasessionId=n39mykl9q1561084844772; tt_webid=6704808321848215043; csrftoken=dcd1d465bc7441c32e8f77a18e4dcb62; s_v_web_id=bfc941bbb6430551a71c9f370afd2c71TE: Trailers'
}
def get_page(offset):
params={
'aid':24,
'app_name':'web_search',
'format':'json',
'keyword':'香港',
'autoload':'true',
'count':20,
'en_qc':1,
'from':'search_tab',
'pd':'synthesis',
'timestamp':'1561085020266',
'offset':offset
}
url='https://www.toutiao.com/api/search/content/?'+urlencode(params)
response=requests.get(url,headers=headers)
if response.status_code==200:
return response.json()
return None
def get_image(page):
if page.get('data'):
for item in page.get('data'):
title=item.get('title',None)
image_list=item.get('image_list',[])
if title:
yield { #*敏*感*词*,返回标题和图像url列表
'title':title,
'image_list':image_list
}
def save_image(item):
if not os.path.exists('E:\\toutiao\\'+item.get('title')): #如果不存在就创建
os.mkdir('E:\\toutiao\\'+item.get('title'))
for img in item.get('image_list'):
print(img.get('url'))
response=requests.get(img.get('url'))
if response.status_code==200:
file_path='E:\\toutiao\\{0}\\{1}.{2}'.format(item.get('title'),
md5(response.content).hexdigest(),
'jpg') #使用MD5编码,防止命名重复
if not os.path.exists(file_path):
with open(file_path,'wb') as f:
f.write(response.content) #下载二进制数据
else:
print('已经下载了')
else:
print(response.reason)
if __name__ == '__main__':
x=get_page(0)
for y in get_image(x):
save_image(y)
多线程下载多个页面
在上述程序的基础上增加一个新的main函数main
from multiprocessing.pool import Pool
def main(offset):
json = get_page(offset)
for item in get_images(json):
print(item)
save_image(item)
GROUP_START = 1 #其实页面
GROUP_END = 20 #终止页面
if __name__ == '__main__':
pool = Pool() #创建多线程
groups = ([x * 20 for x in range(GROUP_START, GROUP_END + 1)]) #构造多个参数
pool.map(main, groups) #传入多个参数,多个函数同时运行
pool.close()
pool.join()