python3+urllib打造新浪微博爬虫,真的很easy

前言(一些废话)

最近试了一下网页版的(weibo.com)和移动端的(m.weibo.cn),网页版的解析一大堆网页实在是太麻烦,移动端只需要请求,直接返回json数据,这里对这两种方式做了下优缺点对比

网页版

  • 优点
  1. 用户信息获取的很全面,出生日期、性取向、感情状况是移动端不能获取的
  2. 微博、粉丝可以抓取的比较全面
  3. 可以学习xpath、bs4、正则的网页解析
  • 缺点
  1. 要花钱哦,因为多账号登录需要验证码,验证码识别的话,用云打码(没用过)是收费的
  2. 解析页面恶心的一批,要写正则、要去看网页...比较麻烦

移动版

  • 优点
  1. 不需要验证码
  2. 直接解析json
  • 缺点
  1. 个人信息不全
  2. 微博、粉丝分页到了250之后,就没有数据返回了,暂时还没解决这个是为什么。

现在用的是移动版,配了5个微博账号,5个线程在跑,电脑扔在寝室跑,不敢说一天多少多少数据,但现在保持在一天用户30W、微博20W左右的数据量...只跑了两天...

源码的话,看后面....

正题

其实思路很简单,就是通过urllib模拟请求登录、发请求,然后解析json,存数据库...当然程序还有很多优化的地方,以后慢慢改进

环境

  • python3
  • django 1.11.3
  • mysql 5.7.17
  • fiddler 4

抓取

写爬虫的套路就是,访问页面,分析页面行为,也就是页面的每一个操作都发了什么样的请求,返回了什么数据,记住这个套路,还有什么爬虫不能写。

模拟登陆

打开m.weibo.cn,打开fiddler 4,开启https请求的捕捉,不知道怎么开自行google
当你输入好账号、密码点击登录的时候,看fiddler4捕获的请求


post请求,当然是看看他发了什么数据啦....

再看看response的数据


返回了用户登录的状态,uid...
你可以访问 www://weibo.com/u/ + 上图的uid加一波微博关注(真无耻,强行吸粉)

密码没有做任何加密处理,嘻嘻,很简单吧,现在只要模拟个post请求就行了。是不是很简单?

def login(user_name, password, opener):
    LOGGER.info(user_name + ' login')
    args = {
        'username': user_name,
        'password': password,
        'savestate': 1,
        'ec': 0,
        'pagerefer': 'https://passport.weibo.cn/signin/'
                     'welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F&wm=3349&vt=4',
        'entry': 'mweibo',
        'wentry': '',
        'loginfrom': '',
        'client_id': '',
        'code': '',
        'qq': '',
        'hff': '',
        'hfp': ''
    }

    post_data = urllib.parse.urlencode(args).encode()
    try_time = 0
    while try_time < constants.TRY_TIME:
        try:
            resp = opener.open(constants.LOGIN_URL, post_data)
            resp_json = json.loads(resp.read().decode())
            if 'retcode' in resp_json and resp_json['retcode'] == '20000000':
                LOGGER.info("%s login successful" % user_name)
                break
            else:
                LOGGER.warn('login fail:%s' % str(resp_json))
                sleep(10)
                try_time += 1
        except :
            LOGGER.error("login failed")
            LOGGER.error(traceback.print_exc())
            sleep(10)
            try_time += 1
            LOGGER.info('try %d time' % try_time)

看看写的模拟登录能不能用,当然要测试啦,这个测试当然是你自己写啦,反正我已经测试过了,如果不出意外的话,你的测试会不通过,如下URLError

Traceback (most recent call last):
  File "E:\codingspace\python\Jpider\spiders\weibo\weibo_http.py", line 40, in login
    resp = opener.open(constants.LOGIN_URL, post_data)
  File "D:\ProgramData\Anaconda3\lib\urllib\request.py", line 526, in open
    response = self._open(req, data)
  File "D:\ProgramData\Anaconda3\lib\urllib\request.py", line 544, in _open
    '_open', req)
  File "D:\ProgramData\Anaconda3\lib\urllib\request.py", line 504, in _call_chain
    result = func(*args)
  File "D:\ProgramData\Anaconda3\lib\urllib\request.py", line 1361, in https_open
    context=self._context, check_hostname=self._check_hostname)
  File "D:\ProgramData\Anaconda3\lib\urllib\request.py", line 1320, in do_open
    raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)>

哎呀,好烦,又报错,怎么办呢,stackoverflow欢迎你,传送门https://stackoverflow.com/,有错自己查,stackoverflow能解决99%你遇到的问题。

关注信息抓取

登录就那么轻松的搞定了,用户信息、微博、粉丝、关注的套路都是一样,分析拦截的请求,看哪个请求是返回数据的,然后自己模拟这个请求,就ok啦。

这里就只做用户关注的抓取示例,其他的自己去依葫芦画瓢。
最近在看环法,自己也是个骑行爱好者...现在天热...都不能出去骑了,很绝望。
就以环法自行车赛这个用户的关注信息为例吧

现在你可以借助chrome的工具栏看请求,windows下的快捷键是F12

查看他的关注->全部关注。你会发现浏览器发了如下的请求

你可以直接复制这个请求,在浏览器上打开。

可以看到这个请求返回的就是他的关注用户的json数据,而python中的json模块直接解析,很方便吧。

看看这个url[点开试试?]

https://m.weibo.cn/api/container/getIndex?containerid=231051_-_followers_-_5901021570&luicode=10000011&lfid=1005055901021570&featurecode=20000320&type=uid&value=5901021570

该用户的uid为5901021570,url是怎么拼的不用再多说了吧。

当然还有分页,自己往下拖,你可以看到url上会多了个page的参数,那个就是页号

数据都拿到了,还等什么?解析完后想怎么存怎么存吧。

    def grab_user_follower(self, user_id):
        opener = weibo_http.get_openner()
        user = self.grab_user(user_id)
        att_num = user.attNum
        max_page = int(int(att_num) / 20)
        page = 1
        while page <= max_page:
            resp = opener.open(constants.FOLLOWER_URL_PATTERN % (user_id, user_id, str(page)))
            self.logger.info(constants.FOLLOWER_URL_PATTERN % (user_id, user_id, str(page)))
            r = resp.read()
            resp_json = json.loads(r.decode())
            if 'msg' in resp_json:
                break
            for card in resp_json['cards']:

                for cg in filter(lambda c: 'user' in c, card['card_group']):
                    follower = dao.save_user_info(cg['user'])
                    dao.save_relationship(follower, user)
                    self.id_enqueue(follower.id, self.user_set_lock, self.CRAWLED_USERS, self.user_queue)
            page += 1

后语

关于微博移动端的抓取就暂时说这么多吧,说实话,移动端还是比较简单的,多线程可以搞定,只开了五个,日抓取量已经达到了30W用户+20W微博了,之后打算改成分布式的...

关于源码,暂时还没想放出来,因为不开心,而且我觉得这个也没什么难度,基本可以自己动手写,单线程写完再改成多线程的,很easy的...

当然我已经放在github了,地址暂时先不放,考验你找资料的能力了....

过几天再把网页版的抓取过程放上来,心情好点再说...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值