第六章 使用ajax接口爬取数据

一、爬取网站流程
1、分析网站的数据来源

​ 分析网站结构,待爬取数据在哪。

2、查看页面数据是否是直接渲染的

​ url请求后响应后,页面数据就已经全部加载出来,为直接渲染,看能否通过requests模块获取到

​ (1)在开发者工具中,找到页面的url这条数据。通过这条请求的信息来进行程序的书写。
​ (2)在代码中通过requests模块封装请求头,查看response.text中是否有页面数据。

3、如果不是直接渲染

​ 滚动鼠标,页面数据会不断加载,还有如显示全文,这种情况考虑用selenium或者ajax方法(XHR)查看请求。

4、如果有数据,就考虑是否有分页,分页如何实现
5、实现分页之后就可以提取数据,保存数据了

爬取网站分析流程

二、selenium的三种等待方式
1.强制等待

​ time.sleep(3)—强制让该进程休眠3秒。

2、隐式等待

driver.implicitly_wait(20)
​ 含义:20,单位为秒,表示最大等待时长。当加载一个页面,看到页面刷新按钮不再转圈圈,即页面数据全部加载完成,才算等待结束。
​ 浏览器数据全部加载完成包含以下内容:
​ (1).页面的html从服务器返回。
​ (2).页面的所有静态资源,js,css,img,广告,全部从服务器获取,在加载到页面中。

​ 隐式等待的弊端:
​ 使用等待,主要目的就是等待我们想要的数据加载出来。用隐式等待会等到所有资源都加载完成,花了一部分时间,去等待我们不想要的资源,所以隐式等待并不常用。

3、显示等待

​ 可以设置一些条件,只要页面加载时满足这个条件,就等待完成,所以等待的终止是可以通过程序员自己来手动控制。

1、显示等待的使用

​ (1)第一步,导入三个模块

# 显示等待的三个重要的模块
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

(2)创建一个显示等待对象
第一个参数:表示等待作用哪那个driver。

​ 第二个参数:最大等待时长,如果20s还没等待数据出来,就报timeout超时异常。

driver = webdriver.PhantomJS()
wait = WebDriverWait(driver,20)

​ (3)发送请求后,等待。

​ wait.until()的返回值是一个webelement对,它对应的就是选择器查找出来的那个webelement对象。

​ presence_of_element_located括号中必须是元组类型,指定等待结束的条件。

​ 第一个参数:By.XPATH,表示定位的选择器的名称。还可以是By.ID、BY.CSS_SELECTOR等。

​ 第二个参数:表示定位器locator,即要等到什么数据出现时,等待才结束。

# 请求url
driver.get(url)
# 等待
wait.until(EC.presence_of_element_located((By.XPATH,'//div[@class="recruit-list"]')))
三、使用ajax方式爬取数据

​ 如果页面数据不是直接渲染的,而是滚动鼠标不断加载数据的方式显示数据,考虑是用ajax请求加载数据。在分析工具中选择XHR,看ajax请求情况,如果不断发送ajax,Response中有数据。则确定使用ajax方法爬取数据。
在这里插入图片描述

1、如何分析ajax接口

​ 一个ajax接口,能否请求成功,最重要的就是请求参数。
​ 请求参数的分析方法:
​ 1.有可能一些参数是通过js加密的。
​ 2.请求参数里面有些参数是通过之前的一个ajax中提前获取好的。

2、以爬取豆瓣电影的电影排行榜中的电影信息为例,介绍ajax方法。

# 导入模块
import requests,re,json
from lxml import etree

# 执行爬取,主要获得type值
def get_content(url,headers):
    response = requests.get(url,headers=headers) # 发送请求,爬取数据
    if response.status_code == 200:
        return etree.HTML(response.text)  # 返回element对象
    return response.status_code

# 解析json数据
def parse_json(html):
    json_data = json.loads(html) # 将json的字符串格式数据转为列表格式数据
    for item in json_data:
        print(item)

# 从ajax请求中获取数据
def parse_ajax(type_num):
	# ajax请求中的基础url
    base_url = 'https://movie.douban.com/j/chart/top_list?'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
    }
    '''
    在不知道有多少页的情况下,用while True,当获取的数据为空时,跳出循环,
    如何判定结束条件,访问ajax的Request URL如https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=800&limit=20
     输入很大的页码(start的值),看返回的内容是否为'[]'
    '''
    i=0
    while True:
    	# ajax请求中的参数
        params = {  
            'type': type_num,   # 电影类型
            'interval_id': '100:90',
            'action':'',
            'start': str(i),  # 页码
            'limit': '20',  # 每页显示数
        }
        # 发送请求,爬取数据,当返回为‘[]’,break
        json_str = requests.get(base_url,headers=headers,params=params).text
        if json_str == '[]':
            break
        i += 20
        parse_json(json_str)  # 执行解析json数据的函数

def main():
    base_url = 'https://movie.douban.com/chart'  # 有电影类型页的url
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
    }
    # 分析了ajax的请求参数后,发现params中的type是根据电影类型变化的,回到上一页获取type
    # 获取type值
    html = get_content(base_url,headers)  # ,调用函数,获得element对象
    a_hrefs = html.xpath('//div[@class="types"]/span/a/@href') # 使用xpath获取含有type的属性
    for a_href in a_hrefs:
        #print(a_href) #href="/typerank?type_name=剧情&type=11&interval_id=100:90&action="
        # 使用正则获取type的值
        type_p = re.compile(r'type=(.*?)&')
        type_num = type_p.search(a_href).group(1)
        # print(type_num)
        parse_ajax(type_num)  # 传入type值,调用函数,从ajax请求接口中获取数据

if __name__ == '__main__':
    main()
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值