python在爬取微信公众号的文章时,你可能踩过的坑我都帮你踩了(下)

您所在的位置:网站首页 公众号文章预览多久失效一次 python在爬取微信公众号的文章时,你可能踩过的坑我都帮你踩了(下)

python在爬取微信公众号的文章时,你可能踩过的坑我都帮你踩了(下)

2024-07-12 23:29| 来源: 网络整理| 查看: 265

接着上一篇没完成的爬虫工程,继续更新最终的代码片段 三、获取每篇文章的阅读量,点赞量四、使用UA代理、IP代理,设置每篇文章的爬取速度 最近一直在忙没时间更新文章的下一篇,正好这几天有时间,把代码重新调整了一下,更新了里面的细节,在调整代码中发现了许多问题,主要一个就是ip代理的质量不行,哪里不行呢,往下看就知道了。

三、获取每篇文章的阅读量,点赞量 想要获取文章的阅读量,在微信公众平台里面直接点击,是获取不了文章的阅读量的,测试如下:

在这里插入图片描述 然后我们可以去fiddler里面查看这篇文章的包,我们可以看出这个包就是 文章的内容,从body的大小可以判断出来,里面就是文章的内容。 在这里插入图片描述

但是我们无法从这条路由中获取到文章的阅读量,因为这条请求是一个get请求,想要获取文章的阅读点赞,首先请求得是post请求,其次需要携带三个重要的参数pass_ticket,appmsg_token,phoneCookie,想要获取这三个参数,我们就得把某个公众号里面的文章放到微信里面点击,然后再从fiddler里面查看抓包情况。 在这里插入图片描述 让后我们去fiddler看一下抓包情况:我们可以看到,同样有上有一个get请求,但下面多了一个post请求的内容,再看携带的参数有我们要的三个获取阅读量的重要参数,还有通过response的内容可以看出,已经能够获取文章的阅读量信息了。下面我们就可以拼接参数发送请求了。 在这里插入图片描述

#获取文章阅读量 def get_readNum(link,user_agent): pass_ticket ="N/Sd9In6UXfiRSmhdRi+kRX2ZUn9HC5+4aAeb6YksHOWNLyV3VK48YZQY6oWK0/U" appmsg_token = "1073_N8SQ6BkIGIQRZvII-hnp11Whcg8iqFcaN4Rd19rKluJDPVMDagdss_Rwbb-fI4WaoXLyxA244qF3iAp_" # phoneCookie有效时间在两个小时左右,需要手动更新 phoneCookie = "rewardsn=; wxtokenkey=777; wxuin=2890533338; devicetype=Windows10x64; version=62090529; lang=zh_CN; pass_ticket=N/Sd9In6UXfiRSmhdRi+kRX2ZUn9HC5+4aAeb6YksHOWNLyV3VK48YZQY6oWK0/U; wap_sid2=CNqTqOIKElxWcHFLdDFkanBJZjlZbzdXVmVrejNuVXdUb3hBSERDTTBDcHlSdVAxTTFIeEpwQmdrWnM1TWRFdWtuRUlSRDFnUzRHNkNQZFpVMXl1UEVYalgyX1ljakVFQUFBfjCT5bP5BTgNQAE=" mid = link.split("&")[1].split("=")[1] idx = link.split("&")[2].split("=")[1] sn = link.split("&")[3].split("=")[1] _biz = link.split("&")[0].split("_biz=")[1] url = "http://mp.weixin.qq.com/mp/getappmsgext" headers = { "Cookie": phoneCookie, "User-Agent":user_agent } data = { "is_only_read": "1", "is_temp_url": "0", "appmsg_type": "9", 'reward_uin_count': '0' } params = { "__biz": _biz, "mid": mid, "sn": sn, "idx": idx, "key": '777', "pass_ticket": pass_ticket, "appmsg_token": appmsg_token, "uin": '777', "wxtoken": "777" } success = False a=1 while not success: ip_num = ranDom_ip()[0] # 使用不同的ip进行阅读、点赞量的获取 try: print("获取阅读量使用ip:%s"%ip_num) content = requests.post(url, headers=headers, data=data, params=params, proxies=ip_num,timeout=6.6)#设置超时时间5秒 time.sleep(4) content = content.json() print(link)#文章链接 print(content)#文章内容 if 'appmsgstat' in content: readNum = content["appmsgstat"]["read_num"] like_num=content["appmsgstat"]["old_like_num"] #点赞量 zai_kan=content["appmsgstat"]["like_num"] #在看量 else: readNum = 0 like_num = 0 success=True return readNum, like_num except: print("获取阅读量ip出现问题,更换ip进入第二次循环获取!!!") a+=1 # if a%5==0: content = requests.post(url, headers=headers, data=data, params=params,timeout=5) time.sleep(3) content = content.json() print(link) #文章链接 print(content)#文章内容 if 'appmsgstat' in content: readNum = content["appmsgstat"]["read_num"] like_num = content["appmsgstat"]["old_like_num"] # 点赞量 zai_kan = content["appmsgstat"]["like_num"] # 在看量 else: print('文章阅读点赞获取失败!') readNum=0 like_num=0 # else: # continue return readNum, like_num

需要注意的是,这三个重要的参数,其中phoneCookie是有时效性的,需要手动更新这是最麻烦的就跟cookies一样。我们通过传进去的文章链接 就可以将链接中一些有用的参数抽取出来,用来后面拼接post请求,本想做个如果报错不断循环的,但我发现我的ip池ip的质量有点不行,所以代码略有点冗余(有待改进)。

四、使用UA代理、IP代理,设置每篇文章的爬取速度

通过上面的一顿操作,我们基本就可以把文章的链接,标题,链接,都爬取下来了,完成了初步的需求: 在这里插入图片描述 但正在我兴高采烈的爬取的时候,发现没多久就被反爬发现了,直接就将我公众号的请求给屏蔽了,在这里插入图片描述 这时候我想到了ip代理,识别我们是否是反爬,主要从ip和UA这两个, 所以后面我做了个ip代理池,从某些ip网站爬取ip下来,通过代码赛选出有用的ip组成一个ip池。贡献一个我爬ip的代码,有兴趣的小伙伴可以直接运行试试:

import requests from bs4 import BeautifulSoup import json import random import re ip_num=[] url="http://www.66ip.cn/1.html" headers={ "Host": "www.66ip.cn ", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36", "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", "Referer": "http://www.66ip.cn/index.html", "Cookie": "Hm_lvt_1761fabf3c988e7f04bec51acd4073f4=1595575058,1595816310; Hm_lpvt_1761fabf3c988e7f04bec51acd4073f4=1595832351", } content=requests.get(url,headers=headers) content.encoding="gbk" html=BeautifulSoup(content.text,"html.parser") # print(html) content=html.find_all("table",{"border":"2px"}) ip=re.findall('(\d{1,4}.\d{1,4}.\d{1,4}.\d{1,4})',str(content)) port=re.findall('(\d{1,5})',str(content)) for i in range(len(port)): ip_num.append(ip[i]+":"+port[i]) proxies = [{'http':ip_num[num]} for num in range(len(ip_num))] for i in range(0, len(ip_num)): proxie = random.choice(proxies) print("%s:当前使用的ip是:%s" % (i, proxie['http'])) try: response = requests.get("http://mp.weixin.qq.com/", proxies=proxie, timeout=3) print(response) if response.status_code == 200: # with open('ip.txt', "a", newline="")as f: # f.write(proxie['http'] + "\n") print("保存成功") except Exception as e: print("ip不可用")

我会将网站的ip筛选出来,保存到本地,再通过写一个函数,组建一个ip地址:

#代理池函数 def ranDom_ip(): with open('ip.txt',"r")as f: ip_num=f.read() ip_list=ip_num.split("\n") num=random.randint(0,len(ip_list)-1) proxies = [{'http': ip_list[num]}] return proxies

然后在函数循环的地方调用这个ip代理的函数,就可以不断的更新你使用的ip,下面给大家列一个流程图,我们就可以知道,可以在哪里使用ip代理的函数了 在这里插入图片描述 通过上面这三个地方加进我们使用的ip池,不断变化的ip是成功绕过反爬的一点,下面我们不断更换ip我感觉还是有点不保障,我觉得UA也需要不断的更新,所以我导入了一个ua 的代理池

from fake_useragent import UserAgent #导入UA代理池 user_agent=UserAgent()

但是需要注意的是,我们不能将headers里面的UA全部换了,我们只能一部分加入UA代理,因为公众号的请求是由两部分组成的,我们只能加到前半部分。 在这里插入图片描述 就像下面这个的请求头,我们的Ua代理只能替换前半部分,这样就可以做到Ua也是不断变化的,变化的位置就跟上面ip函数的位置一致,我们就可以做到ip,UA在每一次请求之后都是不同的。

headers={ "Host":"mp.weixin.qq.com", "User-Agent":user_agent.random +"(KHTML, like Gecko) Version/4.0 Chrome/78.0.3904.62 XWEB/2469 MMWEBSDK/200601 Mobile Safari/537.36 MMWEBID/3809 MicroMessenger/7.0.16.1680(0x27001033) Process/toolsmp WeChat/arm64 NetType/WIFI Language/zh_CN ABI/arm64" }

这两个参数之后我们基本可以控制不被反爬发现,但是还有重要的一个点,就是控制爬取的速度,因为ip和ua是不断变化了,但是你公众号的cookie是不能改变的,如果爬取的速度过快,它会识别到你某个公众号访问一个接口的频次过快,直接把你公众号搜文章的接口禁了,所以我们需要做个请求延迟,那我们在流程的哪里做比较好呢?可以在流程图标注的位置做延迟。 在这里插入图片描述 这样既能控制速度,又能让本机ip和ua不被发现,美滋滋,不足的是没有找到一个高质量的ip池,我用的都是免费的ip造成换ip过程中许多都是不能获取到阅读量的(来自穷人的感叹),如果有一个高匿的ip代理池,速度是很快的。完整代码这里就不粘贴出来的,有兴趣的小伙伴点赞留言我可以私发呀。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3