zoukankan      html  css  js  c++  java
  • 抓取百万级简书用户做数据挖掘

    简书日活用户至少几十万,因此抓取简书的用户,一方面做数据分析和挖掘,另一方面,看看有哪些it同行,挖掘一些高质量的文章。

    本文先分析抓取数据,结合抓取策略和scrapy框架,一步一步教你带你做爬虫和挖掘分析。

    先说抓取思路。本文思路是选择一个大V,大v就是关注用户较多,粉丝也多的用户作为爬虫抓取入口,然后不断对其关注用户和粉丝用户抓取,再对关注用户和粉丝的关注用户和粉丝进行抓取,如此循环。

    抓取函数入口:

        def start_requests(self):
            start_url = 'https://www.jianshu.com/u/811ae6268caa'
            yield Request(start_url, callback=self.parse)
    parse函数式scrapy的回调函数,主要解析用户信息和用户发表的文章,同时解析出其关注列表和粉丝列表进行递归抓取。当然抓取列表显然是有多页的,而这在简书里面的体现在ajax异步加载,只在拖动下拉
    的时候才会触发请求数据。这里拿到分页列表后,采取url拼接的方式构造分页请求。
    followed_url = 'https://www.jianshu.com'+info_selectors[0].xpath("./div/a/@href").extract()[0]
            followed = info_selectors[0].xpath("./div/a/p/text()").extract()[0]
            pages = int(float(followed)/10)
            for page in range(1,pages+1):
                userlist_url = followed_url + '?page={page}'.format(page=page)
                yield Request(userlist_url, callback=self.parseuserlist, dont_filter=True)

    同理抓取粉丝列表。抓取用户文章也一样。

     articles_url = 'https://www.jianshu.com' + info_selectors[2].xpath("./div/a/@href").extract()[0]
            articles = info_selectors[2].xpath("./div/a/p/text()").extract()[0]
            #抓取文章
            article_page= int(float(articles)/10)
            for page in range(1,article_page+1):
                articellist_url = articles_url + '?order_by=shared_at&page={page}'.format(page=page)
                yield Request(articellist_url, callback=self.parse_article_list, dont_filter=True)

    这样既可抓取文章了。

     再看parseuserlist和parse_article_list。解析用户信息和文章信息,然后持久化到文件。

        def parseuserlist(self,response):
            url_list = response.xpath("//ul[@class='user-list']/li/div[@class='info']/a/@href").extract()
            url_list = ['https://www.jianshu.com'+url for url in url_list]
            for url in url_list:
                yield Request(url,callback=self.parse,dont_filter=True)
        def parse_article_list(self, response):
            """
            根据总文章数抓取的每一页的文章列表
            :param response:
            """
            base_url_p = 'https://www.jianshu.com/p/'
            all_links_p = [base_url_p + link for link in re.compile('href="/p/(.*?)"', re.S).findall(response.text)]
            all_article_links = set(all_links_p)
            for article_link in all_article_links:
                yield Request(url=article_link, callback=self.parse_article, dont_filter=True)

    抓取文章列表的时候对每篇文章进行解析,parse_article函数负责解析。

        def parse_article(self, response):
            try:
                bs = BeautifulSoup(response.text, 'lxml')
                url = response.url
                article = ArticleItem()
                article['id'] = str(url).split('/')[-1].split('?')[0]
                article['url'] = url
                article['title']=bs.select("title")[0].get_text()     # 标题
                article['name']=bs.select("div[class='author']")[0].select("span[class='name']")[0].get_text() # 作者名字
                article['post_time']=bs.select("span[class='publish-time']")[0].get_text()  # 发布时间
                article['content']=bs.select("div[class='show-content']")[0].get_text()     # 文章内容
                # article['read_count']= bs.select("span[class='views-count']")[0].get_text() if bs.select("span[class='publish-time']") else "0" # 阅读次数
                # article['comment_count']=bs.select("span[class='comments-count']")[0].get_text() if bs.select("span[class='comments-count']") else "0" # 评论次数
                # article['love_count']=bs.select("span[class='likes-count']")[0].get_text() if bs.select("span[class='likes-count']") else "0"       # 喜欢次数
                yield article
            except Exception as e:
                print(e)

    持久化pipeline,这里为了简便直接写入文件。

        def process_item(self, item, spider):
            if isinstance(item, JianshuItem):
                with open('jianshu_user.csv', 'a+', encoding='utf-8', newline='') as f:
                    writer = csv.writer(f)
                    writer.writerow((item['id'], item['url'], item['nickname'], item['description'], item['followed'], item['following'], item['articles'], item['charlength'], item['likes']))
                    return item
            elif isinstance(item, ArticleItem):
                with open('jianshu_article.csv', 'a+', encoding='utf-8', newline='') as f:
                    writer1 = csv.writer(f)
                    writer1.writerow(
                        (item['id'], item['url'], item['name'], item['title'], item['post_time'], item['content']))
                return item

    这里要保存的数据分为user和article两个类。保存的数据在item类体现。

    class JianshuItem(Item):
        url = Field() #主页
        id = Field()
        nickname = Field()
        description = Field()
        followed = Field()
        following = Field()
        articles = Field()
        charlength = Field()
        likes = Field()
    
    class ArticleItem(Item):
        url = Field()   #当前网页的url
        id = Field()    #作者ID
        name = Field()  # 作者名字
        title = Field() #标题
        post_time = Field()    #发布时间
        content = Field()      #文章内容
        read_count = Field()   #阅读次数
        comment_count = Field()#评论次数
        love_count = Field()   #喜欢次数

    最后,为了反爬虫,增加模拟浏览器的请求头,在scrapy的增加HeadersDownloaderMiddleware中间件,并在配置文件开启。

    class HeadersDownloaderMiddleware(UserAgentMiddleware):
        
        def process_request(self, request, spider):
            ua = random.choice(UserAgentList)
            request.headers.setdefault('User-Agent:', ua)

    其中

    UserAgentList为手动配置的,当然也可以使用fake—Agent。
    最后,在命令行执行:
    sys.path.append(os.path.dirname(os.path.basename(__file__)))
    execute(['scrapy','crawl','jianshu'])

    爬虫就跑起来了。

     
  • 相关阅读:
    开博客啦
    C语言 变长参数表的使用方法
    禅道程序员
    【转】函数式编程另类指南
    Servlet中JSP页面跳转的两种方法以及其区别
    《C程序设计语言》(学习笔记)——结构体
    C#保存wps和office表格.数据源为list<T>类型
    中国网建的短信接口实现
    C#保存wps和office表格.数据源为list<T>类型,
    MD5加密
  • 原文地址:https://www.cnblogs.com/hd-zg/p/9106968.html
Copyright © 2011-2022 走看看