zoukankan      html  css  js  c++  java
  • Python 2.7_多进程获取简书专题数据(一)

    学python几个月了正好练练手,发现问题不断提高,先从专题入手,爬取些数据,一开始对简书网站结构不熟悉,抓取推荐,热门,城市3个导航栏,交流发现推荐和热门是排序不同,url会重复,以及每个专题详情页三个类目最新评论,最新收录, 热门也会重复 做了下调整,代码执行完毕会返回所有专题的urls元组对象,以便下一步进入每个专题页面解析获取其他数据。注:变量focus关注数,和打开专题后最上面显示的专题关注人数会有差异,例如有的专题关注了10175人,在专题列表页会显示成"10.07k",因此在下一次获取详情页的时候回取到具体数值

    多进程获取简书专题数据并写入MySQL数据库

    • 抓取热门和城市页面http://www.jianshu.com/recommendations/collections分类下的所有专题url,专题名字,收录文章数,关注数
    • 定义多个函数获取
      • 获取城市和热门两个分类异步加载的url函数
      • 解析url函数
      • 抓取数据 返回data对象
      • 获取数据存入数据库
      • 多进程   

    图1要获取的字段

    图2分析异步加载请求构造url

    建表

    #MySQL数据库建表
    CREATE TABLE catetable(
    cate_name VARCHAR(255),
    cate_url VARCHAR(255),
    total_num INT(19),
    focus INT(19),
    KEY cate_name(cate_name),
    KEY cate_url(cate_url)
    )ENGINE=INNODB DEFAULT CHARSET=utf8
    

    python代码

    #coding:utf-8
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    import requests
    from lxml import etree
    import MySQLdb
    from multiprocessing import Pool
    
    '''   
    获取所有所有专题所在页的url列表下一步提取每个专题的url
    分析:http://www.jianshu.com/recommendations/collections页面为异步加载,查看热门和城市导航栏请求构造url列表
    '''
    def get_cateurls():
        urls=[]
        for i in range(1, 3):
            cityurl='http://www.jianshu.com/recommendations/collections?page=%s&order_by=city' % i
            urls.append(cityurl)
        for j in range(1,40):
            hoturl='http://www.jianshu.com/recommendations/collections?page=%s&order_by=hot'% j
            urls.append(hoturl)
        return urls
    
    ''' 解析页面 ''' 
    def get_response(url):
        html=requests.get(url).content
        selector=etree.HTML(html)
        return selector
    
    ''' 获取专题数据 得到专题名称 专题url 收录文章数 关注人数 通过zip函数转置数据返回data对象''' 
    def get_catedata(url):
        selector=get_response(url)
        cate_url= map(lambda x: 'http://www.jianshu.com'+x, selector.xpath('//div[@id="list-container"]//div[contains(@class,"count")]/a/@href'))
        cate_name=selector.xpath('//div/h4/a/text()')
        total_num=map(lambda x: int(x.strip("篇文章").strip()),selector.xpath('//div[@id="list-container"]//div[contains(@class,"count")]/a/text()'))
        focus1=selector.xpath('//div[@id="list-container"]//div[contains(@class,"count")]/text()')
        focus=[]
        for i in focus1:
            focus_num=i.split("·")[1].rstrip("人关注")
            if "K" in focus_num:
                focus_num=int(float(focus_num[:-1])*1000)
            else:
                focus_num=int(focus_num)
            #print i,focus_num
            focus.append(focus_num)
        data=zip(cate_name,cate_url,total_num,focus)
        return data
    
    ''' 写入数据库''' 
    def insert_into_Mysql(url):
        try:
            conn=MySQLdb.connect(host='127.0.0.1',user='root',passwd='你的密码',db='local_db',port=3306,charset='utf8')
            with conn:
                cursor = conn.cursor()
                print u'正在加载 %s 页面' % url
                data=get_catedata(url)
                for i in data:
                    #print i[0], i[1], i[2],i[3]
                    cursor.execute("INSERT INTO  catetable (cate_name,cate_url,total_num,focus) values(%s,%s,%s,%s)", (i[0], i[1], i[2],i[3]))
                    conn.commit()
                sql='select * from catetable'
                count = cursor.execute(sql)
                print u'总共输入了%s条数据' % count
        except MySQLdb.Error,e:
            print e
    
    
    ''' 从数据库获取所有的专题url便于以后专题页面数据的进一步获取''' 
    def get_allcate_urls_from_mysql():
        try:
            conn = MySQLdb.connect(host='127.0.0.1', user='root', passwd='你的密码', db='local_db', port=3306, charset='utf8')
            with conn:
                cursor = conn.cursor()
                sql = 'select cate_url from catetable'
                count = cursor.execute(sql)
                print u'共输入了%s条数据' % count
                print u'正在获取专题url'
                all_cate_urls=cursor.fetchall()
                return all_cate_urls
        except MySQLdb.Error, e:
            print url,e
    
    ''' 多进程执行''' 
    def get_allcate_urls():
        urls=get_cateurls()
        pool = Pool(processes=4)
        pool.map(insert_into_Mysql,urls)
        allcate_urls=get_allcate_urls_from_mysql()
        return allcate_urls
    
    ''' 先获取到所有专题的数据 下次获取每个专题的数据''' 
    if __name__ == '__main__':
        allcate_urls=get_allcate_urls()
    

      

    查看数据表数据

    图3数据记录

    执行完查询到一共有914个专题,其中城市专题34个,880个热门专题

  • 相关阅读:
    正则表达式
    跨域请求/SpringMVC拦截器
    批量导出
    什么是2MSL以及TIME_WAIT的作用
    使用jstack精确找到异常代码的
    nettry 入站事件如何传递到下一个handler
    netty 引用计数器 ,垃圾回收
    elasticsearch 查询优化
    Spark性能优化指南-高级篇(spark shuffle)
    Broadcast与map进行join,避免shuffle,从而优化spark
  • 原文地址:https://www.cnblogs.com/Mr-Cxy/p/6391106.html
Copyright © 2011-2022 走看看