python爬虫——爬取静态微博页面,找到可能认识的人 - Go语言中文社区

python爬虫——爬取静态微博页面,找到可能认识的人


环境:

  • BeautifulSoup4 (4.6.0)
  • requests (2.19.1)

分析

    该博客是本人第一个爬虫项目,之前比较懒,没上传博客,最近再学爬虫,在此一并补上。

    我们知道,爬虫获取数据的思路是: 先根据初始(初始id)的网页,筛选需要的网页,并把需要的网页url(用户id)加入到队列中,然后每次队列中取出一个网页,按初始页面的方式爬取,如此循环,即可获取大量的数据。

    根据这个思路,我们猜想能否利用微博关注的人页面获取新用户,检查新检索用户的个人信息是否满足我们要找的地区,或者上学经历中是否有我们需要的,如果有需要的,则将它加入队列,最后循环爬取,将所有

    根据这个思路,我们猜想能否利用微博关注的人页面获取新用户,将地区(青岛)和学校作为筛选条件,满足条件作为可能认识的人,打印并保存其信息。按照如下流程循环,即可获得大量可能认识的人,然后我们可以对输出url进行手动访问,判断是否认识,认识则直接关注,岂不是美滋滋。

程序代码

# -*- coding:utf-8 -*-
__author__ = 'cck'
import requests
from bs4 import BeautifulSoup
import time
import pickle
from collections import deque
import random
import os
import copy

'''
注意事项:
1.工程文件夹下创建一个名为“中断数据保存”的文件夹
2.文件中存的内容分别是什么?
user_info(字典):用来存放爬取的信息
id_q(队列):查找结果的队列
url_follow(队列):待筛选的关注者队列
all_follow_id(列表):用来存放已经找过的用户id
info(字典):存放用户的url、个人简介、相册等信息(待完善)
3.cookie需要登录你的微博,之后按F12,在network里面获取
4.**的地方需要改成你的数据

'''

def td_has_style(tag):  # 查找
    return tag.has_attr('style') and tag.name == 'td'

class wb_crawler:
    def __init__(self):
        # q_tmp = deque()
        #改成你的cookie
        self.cookie = 'SCF=Ak-lTM1OIUxitjlcbC102f4RV5bUzvlzNPmYEHtdKxQFi6HJ17pwXg8cdHluXpTKngC6rOi8t-PguOqHoq5u0nY.; _T_WM=c23559ac343eca2d7a4b434339a62175; SUB=_2A25xQ5AJDeRhGeBO7VAU8ijMwj6IHXVSzzBBrDV6PUJbkdAKLWzDkW1NRchsyxcMaxDpKy8hAohQWmkFs3yrRJ_L; SUHB=0xnyVXOmVrN3C7; SSOLoginState=1548214361'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36',
            'Cookie': self.cookie
        }
        self.user_info = dict()  # 用来存放爬取的信息
        self.id_q = deque()  # 查找结果队列
        self.url_follow = deque()  # 待判断的关注者队列
        self.all_follow_id = []  # 用来存放已经找过的用户id
        self.f = open('中断数据保存/output.txt', 'a')  # 用来存放所有输出信息
        self.info = {
            'url': '',
            'comment': '',
            'album': '',
            'info': ''
        }
        self.user_id = 0  # 初始用户id,
        print('输入1:重新开始(!将删除所有以前数据!)n输入2: 继续上次')
        a = input()
        print(a)
        if os.path.getsize('中断数据保存/id_q.txt') > 0 and a == '2':  # 说明有数据,需要读取新数据,不需要初始user
            print('正在加载上次保存数据!')
            with open('中断数据保存/id_q.txt', 'rb') as file:
                self.id_q = pickle.loads(file.read())
            with open('中断数据保存/url_follow.txt', 'rb') as file:
                self.url_follow = pickle.loads(file.read())
            with open('中断数据保存/all_follow_id.txt', 'rb') as file:
                self.all_follow_id = pickle.loads(file.read())
            print('加载成功!')
            #继续中断前的操作^^^^
        elif a == '1' or os.path.getsize('中断数据保存/id_q.txt') == 0 :#否则指定初始user进行操作
            print('正在初始化!')
            self.clear_all()
            #使用你的初始用户
            self.user_id = **   #爬取第一个用户的id,该id一定是满足筛选条件的,你认识的人
            self.id_q.append(self.user_id)#
            self.all_follow_id.append(self.user_id)
            print('初始化成功!')

    def clear_all(self):
        ##把所有存取在硬盘中的数据清除掉,即将all_follow_id.txt等文件内容清空
        with open('中断数据保存/all_follow_id.txt', 'wb') as f1:
            f1.truncate()
        with open('中断数据保存/url_follow.txt', 'wb') as f2:
            f2.truncate()
        with open('中断数据保存/id_q.txt', 'wb') as f3:
            f3.truncate()
        with open('中断数据保存/user_info.txt', 'wb') as f4:
            f4.truncate()
        with open('中断数据保存/output.txt', 'wb') as f5:
            f5.truncate()

    #中断数据的保存,方便下次继续上次位置爬取
    def save_all(self):#每次找到新用户即调用保存
        pickle.dump(self.all_follow_id, open('中断数据保存/all_follow_id.txt', 'wb'))
        pickle.dump(self.url_follow, open('中断数据保存/url_follow.txt', 'wb'))
        pickle.dump(self.id_q, open('中断数据保存/id_q.txt', 'wb'))
        pickle.dump(self.user_info, open('中断数据保存/user_info.txt', 'wb'))

    def get_html(self,url, headers):  # 由个人cookies模拟访问网站,获取网站的html
        try:
            response = requests.get(url, headers=headers)
            response.raise_for_status()
        except:
            print('爬取{}出错,可能被封ip,正在保存当前数据!', url)
            #保存信息并退出
            self.save_all()
            print('保存成功!')
            # sys.exit()
            return ''
        return response.content

    def get_id(self,lxml):  # 根据主页的html获取该网页对应用户id
        soup = BeautifulSoup(lxml, "lxml")
        div = soup.find('div', 'tip2')
        u = div.find('a').get('href')
        id = u.split('/')
        return id[1]  # 获取id

    def find_region(self,lxml):  # 传入个人信息页面,判断地区学校等是否为你需要的
        soup = BeautifulSoup(lxml, "lxml")
        count = 1
        for div in soup.find_all('div', 'c'):
            if count == 4:  # 找到个人信息的标签部分
                if (div.get_text().find('**') != -1):  # 判断地区
                    print(div.get_text())  # 测试正误
                    self.info['info'] = div.get_text()
                    print(self.info)
                    print('找到可能认识的人!地址为:')
                    return True
                else:
                    print(div.get_text())#test
            if count == 5:
                if (div.get_text().find('**') != -1):  # 判断学校
                    print(div.get_text())  # 测试正误
                    self.info['info'] = div.get_text()

                    print('找到可能认识的人!地址为:')
                    return True
            count += 1
        return False

    def get_follow(self,lxml):  # 将新用户的关注者主页提取并加入队列
        soup = BeautifulSoup(lxml, "lxml")
        # f = open('output.txt','wb+')
        # f.write(lxml)
        # f.close()
        for td in soup.find_all(td_has_style):  # 获取该用户所有的关注的人,并加入爬取队列
            # print(td.find('a').get('href'))
            # td.find('a').get('href')
            self.url_follow.append(td.find('a').get('href'))

    def run(self):
        self.f.close()
        url = ''
        lxml = ''
        while len(self.id_q) != 0:
            print('now len of id_q is %d' % len(self.id_q)) # 测  试
            self.user_id = self.id_q.popleft() #从队列中获取一个用户
            url_root = "https://weibo.cn/%d" % self.user_id  # 构造主页
            # lxml = self.get_html(url,self.headers)# 访问主页获取lxml, 爬 1
            # self.user_id = (int)(self.get_id(lxml))  # 爬取用户id
            # # 1.id_q,读取其所有的follow加入follow队列,重复检测(list)
            # url = "https://weibo.cn/%d" % self.user_id #构造主页
            for page_count in range(1,21):
                #只爬取1-20页
                print('now catching page %d,root url: %s' % (page_count,url_root))
                url_follow = url_root + '/fans?page=%d' % page_count
                lxml_follow = self.get_html(url_follow,self.headers)# 抓取关注的人获取followlxml, 爬 1
                self.get_follow(lxml_follow)#读取加入follow队列
            # 2.分别爬取follow队列用户的info信息,筛选,并把满足要求的加入id_q
                while len(self.url_follow) != 0:
                    url = self.url_follow.popleft()
                    print('scaning url:'+url)
                    lxml = self.get_html(url,self.headers)# 爬2 爬取主页
                    self.user_id = (int)(self.get_id(lxml))
                    #id存在则跳过该id
                    if self.user_id in self.all_follow_id:
                        continue
                    self.all_follow_id.append(self.user_id)
                    url = "https://weibo.cn/%d" % self.user_id  # 构造主页
                    url_info = url + '/info'
                    lxml_info = self.get_html(url_info,self.headers)# 爬3 爬取信息页
                    if self.find_region(lxml_info):#满足要求加入id_q
                        self.id_q.append(self.user_id)
                        #out
                        str_out = "https://weibo.com/%d" % self.user_id
                        print(str_out)
                        # 获取信息
                        self.info['url'] = str_out
                        print(self.info)#test and will soon be deleted
                        info_copy = copy.deepcopy(self.info)
                        self.user_info[self.user_id] = info_copy#待修改,要求保存所有用户信息1.每次都加载上次的
                        print(self.user_info) #
                        #保存输出
                        self.f = open('中断数据保存/output.txt', 'a')
                        self.f.write(str_out+'n')
                        self.f.close()
                        self.save_all()
                    self.info.clear()
                    # time.sleep(3)
                    time.sleep(random.randint(2,6))#爬取一个之后,随机等待2-6秒

if __name__ == '__main__':
    crawler = wb_crawler()
    crawler.run()

 

cookie获取如图:

结果:

    效果还不错。

写在最后

    因为静态微博页面的爬取比较简单,第一次做的时候选择了使用静态页面,风格比较简陋,但也算是数据成功爬取到了吧。

而且本程序还有一些待完成的部分,比如爬取相册,评论的信息,设计的时候加了uer_info信息,但是最终没有实现,有兴趣的,或者有大佬来,可以帮忙看下,万分感谢。(。・`ω´・)

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/a429367172/article/details/86605672
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-08 11:49:13
  • 阅读 ( 1071 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢