Chihiro20

如果我真的存在,也是因为你需要我。

数据采集与融合技术第二次实践

第二次作业

作业①

  • 要求:在中国气象网(http://www.weather.com.cn)给定城市集的7日天气预报,并保存在数据库。

  • 输出信息

    序号 地区 日期 天气信息 温度
    1 北京 7日(今天) 晴间多云,北部山区有阵雨或雷阵雨转晴转多云 31℃/17℃
    2 北京 8日(明天) 多云转晴,北部地区有分散阵雨或雷阵雨转晴 36℃/22℃
    3 北京 9日(后天) 晴转多云 31℃/17℃
    4 北京 10日(周六) 阴转阵雨 30℃/19℃
    5 北京 11日(周日) 阵雨 27℃/18℃
    6...

    (1)实现过程:

    1. 创建数据库weathers.db:

      
       # 打开数据库
       def openDB(self):
           self.con = sqlite3.connect("weathers.db")
           self.cursor = self.con.cursor()
           try:
               self.cursor.execute(    # 创建数据库
                   "create table weathers (wCity varchar(16),wDate varchar(16),wWeather varchar(64),wTemp varchar(32),"
                   "constraint pk_weather primary key (wCity,wDate))")
           except:
               self.cursor.execute("delete from weathers")
       # 插入数据
       def insert(self, city, date, weather, temp):    # 插入数据
           try:
               self.cursor.execute("insert into weathers (wCity,wDate,wWeather,wTemp) values (?,?,?,?)",
                                   (city, date, weather, temp))
           except Exception as err:
               print(err)
      
      
    2. 提取天气信息并写进数据库:

      
       # 城市名称极其代号
       self.cityCode = {"北京": "101010100", "上海": "101020100", "广州": "101280101", "深圳": "101280601"}
      
       date = li.select('h1')[0].text      # 日期信息
       weather = li.select('p[class="wea"]')[0].text   # 天气信息
       temp = li.select('p[class="tem"] span')[0].text + "/" + li.select('p[class="tem"] i')[0].text   # 温度信息
       self.db.insert(city, date, weather, temp)       # 调用函数插入数据
      
      
    3. 结果展示:

      
       # 将数据库信息打印出来
       self.cursor.execute("select * from weathers")
       rows = self.cursor.fetchall()
       tplt = "{0:^10}\t{1:{4}^10}\t{2:{4}^20}\t{3:^10}"
       print(tplt.format("city", "date", "weather", "temp", chr(12288)))
       for row in rows:
           print(tplt.format(row[0], row[1], row[2], row[3], chr(12288)))
      
      

      由于是在晚上运行代码,所以今天的天气打印不出来,在清晨进行爬取即可打印今日天气情况

    (2)心得体会:

    作业①主要考察对数据库的一系列操作,包括打开,关闭,插入数据,打印数据库信息...以及对CSS算法的巩固。

作业②

  • 要求:用requests和BeautifulSoup库方法定向爬取股票相关信息。

  • 候选网站:东方财富网:http://quote.eastmoney.com/center/gridlist.html#hs_a_board

  • 技巧:在谷歌浏览器中进入F12调试模式进行抓包,查找股票列表加载使用的url,并分析api返回的值,并根据所要求的参数可适当更改api的请求参数。根据URL可观察请求的参数f1、f2可获取不同的数值,根据情况可删减请求的参数。
    参考链接:https://zhuanlan.zhihu.com/p/50099084

  • 输出信息

    序号 股票代码 股票名称 最新报价 涨跌幅 涨跌额 成交量 成交额 振幅 最高 最低 今开 昨收
    1 688093 N世华 28.47 62.22% 10.92 26.13万 7.6亿 22.34 32.0 28.08 30.2 17.55
    2...

    (1)实现过程:

    1. 抓取js包
      首先找到沪深A股,鼠标右键检查:


      然后找到我们想要的json包:


      最后查看页面url,方便后面步骤的翻页处理:

    2. 创建数据库stocks.db(步骤同作业1,不再赘述)

    3. 提取股票关键信息:
      首先由下图可以看到所有股票信息都在diff里面

      data = re.findall(r'"diff":\[\{(.*?)\}\]', resp)
      其次提取每支股票的详细信息(以第一支为例):

      代码:

          j = 1  # j表示序号
          for i in range(len(datas)):
              stock = re.findall(r':(.*?),', datas[i])         # re找到包含股票信息的内容
              stocks.append(stock)
          for stock in stocks:
              s0 = j                                  # 序号
              s1 = stock[11].replace('"', '')         # 股票代码
              s2 = stock[13].replace('"', '')         # 股票名称
              s3 = stock[1]                           # 最新报价
              s4 = stock[2]                           # 涨跌幅
              s5 = stock[3]                           # 涨跌额
              s6 = stock[4]                           # 成交量
              s7 = stock[5]                           # 成交额
              s8 = stock[6]                           # 振幅
              s9 = stock[14]                          # 最高
              s10 = stock[15]                         # 最低
              s11 = stock[16]                         # 今开
              s12 = stock[17]                         # 昨收
              # print(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12)
              self.db.insert(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12)
              j = j + 1
      
    4. 主函数:

    5. 结果截图:
      打印函数:

      输出:

    (2)心得体会:

    作业②主要考察了从F12里的network找到所需要的json包的抓取,以及re正则的使用。

作业③

  • 要求:爬取中国大学2021主榜 https://www.shanghairanking.cn/rankings/bcur/2021 所有院校信息,并存储在数据库中,同时将浏览器F12调试分析的过程录制Gif加入至博客中。

  • 技巧:分析该网站的发包情况,分析获取数据的api

  • 输出信息

    排名 学校 总分
    1 清华大学 969.2

    (1)实现过程:

    1. 浏览器F12调试分析的过程录制Gif展示:

    1. 创建数据库univ.db:

    2. 提取院校信息:

          resp = requests.get(url, headers=headers)
          resp = resp.content.decode()
          data = re.findall(r'univData:\[(\{.*?\})\]', resp)
          datas = data[0].split('},{')
          name = re.findall(r'univNameCn:"(.*?)"', datas[i])[0]
          score = re.findall(r'score:(.*?),', datas[i])[0]
      
    3. 结果展示:

    (2)心得体会:

    作业③同作业②类似,巩固json包的抓取,以及re正则的使用.
    需要注意的是,在这次爬取过程中会出现乱码。

    以上图为例,可以发现这所院校的分数并不是数字,而是一个代号。我们将json文件中的function解析出来:

     ![](https://img2020.cnblogs.com/blog/2533398/202110/2533398-20211023201028778-41571932.png)
    
     ![](https://img2020.cnblogs.com/blog/2533398/202110/2533398-20211023202009698-1365709443.png)
    

    翻到funtion的后面,可以看到从"",false开始,上图的每一个字母,在下图中都有对应的内容。可以参照红框。

    代码实现:
    ```

          # 找到乱码与数字对应的内容
          function = re.findall('function\((.*?)\){', resp)
          function = function[0].split(',')
          item = re.findall('void 0}}\((.*?)\)', resp)
          item = item[0].split(',')
    
          for i in range(len(datas)):
              name = re.findall(r'univNameCn:"(.*?)"', datas[i])[0]
              score = re.findall(r'score:(.*?),', datas[i])[0]
              try:
                  score = eval(score)
              except Exception:
                  try:
                      index = function.index(score)
                      score = eval(item[index + 1])  # 将总分的乱码替换成数字
                  except Exception as err:
                      print(err)
      ``` 
    

附:完整代码地址

posted @ 2021-10-23 20:25  chihiro20  阅读(11)  评论(0编辑  收藏  举报