爬虫系列二之爬取微博用户

1.爬取思路
从一个用户的关注列表入手,爬取所有他关注的用户(微博限制只能看到200个),然后再以这200个入手,爬取这200个关注的。200*200 然后以此类推。由于微博的加载方式是动态的,决定从 m.weibo.cn作为入口,以解析微博api的方式获得数据。爬下来的数据用mysql存储,因为只是学习,只爬10万条好了,就要三个数据:用户名 +微博uid+头像

主页因为可以通过uid跳转,就不单独保存了,头像地址也是拼接出来的,保存最后地址信息就好了

2.使用工具
爬虫还是老朋友 scrapy了
数据库用mysql,python上用SQLAlchemy 框架
创建数据库

create database weibo  default charset utf8 COLLATE utf8_general_ci;
use weibo;
create table if not exists t_weibo_user(id bigint auto_increment primary key ,weibo_id bigint unique not null,username varchar(30) not null,avatar text not null)ENGINE=InnoDB DEFAULT CHARSET=utf8;

用chrome的检查功能查看 api的参数,
爬取入口页 选择一个大v的关注列表即可
笔者用的是
姚晨的关注页
用chrome的检查元素功能可以看到请求关注列表 的api涉及的参数

weibo1.png

这里可以拿到curl的
然后用curl解析出请求headers,这里的headers 很重要尤其是需要登陆后标记你自己的cookies,因为游客是请求不下这些数据的
3 scarpy 编程部分
我们已经拿到了请求头,分析出获得关注列表的api
https://m.weibo.cn/api/container/getIndex?containerid=231051_-followers-_%s&luicode=10000011&lfid=107603%s&featurecode=20000320&type=uid&value=%s&page=1
这里面的%s是拼接用的占位符,用微博用户uid替换,这个用户uid也是拉下来的
,接下来编写python代码

数据库操作用的 sqlInstance.py

from sqlalchemy import create_engine, text, Column, BigInteger, String, Sequence, Date, UniqueConstraint, MetaData
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()


class WeiboUserBean(Base):
    __tablename__ = "t_weibo_user"
    id = Column(BigInteger, primary_key=True, autoincrement=True)
    weibo_id = Column(BigInteger,unique = True)
    username = Column(String(30), nullable=False)
    avatar = Column(String, nullable=False)
    # __table_args__ = (UniqueConstraint('companyname', 'checkdate'),
    #                   )


engine = create_engine('mysql+pymysql://pig:123456@localhost:3306/weibo?charset=utf8', encoding='utf-8', echo=False,
                       pool_size=50, pool_recycle=3600)
DBSession = sessionmaker(bind=engine)

class SqlInstance:
    def tryadd(self):
        session = DBSession()
        session.add(WeiboUserBean(weibo_id=1111,username='123',avatar='1234'))
        session.commit()
        session.close()
    def add_weibo_user(self,weibouser):
        if isinstance(weibouser,WeiboUserBean):
            session = DBSession()
            session.add(weibouser)
            session.commit()
            session.close()
sqlInstance = SqlInstance()
if __name__ == '__main__':
    sqlInstance.tryadd()

spider主程序 weibospider.py

# -*- coding: utf-8 -*-
import json
from queue import Queue

import scrapy
from scrapy import Request
from weibo_scrapy import sqlinstance

import re

class WeibospiderSpider(scrapy.Spider):
    name = 'weibospider'
    allowed_domains = ['m.weibo.cn']
    start_urls = ['https://m.weibo.cn/api/container/getIndex?containerid=231051_-_followers_-_1266321801&luicode=10000011&lfid=1076031266321801&featurecode=20000320&type=uid&value=1266321801&page=1']
    queue=Queue()
    def parse(self, response):
        pagenow=re.findall(r"page=(.*?)$",response.url)[0]
        mjsonobj=json.loads(response.text)
        if mjsonobj["cards"]:
            try:
                usercards=mjsonobj["cards"][-1]["card_group"]
            except:
                uid = self.queue.get()
                yield Request(
                    'https://m.weibo.cn/api/container/getIndex?containerid=231051_-_followers_-_%s&luicode=10000011&lfid=107603%s&featurecode=20000320&type=uid&value=%s&page=1' % (
                    uid, uid, uid))
                pass
            for usecard in usercards:
                user=usecard["user"]
                imagepath=""
                try:
                    imagepath=user["avatar_hd"].split("/")[-1]
                except:
                    pass
                try:
                    sqlinstance.sqlInstance.add_weibo_user(sqlinstance.WeiboUserBean(weibo_id=user['id'],username=user['screen_name'],avatar=imagepath))
                except Exception as e:
                    print(e)
                    pass
                self.queue.put(user['id'])
                print("query add")

            targeturl=response.url.replace("page="+pagenow,"page="+str(int(pagenow)+1))
            yield Request(targeturl)
        else:
            uid=self.queue.get()
            yield Request('https://m.weibo.cn/api/container/getIndex?containerid=231051_-_followers_-_%s&luicode=10000011&lfid=107603%s&featurecode=20000320&type=uid&value=%s&page=1'%(uid,uid,uid))

在setting.py里面改scrapy的请求头和间隔
这样基本就好了

最后分享一个curl截取headers的方法

import re
str = ''' curl 'https://m.weibo.cn/api/container/getIndex?containerid=231051_-_followers_-_1266321801&luicode=10000011&lfid=1076031266321801&featurecode=20000320&type=uid&value=1266321801&page=2' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: zh-CN,zh;q=0.9' -H 'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36' -H 'Accept: application/json, text/plain, */*' -H 'Referer: https://m.weibo.cn/p/index?containerid=231051_-_followers_-_1266321801_-_1042015%253AtagCategory_050&luicode=10000011&lfid=1076031266321801&featurecode=20000320' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' --compressed '''
searches = re.findall(r"-H '.*?'", str)
dicct = {}
for searche in searches:
    searche= searche.replace("-H", "")
    searche=searche.replace("'", "")
    searche=searche.strip()
    split = searche.split(": ")
    dicct[split[0].strip()] = split[1].strip()
print(dicct)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容