Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ajax请求 #9

Closed
shilegehuan opened this issue Dec 30, 2019 · 25 comments
Closed

ajax请求 #9

shilegehuan opened this issue Dec 30, 2019 · 25 comments

Comments

@shilegehuan
Copy link

ajax请求命令最后的page=改成sinceid=了,还有办法抓么?

@LiuZhH1366
Copy link

有的,今天学习了学长的第六章 Ajax数据爬取。也发现了这个问题,但我想学长写书的目的教的是方法,利用书中所授方法我找到了如下方式抓取。

首先,我观察几次的ajax的url,并没有发现什么规律
Request URL:https://m.weibo.cn/api/container/getIndex?type=uid&value=2830678474&containerid=1076032830678474&since_id=4464249252756977
每次都不一样,而且毫无规律可循。就在想他们是怎么通过本次的请求得到下次的since_id的,肯定是哪传递了这个参数

仔细观察,发现since_id实际上是本次刷新出来的最开始的那条微博的id
再仔细观察几个xhr之间的关系,发现每次的xhr的preview里的.data.cardlistInfo里有一个since_id,而这个since_id正好是下一次url里的since_id,也就是下一次的第一条微博的id。而第一次的xhr的url里并没有since_id,因为他是第一个。(实际上仔细看书会发现新浪就是把page换成了since_id,位置都没变,其他参数也都没变)

得到了以上信息,我们就可以在原始代码上进行修改。
get_page()函数作如下修改:(省略部分保持不变)
def get_page(since_id):
params = {
'type': 'uid',
'value': '2830678474',
'containerid': '1076032830678474'
}
if since_id!=0:
params['since_id'] = since_id

main作如下修改:(省略部分保持不变)
if name == 'main':
since_id = 0
for page in range(1, max_page + 1):
json = get_page(since_id)
since_id = json.get('data').get('cardlistInfo').get('since_id')

运行结果无误!~

@Germey
Copy link
Member

Germey commented Feb 9, 2020

感谢!

@Germey Germey closed this as completed Feb 9, 2020
@A1bertY
Copy link

A1bertY commented Feb 19, 2020

2020年2月19日测试无效,目前微博更新了api,即使模拟了请求头和url也无法使用requests获取到内容,但是用浏览器却可以,不知为何,等待高手解答,下面是代码
import requests
headers={
'Host':'m.weibo.com',
'Referer':'https://m.weibo.cn/u/2830678474',
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.116 Safari/537.36',
'X-Requested-With':'XMLHttpRequest',
'upgrade-insecure-requests': '1',
'sec-fetch-site': 'same-origin',
'sec-fetch-mode': 'same-origin',
'sec-fetch-dest': 'empty',
'cache-control': 'max-age=0',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
}
r=requests.get('https://m.weibo.cn/api/container/getindex?type=uid&value=2830678474&containerid=1076032830678474',headers=headers)
print(r.text)

下面是运行结果
{
"ok": 0,
"code": 516,
"msg": "CONTROLLER_ERROR"
}

通过浏览器的开发者窗口观察到,请求头部还有一些带冒号的请求头,应该是和HTTP2有关

@LiuZhH1366
Copy link

经测试,你出现的问题在于,headers里的host写的是m.weibo.com,应该是.cn。
改完再试试看,2.19 18:09测试可行

@A1bertY
Copy link

A1bertY commented Feb 19, 2020

经测试,你出现的问题在于,headers里的host写的是m.weibo.com,应该是.cn。
改完再试试看,2.19 18:09测试可行

测试通过!错误定位十分精准!非常感谢!

@hannzhao
Copy link

hannzhao commented Feb 20, 2020

@LiuZhH1366 您好,非常感谢您的代码。但是我执行的时候遇到了一点小问题。
main函数中的json = get_page(since_id)返回的是tuple元组,元组中有两个元素,第一个是json的字典,第二个是变量 页数page。这时候变量json不能直接用.get()方法,我把下一句改成了
since_id = json[0].get('data').get('cardlistInfo').get('since_id') 也就是把json改为了json[0],这样就可以正常输出啦

@LiuZhH1366
Copy link

LiuZhH1366 commented Feb 20, 2020

@LiuZhH1366 您好,非常感谢您的代码。但是我执行的时候遇到了一点小问题。
main函数中的json = get_page(since_id)返回的是tuple元组,元组中有两个元素,第一个是json的字典,第二个是变量 页数page。这时候变量json不能直接用.get()方法,我把下一句改成了
since_id = json[0].get('data').get('cardlistInfo').get('since_id') 也就是把json改为了json[0],这样就可以正常输出啦

我用了好久也没复现出你说的小问题(返回tuple,我这边返回的都是json的字典),希望能借代码一看,我猜可能是get_page()函数返回值不太一样。
以下是我的这部分代码,供你参考,如还有问题,请借代码一看,我再仔细试试。

def get_page(since_id):
    params = {
        'type': 'uid',
        'value': '2830678474',
        'containerid': '1076032830678474'
    }
    if since_id!=0:
        params['since_id'] = since_id
    url = base_url + urlencode(params)
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.json()
    except requests.ConnectionError as e:
        print('Error', e.args)

if __name__ == '__main__':
    since_id = 0
    for page in range(1, max_page + 1):
        json = get_page(since_id)
        since_id = json.get('data').get('cardlistInfo').get('since_id')
        results = parse_page(json)
        for result in results:
            try:
                print(result)
            except:
                print('='*10+"此内容无法显示"+"="*10)

@literence
Copy link

since_id = json.get('data').get('cardlistinfo').get('since_id')
这行代码提示错误信息
AttributeError: 'tuple' object has no attribute 'get'
谁能解答一下

@LiuZhH1366
Copy link

since_id = json.get('data').get('cardlistinfo').get('since_id')
这行代码提示错误信息
AttributeError: 'tuple' object has no attribute 'get'
谁能解答一下

我还是想说一句,问的时候要把代码发全,就这么一句,复现都复现不了,怎么帮你呀、、
但是呢,我还是发现了问题,一个低级错误,cardlistInfo抄错了,大写I抄成了小写i
然后我也试了,但是咱们报的错还不太一样(AttributeError: 'NoneType' object has no attribute 'get'),所以希望能帮到你吧

@LiuZhH1366
Copy link

我终于知道为什么楼上两位会返回tuple了,是因为get_page函数的问题。也是因为我的疏忽,起到了极大的误导性。

问题是这样的,我是照着书写的,楼上两位是照着GitHub上的代码写的,而二者的代码是不一样的。在【stevenshuang committed on 18 May 2018】这次更新中,由于微博API的更新,对get_page()函数进行了修改,对get_page()的返回值,由response.json()改成了两个response.json(), page。这也是楼上两位出现返回值是tuple的根本原因。也是我在【LiuZhH1366 commented on 26 Jan】回复中不严谨的一个问题所在。

所以就有了【hannzhao commented 5 days ago】中的以下内容:

@LiuZhH1366 您好,非常感谢您的代码。但是我执行的时候遇到了一点小问题。
main函数中的json = get_page(since_id)返回的是tuple元组,元组中有两个元素,第一个是json的字典,第二个是变量 页数page。这时候变量json不能直接用.get()方法,我把下一句改成了
since_id = json[0].get('data').get('cardlistInfo').get('since_id') 也就是把json改为了json[0],这样就可以正常输出啦

两个元素,一个是json,一个是page,但是还能正确的跑

当然我还要肯定一点的是,本项目中的代码【https://github.com/Python3WebSpider/WeiboList/blob/master/weibo.py 】还能跑,而且能正确的跑,这是为什么?为什么page参数都没了还能用?
谜底揭晓,因为他只是把参数换了,可原来的json数据还在。就是说以下两个页面主要内容是一致的。(经过文本比对之后得到的结论)
https://m.weibo.cn/api/container/getIndex?type=uid&value=2830678474&containerid=1076032830678474&since_id=4471555595691396
https://m.weibo.cn/api/container/getIndex?type=uid&value=2830678474&containerid=1076032830678474&page=2

So,我的结论就是这些,希望能帮到更多的人~

@forever0830
Copy link

有的,今天学习了学长的第六章 Ajax数据爬取。也发现了这个问题,但我想学长写书的目的教的是方法,利用书中所授方法我找到了如下方式抓取。

首先,我观察几次的ajax的url,并没有发现什么规律
Request URL:https://m.weibo.cn/api/container/getIndex?type=uid&value=2830678474&containerid=1076032830678474&since_id=4464249252756977
每次都不一样,而且毫无规律可循。就在想他们是怎么通过本次的请求得到下次的since_id的,肯定是哪传递了这个参数

仔细观察,发现since_id实际上是本次刷新出来的最开始的那条微博的id
再仔细观察几个xhr之间的关系,发现每次的xhr的preview里的.data.cardlistInfo里有一个since_id,而这个since_id正好是下一次url里的since_id,也就是下一次的第一条微博的id。而第一次的xhr的url里并没有since_id,因为他是第一个。(实际上仔细看书会发现新浪就是把page换成了since_id,位置都没变,其他参数也都没变)

得到了以上信息,我们就可以在原始代码上进行修改。
get_page()函数作如下修改:(省略部分保持不变)
def get_page(since_id):
params = {
'type': 'uid',
'value': '2830678474',
'containerid': '1076032830678474'
}
if since_id!=0: params['since_id'] = since_id

main作如下修改:(省略部分保持不变)
if name == 'main':
since_id = 0
for page in range(1, max_page + 1):
json = get_page(since_id) since_id = json.get('data').get('cardlistInfo').get('since_id')

运行结果无误!~

有的,今天学习了学长的第六章 Ajax数据爬取。也发现了这个问题,但我想学长写书的目的教的是方法,利用书中所授方法我找到了如下方式抓取。

首先,我观察几次的ajax的url,并没有发现什么规律
Request URL:https://m.weibo.cn/api/container/getIndex?type=uid&value=2830678474&containerid=1076032830678474&since_id=4464249252756977
每次都不一样,而且毫无规律可循。就在想他们是怎么通过本次的请求得到下次的since_id的,肯定是哪传递了这个参数

仔细观察,发现since_id实际上是本次刷新出来的最开始的那条微博的id
再仔细观察几个xhr之间的关系,发现每次的xhr的preview里的.data.cardlistInfo里有一个since_id,而这个since_id正好是下一次url里的since_id,也就是下一次的第一条微博的id。而第一次的xhr的url里并没有since_id,因为他是第一个。(实际上仔细看书会发现新浪就是把page换成了since_id,位置都没变,其他参数也都没变)

得到了以上信息,我们就可以在原始代码上进行修改。
get_page()函数作如下修改:(省略部分保持不变)
def get_page(since_id):
params = {
'type': 'uid',
'value': '2830678474',
'containerid': '1076032830678474'
}
if since_id!=0: params['since_id'] = since_id

main作如下修改:(省略部分保持不变)
if name == 'main':
since_id = 0
for page in range(1, max_page + 1):
json = get_page(since_id) since_id = json.get('data').get('cardlistInfo').get('since_id')

今天看见连since_id都没了

@literence
Copy link

我终于知道为什么楼上两位会返回tuple了,是因为get_page函数的问题。也是因为我的疏忽,起到了极大的误导性。

问题是这样的,我是照着书写的,楼上两位是照着GitHub上的代码写的,而二者的代码是不一样的。在【stevenshuang committed on 18 May 2018】这次更新中,由于微博API的更新,对get_page()函数进行了修改,对get_page()的返回值,由response.json()改成了两个response.json(), page。这也是楼上两位出现返回值是tuple的根本原因。也是我在【LiuZhH1366 commented on 26 Jan】回复中不严谨的一个问题所在。

所以就有了【hannzhao commented 5 days ago】中的以下内容:

@LiuZhH1366 您好,非常感谢您的代码。但是我执行的时候遇到了一点小问题。
main函数中的json = get_page(since_id)返回的是tuple元组,元组中有两个元素,第一个是json的字典,第二个是变量 页数page。这时候变量json不能直接用.get()方法,我把下一句改成了
since_id = json[0].get('data').get('cardlistInfo').get('since_id') 也就是把json改为了json[0],这样就可以正常输出啦

两个元素,一个是json,一个是page,但是还能正确的跑

当然我还要肯定一点的是,本项目中的代码【https://github.com/Python3WebSpider/WeiboList/blob/master/weibo.py 】还能跑,而且能正确的跑,这是为什么?为什么page参数都没了还能用?
谜底揭晓,因为他只是把参数换了,可原来的json数据还在。就是说以下两个页面主要内容是一致的。(经过文本比对之后得到的结论)
https://m.weibo.cn/api/container/getIndex?type=uid&value=2830678474&containerid=1076032830678474&since_id=4471555595691396
https://m.weibo.cn/api/container/getIndex?type=uid&value=2830678474&containerid=1076032830678474&page=2

So,我的结论就是这些,希望能帮到更多的人~

终于明白了,谢谢大佬

@LiuZhH1366
Copy link

@forever0830 今天看见连since_id都没了

我刚试了一下,since_id还在,你得往下翻他才会触发
搜狗截图20200227173854

@lziiid
Copy link

lziiid commented Apr 12, 2020

求助 现在微博的ajax请求和书上的好像完全不一样了 怎么办。。

@LiuZhH1366
Copy link

求助 现在微博的ajax请求和书上的好像完全不一样了 怎么办。。

[捂脸]我刚看了一下,好像还和上边的回复一样,应该是没变,建议你先仔细把书看看(书上大部分内容目前依旧有效),然后参考上边的回复以及开发者工具中你所看到的内容进行尝试,遇到实际问题再来求助。

@lziiid
Copy link

lziiid commented Apr 12, 2020

求助 现在微博的ajax请求和书上的好像完全不一样了 怎么办。。

[捂脸]我刚看了一下,好像还和上边的回复一样,应该是没变,建议你先仔细把书看看(书上大部分内容目前依旧有效),然后参考上边的回复以及开发者工具中你所看到的内容进行尝试,遇到实际问题再来求助。

微信图片_20200412164456
我看到的是这样的呀。。请求头里边的参数也和书上的不一样了

@Thousand-Sunnny
Copy link

求助 现在微博的ajax请求和书上的好像完全不一样了 怎么办。。

[捂脸]我刚看了一下,好像还和上边的回复一样,应该是没变,建议你先仔细把书看看(书上大部分内容目前依旧有效),然后参考上边的回复以及开发者工具中你所看到的内容进行尝试,遇到实际问题再来求助。

微信图片_20200412164456
我看到的是这样的呀。。请求头里边的参数也和书上的不一样了

我也是这样,找不到那个getindex了

@Thousand-Sunnny
Copy link

我知道为什么了,必须要去域名为.cn的那个微博网站https://m.weibo.cn/u/2830678474
直接百度搜索出来的微博网站不行,找不到getindex条目

@LiuZhH1366
Copy link

我知道为什么了,必须要去域名为.cn的那个微博网站https://m.weibo.cn/u/2830678474
直接百度搜索出来的微博网站不行,找不到getindex条目

对的,有两个点,一个是手机版一般会比电脑版的页面更好爬取,所以选取的是m.weibo.cn而不是weibo.com,另一个是要想找到ajax的请求首先得先触发它,这里也就是页面得往下滑。

@thhou
Copy link

thhou commented May 13, 2020

建议大家使用 @LiuZhH1366 更改之后的代码,即采用since_id而非page,当然parse_page函数也要做相应修改(把page形参去掉)。因为用page爬取不完整:
微博图
爬取图

@heliusjing
Copy link

原程序是可以正常跑的,page参数还是可以正常使用 的

@wongbng
Copy link

wongbng commented Oct 21, 2020

学习了,各位大神。现在链接中多了display=0&retcode=6102,发现没有这个display=0&retcode=6102,程序照样运行
https://m.weibo.cn/api/container/getIndex?display=0&retcode=6102&type=uid&value=2830678474&containerid=1076032830678474&since_id=4556771409006204

@huang-biao
Copy link

有的,今天学习了学长的第六章 Ajax数据爬取。也发现了这个问题,但我想学长写书的目的教的是方法,利用书中所授方法我找到了如下方式抓取。

首先,我观察几次的ajax的url,并没有发现什么规律
Request URL:https://m.weibo.cn/api/container/getIndex?type=uid&value=2830678474&containerid=1076032830678474&since_id=4464249252756977
每次都不一样,而且毫无规律可循。就在想他们是怎么通过本次的请求得到下次的since_id的,肯定是哪传递了这个参数

仔细观察,发现since_id实际上是本次刷新出来的最开始的那条微博的id
再仔细观察几个xhr之间的关系,发现每次的xhr的preview里的.data.cardlistInfo里有一个since_id,而这个since_id正好是下一次url里的since_id,也就是下一次的第一条微博的id。而第一次的xhr的url里并没有since_id,因为他是第一个。(实际上仔细看书会发现新浪就是把page换成了since_id,位置都没变,其他参数也都没变)

得到了以上信息,我们就可以在原始代码上进行修改。
get_page()函数作如下修改:(省略部分保持不变)
def get_page(since_id):
params = {
'type': 'uid',
'value': '2830678474',
'containerid': '1076032830678474'
}
if since_id!=0: params['since_id'] = since_id

main作如下修改:(省略部分保持不变)
if name == 'main':
since_id = 0
for page in range(1, max_page + 1):
json = get_page(since_id) since_id = json.get('data').get('cardlistInfo').get('since_id')

运行结果无误!~

你好,你可以直接把修改好的整个代码发出来吗,发一句缺斤少两的代码,想运行都失败。无奈

@longchengguxiao
Copy link

想问一下如何用beautifulsoup实现这个呢,bs4如何解析json格式呀

@MGMCN
Copy link

MGMCN commented Oct 30, 2021

为什么要用beautifulsoup解析json呢?直接用json库解析不就得了。而且beautifulsoup主要针对的是HTML/XML的解析。😂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests