翼度科技»论坛 编程开发 python 查看内容

使用Python爬取公众号的合集内容

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
使用Python爬取公众号的合集

前言

。。。最近老是更新关于博客的文章,很久没更新其他的了,然后写一下如何爬取微信公众号里面的图片吧!
先看看微信公众号的样子吧:

我爬取的是公众号的合集内容
讲解

首先用手机打开某个图片公众号的文章,然后复制链接用电脑打开,它的url为:
以下所展示的链接都是被我修改了的
https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzDg3MjY3g==&album_id=2646021169516584499&count=10&begin_msgid=2247483683&begin_itemidx=1&is_reverse=1&uin=&key=&pass_ticket=&wxtoken=&devicetype=&clientversion=&__biz=Mzg2MDg3MjY3Mg%3D%3D&appmsg_token=&x5=0&f=json
每个参数的作用

  • action: 操作类型,值为getalbum。
  • __biz: 公众号的唯一标识,值为MzDg3MjY3g==。
  • album_id: 相册的唯一标识,值为2646021169516584499。
  • count: 需要获取的相册数量,值为10。
  • begin_msgid: 开始的消息ID,值为2247483683。
  • begin_itemidx: 开始的项目索引,值为1。
  • is_reverse: 是否倒序,值为1。
  • uin: 用户uin,值为空。
  • key: 密钥,值为空。
  • pass_ticket: 通行证,值为空。
  • wxtoken: 微信令牌,值为空。
  • devicetype: 设备类型,值为空。
  • clientversion: 客户端版本,值为空。
  • appmsg_token: 文章令牌,值为空。
  • x5: x5参数,值为0。
  • f: 返回的数据格式,值为json。
爬取思路

可以看到文章开头的图片,公告号的每篇文章都是能跳转的,我们爬取图片肯定也是爬取跳转之后页面的图片,那么第一件事就是先获取所有文章的url。然后我的思路是将url爬取后保存到csv文件中,然后再从csv中读取url进一步解析图片的位置,然后下载图片。这就是整体思路。
首先文章列表能够显示再网页上,那它必定是请求后端了的,那么请求后端我们就能拿到API接口,如图:

可以看到也是成功获取到了接口,然后里面返回的列表就是网页中展示的文章列表了,这就非常好办了。我们只需要请求这个接口就能获取到所有文章的url了,然后微信公众号合集内容的规则就是,获取最后一条数据的消息ID是下一条数据开始的消息ID,所以当我们爬取到一个列表,假如这个列表有10条数据,那么第10条数据的msgid就是下一次请求的begin_msgid,这样就能获取11-20的数据,依次内推就能获取所有文章了,之前试过想一次性获取全部文章,好像不太行,所以用一个循环然后去修改begin_msgid参数发送请求就行了。
开爬

爬取文章url

需要用到的库
  1. import requests
  2. import json
  3. import csv
  4. import time
复制代码
参数上面已经讲过了就不讲了。
请求头的Referer和Cookie,用浏览器的开发工具(F12)找到文章请求,然后就能获取到。
  1. # 设置请求参数
  2. url = 'https://mp.weixin.qq.com/mp/appmsgalbum'
  3. # 设置请求参数
  4. params = {
  5.     'action': 'getalbum',
  6.     '__biz': 'MzDg3MjY3g==',
  7.     'album_id': '2646021169516584499',
  8.     'count': 10,
  9.     'is_reverse': 1, # 为倒叙也就是从第一篇文章开始
  10.     'uin': '',
  11.     'key': '',
  12.     'pass_ticket': '',
  13.     'wxtoken': '',
  14.     'devicetype': '',
  15.     'clientversion': '',
  16.     '__biz': 'MzDg3MjY3g==',
  17.     'appmsg_token': '',
  18.     'x5': 0,
  19.     'f': 'json'
  20. }
  21. # 设置请求头
  22. headers = {
  23.     'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
  24.     'Referer': '',
  25.     'Host': 'mp.weixin.qq.com',
  26.     'Accept-Encoding': 'gzip, deflate',
  27.     'Cookie': ''
  28. }
复制代码
分段展示代码
  1. # 设置请求频率限制
  2. MAX_REQUESTS_PER_MINUTE = 10
  3. REQUEST_INTERVAL = 60 / MAX_REQUESTS_PER_MINUTE
  4. # 发送请求,获取第一页相册内容
  5. response = requests.get(url, params=params, headers=headers)
  6. if response.status_code == 200:
  7.     data = json.loads(response.text)
  8.     album = data['getalbum_resp']['article_list']
  9.     last_msgid = album[-1]['msgid']  # 获取最后一张图片的消息ID 用作下次请求的begin_msgid
  10. else:
  11.     print('获取相册内容失败:', response.status_code)
复制代码
  1. # 循环发送请求,获取所有相册内容
  2. result = []
  3. while True:
  4.     params['begin_msgid'] = last_msgid
  5.     params['begin_itemidx'] = 1
  6.     print(url)
  7.     response = requests.get(url, params=params, headers=headers)
  8.     if response.status_code == 200:
  9.         data = json.loads(response.text)
  10.         album = data['getalbum_resp']['article_list']
  11.         if len(album) == 0:
  12.             break  # 如果相册为空,则退出循环
  13.         for photo in album:
  14.             # 获取url和title
  15.             url2 = photo['url']
  16.             title = photo['title']
  17.             result.append({'url': url2, 'title': title})
  18.             # 保存到csv文件中
  19.             with open('blogimg3.csv', 'a', newline='', encoding='utf-8') as f:
  20.                 writer = csv.DictWriter(f, fieldnames=['url', 'title'])
  21.                 writer.writerow({'url': url2, 'title': title})
  22.             # 控制请求频率
  23.             time.sleep(REQUEST_INTERVAL)
  24.         last_msgid = album[-1]['msgid']  # 获取最后一张图片的消息ID,用于下一次请求
  25.     else:
  26.         print('获取相册内容失败:', response.status_code)
  27.         break
复制代码
ok 然后坐等爬取完成,我这里是做了请求限制了的,如果想爬快一点把限制删掉就行了。
文章爬取结果



也是爬取完成了,但是爬完之后会报KeyError: 'article_list'的错误,这个无关紧要,因为已经请求到最后数据之后的请求了,导致获取不到这个article_list的json数据了。

然后看到上面的图片是254个内容,但是爬取的链接只有244条,数据缺失了几条,但是程序也没出现问题,所以就不管了,也就几条数据,不影响,毕竟找出问题得花大量的时间。
爬取图片

上面只是爬取了文章的url,现在要进入文章爬取图片了。
首先,需要用到的库
  1. import csv
  2. import requests
  3. from lxml import etree
  4. import os
  5. from urllib.parse import urlparse
  6. import time
复制代码
然后爬取图片的思路就是解析我们之前爬取的文章url,通过遍历文章url,去使用xpath去匹配文章里面的图片就行了,第一次爬取出现了点小问题,后面会讲。
关于Xpath获取
偷懒方式如下:

匹配图片url函数 download_images
  1. def download_images(url):
  2.     # 设置请求头
  3.     headers = {
  4.         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
  5.         'Referer': '',
  6.         'Host': 'mp.weixin.qq.com',
  7.         'Accept-Encoding': 'gzip, deflate',
  8.         'Cookie': ''
  9.     }
  10.     # 发送请求
  11.     response = requests.get(url, headers=headers)
  12.     # 解析HTML
  13.     html = etree.HTML(response.text)
  14.     # 获取图片
  15.     img_elements = html.xpath('//*[@id="js_content"]/section/section[4]/p/img/@data-src')
  16.     if len(img_elements) == 0:
  17.         img_elements = html.xpath('//*[@id="js_content"]/section/section[4]/p/span/img/@data-src')
  18.     print(img_elements)
  19.     # 下载图片
  20.     for url in img_elements:
  21.         print(f"下载图片:{url}")
  22.         download_image(url, 'blogimg4_1')
复制代码
**下载图片函数 **download_image
  1. # 下载
  2. def download_image(url, img_dir):
  3.      # 解析url
  4.      parsed_url = urlparse(url).path
  5.      wx_fmt = parsed_url.split('/')[1].split('_')[1]
  6.      # 获取文件名
  7.      filename = url.split('/')[-2] + '.' + wx_fmt
  8.      # 发送请求
  9.      response = requests.get(url)
  10.      # 保存图片
  11.      with open(os.path.join(img_dir, filename), 'wb') as f:
  12.          f.write(response.content)
复制代码
main方法
  1. if __name__ == '__main__':
  2.     with open('blogimg3_1.csv',newline='',encoding='utf-8') as f:
  3.         # 读取csv文件内容
  4.         reader = csv.reader(f)
  5.         # 遍历每一行
  6.         for row in reader:
  7.             # 提取第一列的url
  8.             url = row[0]
  9.             # 发送请求
  10.             try:
  11.                 download_images(url)
  12.             except Exception as e:
  13.                 print(f'Error: {e}')
  14.                 continue
  15.             time.sleep(2)
复制代码
图片爬取结果


可以看到有个别图片没有正常显示,那是因为这个公众号最新的文章图片url和之前不一样,我也是爬完才发现,虽然才几张图片,但是得优化一下
第一次爬取,爬到了1333张图片

优化下载图片代码

download_image函数:
  1. # 解析url
  2. parsed_url = urlparse(url)
  3. path_parts = parsed_url.path.split('/')
  4. # 判断链接特征并提取参数值
  5. if 'wx_fmt' in parsed_url.query:
  6.     wx_fmt = parsed_url.query.split('=')[1]
  7.     # 获取文件名
  8.     filename = path_parts[-2] + '.' + wx_fmt
  9. elif 'mmbiz_jpg' in path_parts:
  10.     filename = os.path.splitext(path_parts[2])[0] + '.jpg'
  11. elif 'mmbiz_png' in path_parts:
  12.     filename = os.path.splitext(path_parts[2])[0] + '.png'
  13. # 发送请求
  14. response = requests.get(url)
  15. # 保存图片
  16. with open(os.path.join(img_dir, filename), 'wb') as f:
  17.     f.write(response.content)
复制代码
优化之后也是没有出现图片无法显示的情况,然后爬取了1368张图片。

声明

文章出现的代码只用于学习,不会影响公众号正常运行,如有侵权,联系站长删除。
爬取下来的图片将不会保存,望知~
QQ邮箱:1767992919@qq.com
结尾

公众号是没有反爬机制的,所以爬取下来很容易,不过公众号放的图片都不够高清,但是也还是能看。如果也想学习学习如何爬取的,可以关注公众号私信我,找我要链接。如果有更好的图片网站,也可以私信我~


来源:https://www.cnblogs.com/ZYPLJ/p/17609348.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具