zoukankan      html  css  js  c++  java
  • 曼城新闻情报站(一)爬取3大网站的曼城新闻

    想完成一个Django框架的爬虫,将曼城的新闻内容爬到并放入数据库,然后通过Django框架用网页显示出来。现在第一步是爬新浪、网易、腾讯的曼城新闻内容并放入Mongodb中。本来搜狐也是一个计划中的门户网站,但是爬出来的内容中文不能正常显示,不像是编码的问题,于是就直接跳过了。

    这个程序关键的地方是新浪和网易的球队新闻都是js动态显示的,新浪还是json格式的网页,要找到真正的目的网页还是费了一些周章的。由于新闻具有时效性,所以只抓了首页的新闻内容,避开了逐个翻页的麻烦。

    来看看网易的真实网址。查看元素,选JS,然后鼠标指到曼城可以看到多了个js地址,点进去找到URL打开。

    这样的网页内容看似一个字典的样子,但我没找到简单的方法把想要的数据取出来,直接用的正而表达式取数据。

    新浪的方法一样,不过新浪用的js翻页,用正则取出了一个json文件,再抓数据。

    现在上代码

    #-*- coding:utf-8 -*-
    #_author:John
    #date:2018/9/10 19:37
    #softwave: PyCharm
    from bs4 import BeautifulSoup
    from datetime import datetime
    import requests
    import re, json
    import pymongo
    
    class Man_City():
        def __init__(self):
            self.header = {
                'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
                'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
            }
    
        def news_man(self):
            #这是js动态生成的页面,需要找到对应的js网页,再用正则表达式找到所需内容
            man_163_url = 'http://sports.163.com/special/000587PO/newsdata_epl_mch.js?callback=data_callback'
            man_163_data = requests.get(man_163_url, headers=self.header)
            man_163_soup = BeautifulSoup(man_163_data.text, 'lxml').get_text()
            title_re = re.compile('title":"(.*?)",')
            url_re = re.compile('docurl":"(.*?)",')
            tienum_re = re.compile('tienum":(d+),')
            pub_date_re = re.compile('time":"(.*?)",')
    
            titles = title_re.findall(man_163_soup)
            urls = url_re.findall(man_163_soup)
            tienums = tienum_re.findall(man_163_soup)
            pub_dates = pub_date_re.findall(man_163_soup)
    
            for title, url, tienum, pub_date in zip(titles, urls, tienums, pub_dates):
                data = {
                    'title': title,
                    'url': url,
                    # 'tienum': tienum,
                    #将字符串的时间转换成时间模式再传入数据库,以便之后以时间进行排序
                    'pub_date': datetime.strftime(datetime.strptime(pub_date, '%m/%d/%Y %H:%M:%S'), '%Y-%m-%d %H:%M:%S')
    
                }
                print(data)
                self.add_to_mongodb(db_name='163', data=data)
    
        def sina_man_news(self):
            #跟163一样先找到真正的网页,得到的是一个json格式的页面,转换一下再取内容
            url = 'http://interface.sina.cn/pc_zt_api/pc_zt_press_news_doc.d.json?subjectID=68265&cat=&size=40&page=1&channel=sports&callback=jsonpcallback1536942563301'
            data_get = requests.get(url, headers= self.header)
            #获取的网页内容大括号里面的是json数据,用正则表达式获取大括号里面的内容得到json格式数据
            data_re = re.compile('((.*?))')
            soup_data = data_re.findall(data_get.text)[0]
            soup = json.loads(soup_data)
            for i in soup['result']['data']:
                # 观察发现日期是放在url中的,把日期分离出来
                pub_date_soup = i['url'].split('/')[-2]
                data = {
                    'title': i['title'],
                    'url': i['url'],
                    #转换时间格式
                    'pub_date':datetime.strftime(datetime.strptime(pub_date_soup, '%Y-%m-%d'), '%Y-%m-%d')
                }
                print(data)
                self.add_to_mongodb(db_name='sina', data=data)
    
        def qq_man_news(self):
            #腾讯里面的曼城新闻没有用js生成,是静态的网页,直接用bs4获取
            url='http://sports.qq.com/premierleague/'
            data_get=requests.get(url, headers=self.header)
            soup = BeautifulSoup(data_get.text, 'lxml')
            titels = soup.select('.newsul.newsCont3 .news_txt a')
            for i in titels:
                # 跟新浪一样的,日期包含在url中
                pub_date_soup = i.get('href').split('/')[-2]
                data = {
                    'title': i.get_text(),
                    'url': 'http://sports.qq.com/'+ i.get('href'),
                    #转换时间格式
                    'pub_date':datetime.strftime(datetime.strptime(pub_date_soup, '%Y%m%d'), '%Y-%m-%d')
                }
                self.add_to_mongodb(db_name='qq', data=data)
                print(data)
    
        def add_to_mongodb(self, db_name, data):
            #分别命名存入数据库
            client = pymongo.MongoClient('localhost', 27017)
            Man_City = client['Man_City']
            db_name = Man_City[db_name]
            #用日期倒序排列,取出60个标题放到列表,如果新获取的数据标题不在这60个标题列表中就加入数据库中,避免同一个新闻多次存入数据库
            pipeline= [
                {'$sort':{'pub_date':-1}},
                {'$limit':60,},
            ]
            titel_list = [db['title'] for db in db_name.aggregate(pipeline)]
            if data['title'] not in titel_list:
                db_name.insert_one(data)
    
    if __name__ == '__main__':
        M = Man_City()
        M.news_man()
        M.sina_man_news()
        M.qq_man_news()
        # M.add_to_mongodb(db_name='sina')
     

    为了后面按新闻日期排序,所以在把数据存入数据库前把新闻日期一栏全部转换成了日期格式。存入数据库前取最近存入的60条新闻来比对获得的新闻是不是已经在数据库中了,避免多次存入同一条新闻。

    最后的成果如下

    现在只是完成了获取数据的第一步,后面还需要用到Django框架,把获取到的数据在网页中显示出来。

  • 相关阅读:
    怎么样实现打印网页中指定的表格,而不是全页
    加深C# 中字符串前加@符号理解以及使用~~
    CommandArgument 绑定多个参数
    gridview等控件CommandField英文的解决.
    正式发布基于VS2008的AJAX模板包
    给datalist加自动编号
    .net生成文字图片
    重新注册.net
    Android JNI入门第二篇——Java参数类型与本地参数类型对照
    Android推送方式比较
  • 原文地址:https://www.cnblogs.com/lkd8477604/p/9697475.html
Copyright © 2011-2022 走看看