我想抓取知乎上用户的关注信息,如查看A关注了哪些人,通过www.zhihu.com/people/XXX/followees这个页面来获得followee的列表,但是在抓取中遇到了403问题。
1.爬虫仅仅是为了搜集用户关注信息,用于学术研究,绝非商业或其他目的
2.使用PHP,利用
curl
构造请求,使用simple_html_dom来解析文档
3.在用户的关注者(Followees)列表,应该是使用Ajax进行动态加载更多的followees,于是我想直接爬接口的数据,通过firebug查看到,加载更多的关注者似乎是通过
http://www.
zhihu.com/node/ProfileF
olloweesListV2
进行的,并且post的数据有_xsrf,method,parmas,于是我在模拟保持登录的情况下,对这个链接提交请求,并带有post过去的所需要的参数,但是返回的是403。
4.但是我同样模拟登录的情况下,可以解析到如赞同数、感谢数这些不需要Ajax的数据
5.我使用curl_setopt($ch, CURLOPT_HTTPHEADER, $header );来设置请求头,使其与我在浏览器中提交的请求的请求头一致,但是这样任然导致403错误
6.我尝试打印出curl的请求头与浏览器发出的请求头进行比较,但是没有找到正确的方式(百度出的curl_getinfo()似乎打印出的相应报文)
7.有许多人曾因为没有设置User-Agent或者X-Requested-With遭遇403,但是我在5中描述设置请求头时都设置了
8.如果叙述不详需要贴出代码,我可以贴出代码
9.这个爬虫是我毕设的一部分,需要获取数据来进行接下来的工作,如1所说,爬取数据纯粹是为了学术研究
curl模块采集任意网页php类
curl模块采集任意网页php类
下载
回复内容:
如果带有防火墙功能的服务器,连续抓取可能被干掉,除非你有很多代理服务器。或者最简单用adsl不断重新拨号更换ip
你先找个浏览器,研究一下request的HTTP Header再来抓
这两天刚好做了一个抓取用户的关注着和追随者的的爬虫在抓数据,使用的是Python。这里给你一段python的代码,你可以对着代码看一下你的代码问题。
403应该就是请求的时候一些数据发错了,下面的代码中涉及到一个打开的文本,文本中的内容是用户的id,文本里面的内容样式我截了图放在最后面。
无非就是那些, useragent,referer,token,cookie
觉得可能会是 2 个原因造成的:
没带 cookies
_xsrf 或 hash_id 错误
这个问题我来回答下吧,知乎在“_xsrf”这个字段搞了个小动作,并不是首页页面取到的那个_xsrf 的值,而是在登录成功后通过cookie返回的那个“_xsrf ”的值,所以你需要获取正确的这个值,不然一直会报403错误(我是在Post提问时发现的,相信你遇到的问题类似,直接上代码):
///
/// 知乎提问///
///
提问标题
///
详细内容
///
登录后获取的cookie
public void ZhiHuFaTie(string question_title,string question_detail,CookieContainer cookie)
{
question_title=“提问内容”;
question_detail=“问题详细描述”;
//遍历cookie,获取_xsrf 的值
var list = GetAllCookies(cookie);
foreach (var item in list)
{
if (item.Name == "_xsrf")
{
xsrf = item.Value;
break;
}
}
//发帖
var FaTiePostUrl = "
http://www.
zhihu.com/question/add
";
var dd = topicStr.ToCharArray();
var FaTiePostStr = "question_title=" + HttpUtility.UrlEncode(question_title) + "&question_detail=" + HttpUtility.UrlEncode(question_detail) + "&anon=0&topic_ids=" + topicId + "&new_topics=&_xsrf="+xsrf;
var FaTieResult = nhp.PostResultHtml(FaTiePostUrl, cookie, "http://www.zhihu.com/", FaTiePostStr);
}
///
/// 遍历CookieContainer///
///
///
public static List
GetAllCookies(CookieContainer cc){ListlstCookies = new List();Hashtable table = (Hashtable)cc.GetType().InvokeMember("m_domainTable",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField |System.Reflection.BindingFlags.Instance, null, cc, new object[] { });foreach (object pathList in table.Values){SortedList lstCookieCol = (SortedList)pathList.GetType().InvokeMember("m_list",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField| System.Reflection.BindingFlags.Instance, null, pathList, new object[] { });foreach (CookieCollection colCookies in lstCookieCol.Values)foreach (Cookie c in colCookies) lstCookies.Add(c);}return lstCookies;}
修改header的X-Forwarded-For字段伪装ip
真的是很巧,昨天晚上刚刚遇到了这个问题。原因可能有有很多,我只说自己遇到的,仅供参考,提供一种思路。我爬取的是新浪微博,使用了代理。出现403是因为访问时网站拒绝,我在浏览器上操作也是一样,随便看里面几个网页就会出现403,不过刷新几次就好了。在代码中实现就是多请求几次。
看了楼上的答案,瞬间被镇住了。大牛真多,不过我建议题主去问问李开复好了~哈哈
话说接口是怎么抓到的...为何我用firebug抓不到接口..chrome的network也抓不到接口话说直接请求followees也可以直接获取到,剩下的也就是正则了
#encoding=utf8
import urllib2
import json
import requests
from bs4 import BeautifulSoup
Default_Header = {'X-Requested-With': 'XMLHttpRequest',
'Referer': 'http://www.zhihu.com',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; '
'rv:39.0) Gecko/20100101 Firefox/39.0',
'Host': 'www.zhihu.com'}
_session = requests.session()
_session.headers.update(Default_Header)
resourceFile = open('/root/Desktop/UserId.text','r')
resourceLines = resourceFile.readlines()
resultFollowerFile = open('/root/Desktop/userIdFollowees.text','a+')
resultFolloweeFile = open('/root/Desktop/userIdFollowers.text','a+')
BASE_URL = 'https://www.zhihu.com/'
CAPTURE_URL = BASE_URL+'captcha.gif?r=1466595391805&type=login'
PHONE_LOGIN = BASE_URL + 'login/phone_num'
def login():
'''登录知乎'''
username = ''#用户名
password = ''#密码,注意我这里用的是手机号登录,用邮箱登录需要改一下下面登录地址
cap_content = urllib2.urlopen(CAPTURE_URL).read()
cap_file = open('/root/Desktop/cap.gif','wb')
cap_file.write(cap_content)
cap_file.close()
captcha = raw_input('capture:')
data = {"phone_num":username,"password":password,"captcha":captcha}
r = _session.post(PHONE_LOGIN, data)
print (r.json())['msg']
def readFollowerNumbers(followerId,followType):
'''读取每一位用户的关注者和追随者,根据type进行判断'''
print followerId
personUrl = 'https://www.zhihu.com/people/' + followerId.strip('\n')
xsrf =getXsrf()
hash_id = getHashId(personUrl)
headers = dict(Default_Header)
headers['Referer']= personUrl + '/follow'+followType
followerUrl = 'https://www.zhihu.com/node/ProfileFollow'+followType+'ListV2'
params = {"offset":0,"order_by":"created","hash_id":hash_id}
params_encode = json.dumps(params)
data = {"method":"next","params":params_encode,'_xsrf':xsrf}
signIndex = 20
offset = 0
while signIndex == 20:
params['offset'] = offset
data['params'] = json.dumps(params)
followerUrlJSON = _session.post(followerUrl,data=data,headers = headers)
signIndex = len((followerUrlJSON.json())['msg'])
offset = offset + signIndex
followerHtml = (followerUrlJSON.json())['msg']
for everHtml in followerHtml:
everHtmlSoup = BeautifulSoup(everHtml)
personId = everHtmlSoup.a['href']
resultFollowerFile.write(personId+'\n')
print personId
def getXsrf():
'''获取用户的xsrf这个是当前用户的'''
soup = BeautifulSoup(_session.get(BASE_URL).content)
_xsrf = soup.find('input',attrs={'name':'_xsrf'})['value']
return _xsrf
def getHashId(personUrl):
'''这个是需要抓取的用户的hashid,不是当前登录用户的hashid'''
soup = BeautifulSoup(_session.get(personUrl).content)
hashIdText = soup.find('script', attrs={'data-name': 'current_people'})
return json.loads(hashIdText.text)[3]
def main():
login()
followType = input('请配置抓取类别:0-抓取关注了谁 其它-被哪些人关注')
followType = 'ees' if followType == 0 else 'ers'
for followerId in resourceLines:
try:
readFollowerNumbers(followerId,followType)
resultFollowerFile.flush()
except:
pass
if __name__=='__main__':
main()
