最近看教程爬取搜狗微信文章,前边工作做好爬取ok,到了抓取每个文章的url时候出现了问题
这一串并不是文章真正的url,直接点的会弹出输入验证码,ok,去百度,吸取各个大佬的经验,得知了这只是一个未处理的url,处理过后才能得到真正的url。
具体过程(吸取前人经验总结的,百度真是个好东西):
首先这个url不是真正的url,在网页中点击标题后,会触发一个事件,这个事件会为我们在网页源代码中看到的url加上两个参数,已经有人把这个事件用python代码写出来了,也可以保存下来用execjs执行js代码获得加工后的url。加工后的url也不是真正的url,而是请求加工后的url后,返回一段js代码,这段代码会暴露出真正的url。具体分析过程可以见下边别人的博客,这里是对他们的补充(因为爬虫不断更新,或者各位大佬没说清楚的细节)。
这是他翻译的代码
r是从href属性下拿到的
def url_decode(r):
url = 'https://weixin.sogou.com' + r
b = random.randint(0, 99)
a = url.index('url=')
a = url[a + 30 + b:a + 31 + b:]
url += '&k=' + str(b) + '&h=' + a
return url
别人的博客
看完后请回到这里,这里会有一些重要的补充(在最后会说明到底需要什么样的headers)。
ok
捋一下:
拿到原始url就是href里的东西,然后经过代码初步加工(加两个参数),然后请求这个url,获得返回的js代码,执行js代码获得真正的url
要注意的是访问过程中需要headers和cookie,headers要包含一项重要的参数就是
'Referer': 'https://weixin.sogou.com/weixin?query=%E9%A3%8E%E6%99%AF&type=2&page=17&ie=utf8'
这代表了这篇文章是从那一页点出去的,后边的参数page=17代表这是从17页出去的,但是你把这个17改成其他的也会出正确的结果。
这一点上篇博客的作者未说明白,就很头痛
完整代码:
import requests
import random
import execjs
headers ={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6788.400 QQBrowser/10.3.2843.400',
'Referer': 'https://weixin.sogou.com/weixin?query=%E9%A3%8E%E6%99%AF&type=2&page=78&ie=utf8',
'Cookie':'请写自己的cookie'
}
#这个r是从href属性中随便找的一个
r = '/link?url=dn9a_-gY295K0Rci_xozVXfdMkSQTLW6cwJThYulHEtVjXrGTiVgS-YkygAfURZixdHSWWTpjKGkObPViAwEPVqXa8Fplpd9W1RjMz0jVEOYLI-rHUPgtBk2_TyeoA3GDJspUagW-Yy9H6-7QCE2hSaBhOGtNMj4F0FcxDoTjZybKWio3tq6IMm2GquGlhKJqAgaYZNJG8637wb_OeiFDqWh7iDLQRH83eTM7rFoCnQIl6fai6Q9VK8x6EAqg2mK506YFvY2wmPs46dn8Efgxg..&type=2&query=%E9%A3%8E%E6%99%AF'
def url_decode(r):
url = 'https://weixin.sogou.com' + r
b = random.randint(0, 99)
a = url.index('url=')
a = url[a + 30 + b:a + 31 + b:]
url += '&k=' + str(b) + '&h=' + a
return url
url = url_decode(r)
resp = requests.get(url,headers=headers)
print(resp.content.decode('utf8'))
结果:
用execjs处理一下就可以了
js_code = resp.content.decode('utf8')
comment = re.compile('<script>(.*?)</script>',re.DOTALL)
js_code = 'f = function(){%s}'%(comment.findall(js_code)[0].replace('window.location.replace(url)','return url;'))
print(execjs.compile(js_code).call('f'))
其中js_code就是网页返回值
处理完后打印出的就是正确的url