利用python爬取大渡河公司新闻信息(爬虫)

2019-04-12  本文已影响0人  Xyxtank

一、公司简介

大渡河公司于2000年11月在成都高新区注册成立,主要任务是以龚嘴、铜街子为母体电站,滚动开发大渡河流域水电站,是国家能源集团所属最大的集水电开发建设和运营管理于一体的大型流域水电开发公司。

公司目前主要负责大渡河流域开发和西藏帕隆藏布流域开发筹建,拥有大渡河干流、支流以及西藏帕隆藏布流域水电资源约3000万千瓦。大渡河流域规划28个梯级电站开发,总装机约2340万千瓦。公司负责干流17个梯级电站的开发,涉及四川省三州两市(甘孜州、阿坝州、凉山州、雅安市、乐山市)12个县,总装机约1757万千瓦,形成了投产、在建、筹建稳步推进的可持续发展格局。帕隆藏布流域已完成流域规划报告(咨询稿),初步规划了“一库九级”方案,规划装机1142万千瓦。截至目前,公司资产总额为910.68亿元,在川投运装机约占四川统调水电总装机容量的四分之一。

二、需求分析

分析统计网站新闻标题、作者、日期等信息,分析一下该网站上网新闻有上面共性,也就是哪些类型题材新闻更容易上,另外也可以分析一下该公司上稿较多的作者,上稿较多一定程度上能反应作者水平。

三、具体实施

1、利用python爬虫技术获取该公司网站新闻相关信息
第一步,爬取url:重构url,并将其放入多线程队列之中

              url = 'http://www.spddr.com/spddr/index.jsp?id=360'

              base_url = 'http://www.spddr.com/spddr/'

              #获取队列中的data数据

              data = self.page_queue.get()

              #经分析,网站是通过post方法进行请求

              html = requests.post(url, headers=headers, data=data)

              tree = etree.HTML(html.text)

              #获取每条新闻的url链接

              urls = tree.xpath('//div[@class="item"]//span/a/@href')

              for u in urls:

                  # 将获取的每条新闻的url链接进行拼接,重构成新的新闻链接,并将其放入队列中

                  self.writer_queue.put(base_url + u)

                  print('*' * 30 + "正在获取第{}页地址".format(data['pages']) + '*' * 30)

              #如果队列中的已经取完了,那么就跳出while循环

              if self.page_queue.empty():

                  break

第二步,解析url:在多线程队列中获取重构的url,并进行解析,最后将解析后的信息放入线程队列

               #若两个队列中的数据都已经获取完,那么意味着信息已经爬去完毕,于是跳出循环
                if self.page_queue.empty() and self.writer_queue.empty():
                    break
                #在队列中获取重构后的新闻链接
                url = self.writer_queue.get()
                #分析网页后得出具体的新闻页面时通过get方法
                html = requests.get(url, headers=headers)
                tree = etree.HTML(html.text)
                #用xpath获取新闻标题
                title = tree.xpath('//div[@class="newsContent"]//strong/font/text()')[0].strip()
                #由于作者和日期是一起的,于是将信息全部获取
                com = tree.xpath('//tr/td[@align="center"]/div/text()')[0]
                #分析后作者和日期是用“:”分割,于是提取信息时也采用“:”分割提取
                author = ":".join(com.split()).split(':')[1]
                department = ":".join(com.split()).split(':')[3]
                time = ":".join(com.split()).split(':')[-1]
                #信息提取后重构为字典
                infos = {
                    'title': title,
                    'author': author,
                    'department': department,
                    'time': time
                }
                print("正在获取信息标题为《{}》的文章".format(title))
                #调用信息下载保存函数
                self.write_infos(infos)

第三步,下载保存信息:将解析后的信息从队列中取出,执行下载保存操作

def write_infos(self,infos):
        print(30 * '=' + "开始下载" + 30 * '=')
        #由于是多线程逐条保存信息,为了避免数据出错,在保存的时候进行开锁操作
        self.glock.acquire()
        #逐条保存信息
        self.writer.writerow(infos)
        ##由于是多线程逐条保存信息,为了避免数据出错,在保存完毕后进行锁操作
        self.glock.release()

四、全部代码如下

from lxml import etree

import requests

import csv

import random

from headers_list import headers_list

import threading

from queue import Queue

headers = {

        'User-Agent':random.choice(headers_list),

        'Cookie': 'JSESSIONID=91AFDB0A74FDB3DE1011B2E59CF99993; JSESSIONID=DD7458D1055A53D464AE8DF68400DE1F',

        'Referer': '[http://www.spddr.com/spddr/index.jsp?id=360](http://www.spddr.com/spddr/index.jsp?id=360)'

    }

#定义一个Producter类,类名通常是大写开头的单词,它继承的是threading.Thread

class Producter(threading.Thread):

    # 用init方法绑定属性,比如定义一个人的类,那你可以再定义人的属性,比如有手、有脚

    def __init__(self,page_queue,writer_queue,*args,**kwargs):

        super(Producter,self).__init__(*args,**kwargs)

        self.page_queue = page_queue

        self.writer_queue = writer_queue

    def run(self):

        while True:

            try:

                url = '[http://www.spddr.com/spddr/index.jsp?id=360](http://www.spddr.com/spddr/index.jsp?id=360)'

                base_url = '[http://www.spddr.com/spddr/](http://www.spddr.com/spddr/)'

                #获取队列中的data数据

                data = self.page_queue.get()

                #经分析,网站是通过post方法进行请求

                html = requests.post(url, headers=headers, data=data)

                tree = etree.HTML(html.text)

                #获取每条新闻的url链接

                urls = tree.xpath('//div[@class="item"]//span/a/@href')

                for u in urls:

                    # 将获取的每条新闻的url链接进行拼接,重构成新的新闻链接,并将其放入队列中

                    self.writer_queue.put(base_url + u)

                    print('*' * 30 + "正在获取第{}页地址".format(data['pages']) + '*' * 30)

                #如果队列中的已经取完了,那么就跳出while循环

                if self.page_queue.empty():

                    break

            except:

                print("解析网页出错")

#定义一个Consumer类,类名通常是大写开头的单词,它继承的是threading.Thread

class Consumer(threading.Thread):

    def __init__(self,page_queue,writer_queue,glock,writer,*args,**kwargs):

        super(Consumer,self).__init__(*args,**kwargs)

        self.page_queue = page_queue

        self.writer_queue = writer_queue

        self.glock = glock

        self.writer = writer

    def run(self):

        while True:

            try:

                #若两个队列中的数据都已经获取完,那么意味着信息已经爬去完毕,于是跳出循环

                if self.page_queue.empty() and self.writer_queue.empty():

                    break

                #在队列中获取重构后的新闻链接

                url = self.writer_queue.get()

                #分析网页后得出具体的新闻页面时通过get方法

                html = requests.get(url, headers=headers)

                tree = etree.HTML(html.text)

                #用xpath获取新闻标题

                title = tree.xpath('//div[@class="newsContent"]//strong/font/text()')[0].strip()

                #由于作者和日期是一起的,于是将信息全部获取

                com = tree.xpath('//tr/td[@align="center"]/div/text()')[0]

                #分析后作者和日期是用“:”分割,于是提取信息时也采用“:”分割提取

                author = ":".join(com.split()).split(':')[1]

                department = ":".join(com.split()).split(':')[3]

                time = ":".join(com.split()).split(':')[-1]

                #信息提取后重构为字典

                infos = {

                    'title': title,

                    'author': author,

                    'department': department,

                    'time': time

                }

                print("正在获取信息标题为《{}》的文章".format(title))

                #调用信息下载保存函数

                self.write_infos(infos)

            except:

                print("提取信息出错!")

    def write_infos(self,infos):

        print(30 * '=' + "开始下载" + 30 * '=')

        #由于是多线程逐条保存信息,为了避免数据出错,在保存的时候进行开锁操作

        self.glock.acquire()

        #逐条保存信息

        self.writer.writerow(infos)

        ##由于是多线程逐条保存信息,为了避免数据出错,在保存完毕后进行锁操作

        self.glock.release()

if __name__ == '__main__':

    # 创建FIFO队列

    page_queue = Queue(1000)

    writer_queue = Queue(1000)

    # 创建线程锁

    glock = threading.Lock()

    #csv表头信息

    head = ['title', 'author', 'department', 'time']

    #打开csv文件

    fp = open('daduhe.csv', 'a', newline='', errors='ignore', encoding='utf-8')

    #用字典方式写入表头信息

    writer = csv.DictWriter(fp, head)

    writer.writeheader()

    for i in range(1,207):

        data = {

            'nowPage': i,

            'totalpage': 206,

            'id': 360,

            'pages': i,

        }

        page_queue.put(data)

    for x in range(10):

        t = Producter(page_queue,writer_queue)#根据Producter类创建一个实例t的线程

        t.start()#开启线程

    for x in range(10):

        t = Consumer(page_queue,writer_queue,glock,writer)#根据Producter类创建一个实例t的线程

        t.start()

上一篇下一篇

猜你喜欢

热点阅读