实战解决Python requests爬虫①返回全是JS②403错误的问题

实战解决Python requests爬虫①返回全是JS②403错误的问题,第1张

实战解决Python requests爬虫①返回全是JS②403错误的问题 背景

因工作需要,要统计一些使用400客服电话的企业名单,百度的号码验证平台提供了一个查询的能力,对于已经收录的400电话,可以查询到对应的企业名称,但是直接request会遇到 ① url形式爬取到全是JS代码;② 使用post方法返回403 的两个问题。

解决过程

1、解决爬取到的全是JS代码的问题

问题:直接从url出手取到的全是JS代码

 从截图可以看出,每次查询,顶部url中的search参数会切换为对应的搜索关键词,如 在输入框中输入“4008208820”,那么会url会变成:号码认证平台.

因此第一反应是,直接用get方法,每次切换电话号码时,修改对应的url参数。

# 切换电话号码时,修改对应的url参数
import requests as re

# 省略headers的配置环节

for each_number in range(起始号码,结束号码):
    response = re.get(url + str(each_number))
    print(response.text)

结果意料之中,全是JS代码,意味着这条路走不通。

不过看到JS代码,我们应该想到,下方查询的结果肯定是从某个接口请求到的,我们如果能找到对应的api接口,并且构造以假乱真的请求,也许能从接口中拿到数据。

通过分析执行查询时检查模式下network变化找到数据请求的接口api

说干咱就干。

在浏览器中F12进入检查模式,切换到network tab,勾选上“Fetch/XHR”tab。

随便输入一个电话号码,点击搜索。可以看到 一瞬间出现了2个网络请求的过程。

通过分析两个请求的内容,我们可以发现:

  • abdr这个请求,主要是向 https://miao.baidu.com/abdr 这个接口请求,request的参数为一个字符串,返回的数据包含 data、sign、key_id

  • search这个请求,向 https://haoma.baidu.com/api/v1/search 这个接口请求,参数是一个由data、sign、page、key_id、size和serach参数构成的字典。其中data、sign和key_id参数和刚刚abdr返回的数据是一样的!而通过手动构造几个新的搜索可以发现,page和size两个个参数在不同的查询中是不变的!而search参数正是我们输入的电话号码!而这个接口返回的数据中,刚好包含了对应的企业名称。Perfect。

至此,我们可以梳理整个链路了:

  1. 请求abdr接口,拿回来 data、sign、key_id参数;
  2. 将data、sign、key_id三个参数和不变的size、page,以及我们输入的搜索词(search参数) 构造成request的data,请求search接口;
  3. 解析search接口的返回值,即可拿到电话对应的企业名称。

编码实现:

for each_number in range(起始号码,结束号码):
    # 首先 请求abdr接口
    # 此处省略构造 headers 和 data的步骤
     abdr_response = re.post(url = "https://miao.baidu.com/abdr",
            headers = abdr_headers,
            data = abdr_data)
    
    # 然后请求search接口
    # 此处省略构造 headers的步骤
    search_data = {
            "data": abdr_response.data,
            "sign":abdr_response.sign,
            "key_id":abdr_response​.key_id,
            "page":1,
            "size":10, 
            "search":str(each_number)    
    }

    search_response = re.post(url = "https://haoma.baidu.com/api/v1/search",
            headers = search_headers,
            data = search_data)

然而,解析此处的search_reponse却是403。

解决通过接口POST请求,返回403错误的问题

当看到接口返回403,也就是服务器禁止访问的时候,第一时间感觉应该是cookie的问题,cookie设置错误是最有可能导致服务器禁止访问的。

因为我这里是直接将手动搜索时abdr的cookie配置到本次abdr的headers中,将手动搜索时search的cookie配置到本次search的headers中,一些情况下这个使用是没问题的,这里可能是存在一些动态的调整导致前一次的cookie中的某些参数在最新的一次请求中没法使用了。

为了排查cookie的问题,我们再手动搜索一次,对比两次search请求的cookie,我们可以发现,cookie中的其他参数一模一样,但是 ab_sr这个参数的值不一样了!

问题可能就出在这里,但是这个新的参数从哪儿来的呢?联想到data、key_id、sign这些参数来自于adbr请求,我们再回过头去研究一下adbr请求。

可以看到,adbr请求其实返回了一个cookie,而这个cookie中的ab_sr参数正是新的search参数中的ab_sr参数。不过这个返回的cookie并不在显式的返回结果中,而是要用response.cookie才能取到,所以被忽略了。

到这里差不多已经解决问题啦,我们根据abdr的返回的cookie中的ab_sr参数来更新新的search请求的cookie中的ab_sr参数,即可实现请求。

for each_number in range(起始号码,结束号码):
    # 首先 请求abdr接口
    # 此处省略构造 headers 和 data的步骤
     abdr_response = re.post(url = "https://miao.baidu.com/abdr",
            headers = abdr_headers,
            data = abdr_data)
    
    # 然后请求search接口
    # 此处省略构造 headers的步骤
    search_data = {
            "data": abdr_response.data,
            "sign":abdr_response.sign,
            "key_id":abdr_response.key_id,
            "page":1,
            "size":10,
            "search":str(each_number)    
    }


    # 根据abdr接口返回的cookie更新search_headers,主要是ab_sr参数
    
    search_response = re.post(url = "https://haoma.baidu.com/api/v1/search",
            headers = search_headers,
            data = search_data)

这次返回了正常的数据,大功告成!

总结
  • 在构建爬虫时,充分利用检查模式,分析接口调用情况是很重要的意识。

  • 遇到403错误时,重点分析cookie的问题(用户凭证,比如百度的BAIDUID也是通过cookie传递给接口的)

  • 要对比同一接口在不同调用下的参数、cookie、response的的细微差异,往往能找到有价值的线索

  • 一次查询、传输涉及到多个接口时,要梳理接口之间的数据传输关系,一个接口如果没有价值,肯定不会被调用嘛,所以存在的几个接口肯定都是有用的。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5522054.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存