zoukankan      html  css  js  c++  java
  • Python爬虫入门教程 34-100 掘金网全站用户爬虫 scrapy

    爬前叨叨

    已经编写了33篇爬虫文章了,如果你按着一个个的实现,你的爬虫技术已经入门,从今天开始慢慢的就要写一些有分析价值的数据了,今天我选了一个《掘金网》,我们去爬取一下他的全站用户数据。

    爬取思路

    获取全站用户,理论来说从1个用户作为切入点就可以,我们需要爬取用户的关注列表,从关注列表不断的叠加下去。

    随便打开一个用户的个人中心

    在这里插入图片描述

    绿色圆圈里面的都是我们想要采集到的信息。这个用户关注0人?那么你还需要继续找一个入口,这个用户一定要关注了别人。选择关注列表,是为了让数据有价值,因为关注者里面可能大量的小号或者不活跃的账号,价值不大。

    我选了这样一个入口页面,它关注了3个人,你也可以选择多一些的,这个没有太大影响!
    https://juejin.im/user/55fa7cd460b2e36621f07dde/following
    我们要通过这个页面,去抓取用户的ID
    在这里插入图片描述

    得到ID之后,你才可以拼接出来下面的链接

    https://juejin.im/user/用户ID/following
    

    爬虫编写

    分析好了之后,就可以创建一个scrapy项目了

    items.py 文件,用来限定我们需要的所有数据,注意到下面有个_id = scrapy.Field() 这个先预留好,是为了mongdb准备的,其他的字段解释请参照注释即可。

    class JuejinItem(scrapy.Item):
       
        _id = scrapy.Field()
        username = scrapy.Field()
        job = scrapy.Field()
        company =scrapy.Field()
        intro = scrapy.Field()
        # 专栏
        columns = scrapy.Field()
        # 沸点
        boiling = scrapy.Field()
        # 分享
        shares = scrapy.Field()
        # 赞
        praises = scrapy.Field()
        #
        books = scrapy.Field()
        # 关注了
        follow = scrapy.Field()
        # 关注者
        followers = scrapy.Field()
        goods = scrapy.Field()
        editer = scrapy.Field()
        reads = scrapy.Field()
        collections = scrapy.Field()
        tags = scrapy.Field()
    
    

    编写爬虫主入口文件 JuejinspiderSpider.py

    import scrapy
    from scrapy.selector import Selector
    from Juejin.items import JuejinItem
    
    class JuejinspiderSpider(scrapy.Spider):
        name = 'JuejinSpider'
        allowed_domains = ['juejin.im']
        # 起始URL    5c0f372b5188255301746103
        start_urls = ['https://juejin.im/user/55fa7cd460b2e36621f07dde/following']
    

    def parse 函数,逻辑不复杂,处理两个业务即可

    1. 返回item
    2. 返回关注列表的Request

    item的获取,我们需要使用xpath匹配即可,为了简化代码量,我编写了一个提取方法,叫做get_default函数。

        def get_default(self,exts):
            if len(exts)>0:
                ret = exts[0]
            else:
                ret = 0
            return ret
    
        def parse(self, response):
            #base_data = response.body_as_unicode()
            select = Selector(response)
            item = JuejinItem()
            # 这个地方获取一下数据
            item["username"] = select.xpath("//h1[@class='username']/text()").extract()[0]
            position = select.xpath("//div[@class='position']/span/span/text()").extract()
            if position:
                job = position[0]
                if len(position)>1:
                    company = position[1]
                else:
                    company = ""
            else:
                job = company = ""
            item["job"] = job
            item["company"] = company
            item["intro"] = self.get_default(select.xpath("//div[@class='intro']/span/text()").extract())
            # 专栏
            item["columns"] = self.get_default(select.xpath("//div[@class='header-content']/a[2]/div[2]/text()").extract())
            # 沸点
            item["boiling"] = self.get_default(select.xpath("//div[@class='header-content']/a[3]/div[2]/text()").extract())
            # 分享
            item["shares"] = self.get_default(select.xpath("//div[@class='header-content']/a[4]/div[2]/text()").extract())
            # 赞
            item["praises"] = self.get_default(select.xpath("//div[@class='header-content']/a[5]/div[2]/text()").extract())
            #
            item["books"] = self.get_default(select.xpath("//div[@class='header-content']/a[6]/div[2]/text()").extract())
    
            # 关注了
            item["follow"] = self.get_default(select.xpath("//div[@class='follow-block block shadow']/a[1]/div[2]/text()").extract())
            # 关注者
            item["followers"] = self.get_default(select.xpath("//div[@class='follow-block block shadow']/a[2]/div[2]/text()").extract())
    
    
            right = select.xpath("//div[@class='stat-block block shadow']/div[2]/div").extract()
            if len(right) == 3:
                item["editer"] = self.get_default(select.xpath("//div[@class='stat-block block shadow']/div[2]/div[1]/span/text()").extract())
                item["goods"] = self.get_default(select.xpath("//div[@class='stat-block block shadow']/div[2]/div[2]/span/span/text()").extract())
                item["reads"] = self.get_default(select.xpath("//div[@class='stat-block block shadow']/div[2]/div[3]/span/span/text()").extract())
    
            else:
                item["editer"] = ""
                item["goods"] = self.get_default(select.xpath("//div[@class='stat-block block shadow']/div[2]/div[1]/span/span/text()").extract())
                item["reads"] = self.get_default(select.xpath("//div[@class='stat-block block shadow']/div[2]/div[2]/span/span/text()").extract())
    
    
            item["collections"] = self.get_default(select.xpath("//div[@class='more-block block']/a[1]/div[2]/text()").extract())
            item["tags"] = self.get_default(select.xpath("//div[@class='more-block block']/a[2]/div[2]/text()").extract())
            yield item  # 返回item
     
    

    上述代码,已经成功返回了item,打开setting.py文件中的pipelines设置,测试一下是否可以存储数据,顺便在
    DEFAULT_REQUEST_HEADERS 配置一下request的请求参数。

    setting.py

    DEFAULT_REQUEST_HEADERS = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'en',
        "Host": "juejin.im",
        "Referer": "https://juejin.im/timeline?sort=weeklyHottest",
        "Upgrade-Insecure-Requests": "1",
        "User-Agent": "Mozilla/5.0 浏览器UA"
    }
    
    ITEM_PIPELINES = {
       'Juejin.pipelines.JuejinPipeline': 20,
    }
    

    本爬虫数据存储到mongodb里面,所以需要你在pipelines.py文件编写存储代码。

    
    import time
    import pymongo
    
    DATABASE_IP = '127.0.0.1'
    DATABASE_PORT = 27017
    DATABASE_NAME = 'sun'
    client = pymongo.MongoClient(DATABASE_IP,DATABASE_PORT)
    db = client.sun
    db.authenticate("dba", "dba")
    collection = db.jujin  # 准备插入数据
    
    
    class JuejinPipeline(object):
    
        def process_item(self, item, spider):
            try:
                collection.insert(item)
            except Exception as e:
                print(e.args)
    
    

    运行代码之后,如果没有报错,完善最后一步即可,在Spider里面将爬虫的循环操作完成

          list_li = select.xpath("//ul[@class='tag-list']/li")  # 获取所有的关注
          for li in list_li:
               a_link = li.xpath(".//meta[@itemprop='url']/@content").extract()[0] # 获取URL
    			 # 返回拼接好的数据请求
               yield scrapy.Request(a_link+"/following",callback=self.parse)
    

    所有的代码都已经写完啦
    在这里插入图片描述

    全站用户爬虫编写完毕,厉害吧。

    扩展方向

    1. 爬虫每次只爬取关注列表的第一页,也可以循环下去,这个不麻烦
    2. setting.py中开启多线程操作
    3. 添加redis速度更快,后面会陆续的写几篇分布式爬虫,提高爬取速度
    4. 思路可以扩展,N多网站的用户爬虫,咱后面也写几个
  • 相关阅读:
    一起谈.NET技术,深入ASP.NET 2.0的提供者模型(2) 狼人:
    一起谈.NET技术,从.NET中委托写法的演变谈开去(上):委托与匿名方法 狼人:
    一起谈.NET技术,将Flash 嵌入WPF 程序 狼人:
    一起谈.NET技术,数组排序方法的性能比较(中):Array.Sort<T> 实现分析 狼人:
    人一生当中最应该珍惜的十种人
    《程序员的第一年》复习一下C#的【封装 多态 继承 简单计算器源码实例】
    myeclipse 修改模板
    三星将在百思买零售店内开设1400家体验店
    谷歌Q3推Android本 蚕食自己平板市场
    Spring Setting
  • 原文地址:https://www.cnblogs.com/happymeng/p/10381549.html
Copyright © 2011-2022 走看看