python抓取动态网页(web页面使用ajax技术动态加载页面的解决办法内存开销 )

优采云 发布时间: 2021-12-03 15:00

  python抓取动态网页(web页面使用ajax技术动态加载页面的解决办法内存开销

)

  现在很多网页都使用ajax技术来动态加载页面。但是对于爬虫来说,目标数据可能不在页面的HTML源代码中(右键查看网页源代码,F12搜索),静态页面的爬虫已经不能满足当前的需求.

  很多教程推荐结合使用Selenium和PhantomJS来渲染网页,获取网页的所有信息。但是对于爬虫程序来说,模拟浏览器的内存开销很大,效率很低。

  好消息是,大部分浏览器在请求解析完 HTML 后,会根据 js 的“指令”发送另一个请求,获取页面显示的内容,然后通过 js 渲染后显示到界面上。这类请求的内容往往是json格式,这样既不会加重爬虫任务,反而可以省去解析HTML的工作量。

  本文以抓取某位名人在Instagram上传的所有图片为例,讲解动态加载页面的解决方案。文末附上所有代码

  

  工具:铬

  包:json、请求、urllib

  分析ins页面

  

  一个用户的主页

  打开一个用户ins的首页(),可以看到首页只加载了12张图片,点击“更多”会加载更多图片。我们先来获取这12张图片的网址。

  获取前12张图片的URL

  首先检查源代码中是否存在图片的URL。在脚本标签中找到了前 12 张图片的 URL。

  

  网页源代码

  有了这个发现,我们可以提取到首页的12个图片网址!!

  代码显示如下:

  

  

  通过使用lxml库实现解析,不懂lxml的小朋友可以去崔大神的博客学习。

  获取更多图片的网址

  当我单击“更多”按钮时,我发现 XHR 选项卡中加载了一些新文件。

  

  加载前

  

  加载后

  每次页面下拉,加载12张图片,“?query_idbalabala”文件也会加1个!

  

  单击文件可查看详细信息。发现文件返回的是json数据,数据中收录了我们想要的图片网址!!

  

  返回的json数据

  所以只要拿到这些json数据,就可以提取出更多的图片网址。

  

  索取资料

  

  索取资料

  

  索取资料

  仔细查看上图中的Request URL,让我们分析一下它的请求参数(包括query_id、id、first、after),可以看到后续加载的query_id为“059182”,“id”为你访问的用户的用户id,即“1161353543”,“first”是一次加载的图片数量,总是12,“after”比较复杂。但是按照常识,这个参数应该在之前的文件中可以找到。

  找到“之后”

  使用ctrl+F查找页面源码中after参数对应的值。脚本标签中也是一样,只是对应的键名是“end_cursor”

  

  采集了四个请求参数,现在我们可以构造Request URL,通过解析返回的json数据获取更多的图片URL

  

  代码显示如下:

  

  src_list中保存了用户590张图片的URL,现在是时候进入下载链接了~

  下载图片

  博主懒得换代理,直接用最简单粗暴的方式下载图片。

  

  结果显示~

  

  所有代码

  # -*- coding: utf-8 -*-

import json

import requests

from lxml import etree

from urllib import parse

BASE_URL = "https://www.instagram.com/urnotchrislee/"

headers = {

"Origin": "https://www.instagram.com/",

"Referer": "https://www.instagram.com/urnotchrislee/",

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "

"Chrome/58.0.3029.110 Safari/537.36",

"Host": "www.instagram.com"}

def load_rest(table,has_next_page):

rest = []

while has_next_page:

text = json.dumps(table)

URL = 'https://www.instagram.com/graphql/query/?query_id=17888483320059182&variables='+parse.quote(text)

res = requests.get(URL,headers = headers)

dic = json.loads(res.content.decode(),encoding='utf-8')

data = dic['data']['user']['edge_owner_to_timeline_media']

nodes = data['edges']

end_cursor = data['page_info']['end_cursor']

has_next_page = data['page_info']['has_next_page']

for node in nodes:

rest.append(node['node']['display_url'])

#print(node['node']['display_url'])

table['after'] = end_cursor

print('加载..')

print('加载完成')

return rest

if __name__=='__main__':

res = requests.get(BASE_URL,headers = headers)

html = etree.HTML(res.content.decode())

# h = html.xpath('''//script[@type="text/javascript"]/text()''')[1].replace('window._sharedData =','').strip()

h = html.xpath('''//script[@type="text/javascript"]''')[1].text.replace('window._sharedData = ','').strip()[:-1]

dic = json.loads(h,encoding='utf-8')

data = dic['entry_data']['ProfilePage'][0]['user']['media']

nodes = data['nodes']

end_cursor = data['page_info']['end_cursor']

has_next_page = data['page_info']['has_next_page']

lee_id = nodes[0]["owner"]["id"] #'1161353543'

src_list = []

for node in nodes:

src_list.append(node['display_src'])

print(node['display_src'])

print('加载')

table = {

'id':lee_id,

'first':12,

'after':end_cursor}

rest = load_rest(table,has_next_page)

src_list = src_list + rest

print(len(src_list))

# with open('abc', 'w') as f:

# for s in src_list:

# f.write(s)

# f.write('\n')

headers = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "

"Chrome/58.0.3029.110 Safari/537.36",}

for i in range(len(src_list)):

url = src_list[i].strip()

res = requests.get(url,headers = headers)

with open('第'+str(i+1)+'张.jpg','wb') as ff:

ff.write(res.content)

  参考页面:

  网络爬虫用Python-04.另一种爬虫方法

  Python 的 Instagram 图片爬虫 (一)

  Python 的 Instagram 图片爬虫 (二)

  新手小白,逻辑混乱,欢迎大佬指正,请吐槽

  

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线