【评论文本分类】1.爬取评论数据

环境配置

  • Ubuntu 16.04
  • Python 3.5

技术框架

  • Scrapy
  • Selenium
  • PhantomJS

需求目标

对网址http://liuyan.cjn.cn/index.html进行数据爬取

本文爬虫有三层爬取,爬取结构层次如图所示,

  • 主页面

mark

  • 列表页面,需要利用selenium+phantomJS模拟点击加载更多按钮

mark

  • 详情页面

mark

  • 主页面中的红框中的各区(功能区)政府部门法检及其他单位等作为一级类保存,然后依次爬取一级类中各个分类
  • 进入到列表页面,因为此页面是动态加载,并且是简介列表,因此需要加载完所有列表进入到详情页面。
  • 进入到详情页面,爬取相应内容。

设计方案

动态爬取数据一般有两种方法

  • 分析包,构造Request
  • 通过模拟浏览器行为加载页面

通过尝试,第一种方法对于此网站不适合,采用第二种方法。

采用Scrapy+Selenium+PhantomJS来进行动态网页的爬取。

Selenium

Selenium是一个自动化测试工具,本文用到的是其Webdriver,用其来操作浏览器,可以操作多种主流浏览器,如Chrome,Firefox等,下文中的PhantomJS是一种无界面的浏览器。

PhantomJS

PhantomJS是一个无界面浏览器,提供JavaScript接口。通过这个工具,可以进行页面的加载、解析、操作等。

爬取方案

  • 先爬取主页面各个主类(如各区(功能区)政府部门等)下的子类链接,如(江岸区、江夏区等)
  • 按照先前爬取的子类链接依次打开跳转到列表界面,然后利用Selenium+PhantomJS模拟浏览器动态加载完全部列表,解析出所有列表的链接,跳转到详情页面
  • 进入到详情页面,解析所要提取的内容

详细步骤

安装Scrapy

sudo pip3 install scrapy

安装PhantomJS

  1. 安装PhantomJS
sudo apt-get install phantomjs
  1. apt-get会安装不完整,需要安装以下
sudo apt-get install nodejs
sudo apt-get install nodejs-legacy
sudo apt-get install npm
sudo npm -g install phantomjs-prebuilt

安装Selenium

sudo pip3 install selenium

使用Scrapy

  1. 创建新工程
scrapy startproject xxxx
  1. 编辑items.py文件
from scrapy import Item
from scrapy import Field


class MessageboardspiderItem(Item):
    # define the fields for your item here like:

    dir_name=Field()
    url=Field()
    title=Field()
    domain=Field()
    type=Field()
    content=Field()
  1. 编写Spider

流程:

  • 先通过scrapy爬取主页面上的所有子分类链接,

  • 然后依次利用PhantomJS模拟点击列表页面加载更多按钮,动态加载所有列表项,然后保存网页源码,抽取出其中的列表项的链接,进入详情页面

    此两过程的代码都在parse(self,response)方法中

  • 通过parse_detailed_remark(self,response)方法,解析出需要的内容

【注】目前版本爬取主页面上不同的主类需要手动改动baseDirself.start_urls

import os
import stat
import scrapy
import time
from selenium import webdriver
from scrapy.selector import Selector
from scrapy.http import HtmlResponse
from messageBoardSpider.items import MessageboardspiderItem


baseDir = '/home/t/dataset/msgBoard/department/'    #爬取不同主分类,需要手动改动
baseUrl='http://liuyan.cjn.cn'
global subclass_name
global brower
class DistrictSpider(scrapy.Spider):
    name='spider'
    def __init__(self):
        global brower
        self.start_urls=['http://liuyan.cjn.cn/forum/list?fid=4']   #爬取不同主分类,需要手动改动
        brower=webdriver.PhantomJS()    #创建PhantomJS浏览器

    def parse(self,response):
        global brower
        global subclass_name

        subclasses=response.xpath('/html/body/div[7]/ul/li/b/a') #解析出所有子分类
        for subclass in subclasses: #逐条解析子分类

            subclass_name=subclass.xpath('text()').extract() #解析

            #make district directory
            self.mkdirs(baseDir+subclass_name[0])

            #extrat new link
                link=subclass.xpath('@href').extract()  #解析出子类的链接
            #joint link
            link=str(baseUrl+link[0].split('..')[1])    #拼接链接

            brower.get(link)    #利用PhantomJS打开链接
            #进行动态解析,直到没有'加载更多'按钮之后停止
            while True:
                try:
                    more=brower.find_element_by_id('show_more') #找到'加载更多'按钮
                    time.sleep(0.5)
                    more.click()
                    time.sleep(0.5)
                except:
                    with open(baseDir+subclass_name[0]+'/web_page.txt','w',encoding='utf-8') as f:
                        f.write(brower.page_source)
                    print('ending')
                    break


            #对加载完后的源码进行解析,解析出列表标题
            items=brower.find_elements_by_xpath('//*[@id="list_content"]/li/h2/b/a')    
            for item in items:
               #解析出列表标题链接
                title_link=item.get_attribute('href')
                print(title_link+'.........')
                yield scrapy.Request(url=title_link,callback=self.parse_detailed_remark)

    #解析详情页面
    def parse_detailed_remark(self,response):

        global subclass_name
        item=MessageboardspiderItem()
        item['dir_name']=subclass_name[0]
        item['url']=response.url
        item['title']=response.xpath('/html/body/div[6]/h2/b/text()').extract()
        item['domain']=response.xpath('/html/body/div[6]/h3/em[1]/a/text()').extract()
        item['type']=response.xpath('/html/body/div[6]/h3/em[2]/a/text()').extract()
        item['content']=response.xpath('//*[@id="zoom"]/text()').extract()
        yield item


    def mkdirs(self,path):

        if not os.path.exists(path):
            os.makedirs(path)
            os.chmod(path,stat.S_IRWXU|stat.S_IRWXG|stat.S_IRWXO)
  1. 编写pipelines
import json
import codecs
baseDir = '/home/t/dataset/msgBoard/department/'

class DistrictPipeline(object):
    def process_item(self, item, spider):
        with codecs.open(baseDir+item['dir_name']+'/data.json','a+',encoding='utf-8') as f:
            self.file=f
            line=json.dumps(dict(item),ensure_ascii=False)+'\n'
            self.file.write(line)

        return item

猜你喜欢

转载自blog.csdn.net/tiweeny/article/details/78913589