手记

微信公众号爬虫 - 公众号接口

    使用公众号自带的接口去抓取想要的信息,首先要在自己的公众号中对文章或者公众号进行查找,在数据包中解析出想要的信息,过程中最重要的几个难点:

  • cookies:标识别登录信息
  • token:个人标识
  • fakeid:标识公众号

1. 调用接口查找文章

进入主页 -> 素材管理 -> 新建图文 -> 超链接 -> 查找文章

I. 素材管理

II. 新建图文

III. 超链接

IV. 查找文章

2. 抓取所有相关公众号信息

    我们输入关键字并点击搜索后,右侧会出现相应的数据包,这里比较好找,选中xhr后只会出现唯一的数据包

I. 查看访问参数

    选中它选择headers栏滑到最下方可以看到一系列的请求参数,比较重要的参数无非tokenquery(搜索关键字)、begin(开始的数值)、count(每页显示的数值),在headers中还能够看到数据的真实url,之后会向他发起请求

II. 查看数据包内容

    在这里可以看到数据包内返回的所有内容,一般都是json格式,也可以查看一下是否与页面上看的的内容相对应,这里在返回数据的list列表中可以看到每个公众号的信息,包括fakeid(之后访问公众号文章会用到),公众号名称、公众号号码和总搜索量

III. 流程分析

    我们通过模拟登陆获取到cookie后,访问主页获取到url上的token标识,通过向抓取到的数据包上面的真实url发送请求以及数据来获取相应信息,在返回的信息中,通过解析total判断总数量,改变begin的数值来执行翻页,最后将信息写入文件

class Public(metaclass=SingletonType):
    def __init__(self, search_key, token, cookie):
        self.search_key = search_key
        self.url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?'
        self.headers = {
            'cookie': cookie,
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/74.0.3729.169 Safari/537.36'
        }
        self.data = {
            'action': 'search_biz',
            'token': token,
            'lang': 'zh_CN',
            'f': 'json',
            'ajax': '1',
            'random': '0.012103784566473319',
            'query': self.search_key,
            'count': '5'
        }

    def get_total(self):
        self.data['begin'] = 0
        content = requests.get(self.url, headers=self.headers, params=self.data).json()
        total = content['total']
        if total % 5:
            return int(total / 5) + 1
        else:
            return int(total / 5)

    def parse_public(self, num):
        self.data['begin'] = num
        content = requests.get(self.url, headers=self.headers, params=self.data).json()
        return content

    def get_data(self):
        for num in range(0, self.get_total() + 1, 5):
            for data in self.parse_public(num)['list']:
                yield {
                    "name": data['nickname'],
                    "id": data['fakeid'],
                    'number': data['alias']
                }
            time.sleep(random.randint(1, 3))
            
def write_data(result, filename):
    for data in result:
        print(data)
        with open(filename, 'a', encoding='utf-8') as f:
            f.write(json.dumps(data, ensure_ascii=False) + '\n')

3. 抓取公众号下的文章

    在上一步的操作后选定相应的公众号并执行抓包,可以看到新的数据包,包含其下的所有文章列表

I 抓包

II. 查看请求参数

    很明显,这里就用到了之前我们所获取到的fakeid信息,其他的都和之前类似,query同样是搜索关键字,指定query后会返回相关搜索项,未指定则默认为空,返回默认的

III. 查看数据内容

IV. 流程分析

    通过模拟登陆后获取到cookietokenfakeid可以自行获取,参考上一部分获取公众号信息的内容,然后向数据包的真实url发送请求,对返回的数据做解析,通过app_msg_cnt获取总量,更改begin值执行翻页,获取文章标题、创建时间(时间戳需要转为时间格式)、文章简述、文章链接等信息,最后执行写入文件操作

class Articls(metaclass=SingletonType):
    def __init__(self, token, fakeid, cookie, search_key=""):
        self.search_key = search_key
        self.url = 'https://mp.weixin.qq.com/cgi-bin/appmsg?'
        self.headers = {
            'cookie': cookie,
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/74.0.3729.169 Safari/537.36',
            'host': 'mp.weixin.qq.com',
            'Connection': 'keep-alive',
            'Accept': 'application/json, text/javascript, */*; q=0.01'
        }
        self.data = {
            "token": token,
            "lang": "zh_CN",
            "f": "json",
            "ajax": "1",
            "action": "list_ex",
            "count": "5",
            "query": self.search_key,
            "fakeid": fakeid,
            "type": "9",
        }

    def parse_articles(self, num):
        self.data['begin'] = num
        content = requests.get(self.url, headers=self.headers, params=self.data).json()
        return content

    def get_total(self):
        self.data['begin'] = 0
        content = requests.get(self.url, headers=self.headers, params=self.data).json()
        total = content['app_msg_cnt']
        if total % 5:
            return int(total / 5) + 1
        else:
            return int(total / 5)

    @staticmethod
    def convert_2_time(stamp):
        return time.strftime("%Y-%m-%d", time.localtime(stamp))


    def get_data(self):
        if self.get_total():
            for num in range(0, self.get_total() + 1, 5):
                for data in self.parse_articles(num)['app_msg_list']:
                    yield {
                        "title": data['title'],
                        "create_time": self.convert_2_time(data['create_time']),
                        # 摘要
                        'digest': data['digest'],
                        'link': data['link']
                    }
                time.sleep(random.randint(1, 3))
        else:
            print("No search item")
            exit()
            
def write_data(result, filename):
    for data in result:
        print(data)
        with open(filename, 'a', encoding='utf-8') as f:
            f.write(json.dumps(data, ensure_ascii=False) + '\n')

4. 模拟登陆

    具体操作流程我们都已经知道了,现在就缺两个东西,cookietoken,我们仔细观察首页,token简直随处可见,html代码,url中随处可见,我们就简单的从url中获取即可,cookie我们通过selenium登录后获取

I. cookies获取

    通过selenium调用chrome浏览器传入用户名以及密码,点击登录后睡眠一定时间给用户扫码,当登录成功后再次访问主页并获取cookie写入文件(是否写入文件看个人喜好,返回也可以)

def login(username, passwd):
    cookies = {}
    driver = webdriver.Chrome()  # 谷歌驱动
    driver.get('https://mp.weixin.qq.com/')

    # 用户名
    driver.find_element_by_xpath('//input[@name="account"]').clear()
    driver.find_element_by_xpath('//input[@name="account"]').send_keys(username)
    driver.find_element_by_xpath('//input[@name="password"]').clear()
    driver.find_element_by_xpath('//input[@name="password"]').send_keys(passwd)
    # 登录
    driver.find_element_by_xpath('//a[@class="btn_login"]').click()
    time.sleep(20)
    # 获取cookie
    driver.get('https://mp.weixin.qq.com/')
    time.sleep(5)
    cookie_items = driver.get_cookies()
    for cookie_item in cookie_items:
        cookies[cookie_item['name']] = cookie_item['value']
    with open('cookie.txt', 'w') as f:
        f.write(json.dumps(cookies))
    driver.close()
  • 这里对cookie有一个处理,因为selenium获取到的cookie是如下格式的,需要在其中提取出namevalue,如果是用requests访问,还需要将字典转为字符串,并且以'; '分割,别忘记后面的空格

II. token获取

    读取文件解析cookie对主页发起请求,获取到token后和cookie一起返回

def get_cookie_token():
    url = 'https://mp.weixin.qq.com'
    header = {
         'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/74.0.3729.169 Safari/537.36',
        'host': 'mp.weixin.qq.com',
    }

    with open('cookie.txt', 'r', encoding='utf-8') as f:
        cookie = f.read()
    cookies = json.loads(cookie)
    response = requests.get(url=url, cookies=cookies)
    token = re.findall(r'token=(\d+)', str(response.url))[0]
    result = []
    for k, v in cookies.items():
        result.append(k + '=' + v)
    return "; ".join(result), token
1人推荐
随时随地看视频
慕课网APP

热门评论

?

查看全部评论