数据采集(六):scrapy爬取搜狗微信新闻+selenium模拟鼠标点击

标签: scrapy 爬虫 selenium 模拟鼠标点击
2359人阅读 评论(2) 收藏 举报
分类:

scrapy框架解析

scrapy是一个流行的爬虫框架,为什么要用它呢?前面我们已经通过xpath或beautifulsoup实现了爬虫,scrapy又有什么不同?我在初步理解了这个框架之后,感觉它很灵活,很强大。

使用beautifulsoup库我们可以很方便的实现单个爬虫,最后的结果写进了一个字典。但是当考虑一个项目中有多个爬虫,或者需要将最后的结果保存进json、csv文件,mysql数据库、mogodb数据库,或者网页是包含js的动态网页时,请使用scrapy。

下面这张图可以帮助我们宏观地把握这个框架:

这里写图片描述

绿色的箭头代表了工作过程的流向。scrapy内部有一个调度器,它根据提供的初始链接,去下载网页内容。有一些动态的网页不能直接通过request下载,比如需要点击鼠标,下拉滑块等操作,html才能加载完整,这个时候需要用到DownloaderMiddlewares,即下载器中间件。

当网页下载之后,然后会通过response交给爬虫来处理了。爬虫会返回两类内容,一类是爬取的结果,它封装在items里,items可以类比一个字典,是一个scrapy自定义的数据结构,把它交给Item Pipeline处理;一类是url链接,这是个更深层次的网页,遵循同样的流程,把它抛给调度器,重复这个过程。后面解析代码时会详细看到这个过程的实现。

SpiderMiddlewares我暂时还没怎么接触到。

Item Pipeline负责将item保存在文本文件或者数据库。

可以看到框架中每个部分分工明确,可以很方便的定制。

爬取搜狗微信新闻

下面以爬取搜狗微信新闻为例,对scrapy一探究竟。网址为搜狗微信频道。我们的目的是爬取首页所有新闻的标题、发布时间以及发布者。可以看到首页新闻仅有20条,点击“加载更多内容”之后,其余的新闻才能显现出来。

在scrapy中怎么着手呢?建立一个空的scrapy项目之后,我们会发现里面有items.py、middlewares.py、pipelines.py、settings.py、还有一个spiders文件夹。这是都是我们施展拳脚的地方,当然一些爬虫项目不会用到全部,那剩余的各种,我们都不用管,交给框架处理就好。

确定爬取字段

首先明确爬取的字段—title、time、post_user。这个在items.py中指定。

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class WxnewsItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()

    title=scrapy.Field()
    time=scrapy.Field()
    post_user=scrapy.Field()

编写爬虫

然后在spiders文件夹中建立一个py文件,比如wxnews_spider.py,文件名字是无所谓的。在py文件中,要写一个符合规范的类,比如:

# -*- coding:utf-8 -*-
import scrapy
from wxnews.items import WxnewsItem


class WxnewsSpider(scrapy.Spider):
    name = 'wxnews'
    start_urls = [
        'http://weixin.sogou.com'
    ]

    def parse(self, response):
        news_href_list=response.xpath('//ul[@class="news-list"]/li/div[2]/h3/a/@href')
        #print response.url
        for href in news_href_list:
            url=response.urljoin(href.extract())
            yield scrapy.Request(url,callback=self.parse_news)


    def parse_news(self, response):
        title=response.xpath('.//div[@id="page-content"]/div/h2/text()').extract_first()
        time=response.xpath('.//div[@id="page-content"]/div/div[1]/em[1]/text()').extract_first()
        post_user=response.xpath('.//a[@id="post-user"]/text()').extract_first()

        #print title.strip()
        #print time.strip()
        #print post_user.strip()

        #print " "

        #yield {'title':title,
        #      'time':time,
        #     'post_user':post_user
        # }


        news=WxnewsItem()
        news['title']=title.strip()
        news['time']=time
        news['post_user']=post_user

        yield news

解释一下上述代码,首先需要导入item类,然后写一个爬虫类体。它是一个派生类,name是爬虫名字、start_url是爬虫开始的url,都是从父类继承的属性。parse也是继承函数,程序会默认调用。在程序中我们也写了一个自定义的解析函数parse_news。它和parse相同,都接受response对象。都可通过yield抛出两类对象,一类是item,一类就是request。request通过callback指定了对获取后的网页内容采用何种解析方法,比如下句:

yield scrapy.Request(url,callback=self.parse_news)

yield类比return,不同之处在于执行yield之后会继续执行函数体中后续代码。

可以看到在parse函数中,一样是通过xpath定位并解析出想要的元素。

将结果写入文件

到这一步,我们就该考虑怎么把结果保存进文本文件。如果是保存到csv文件或json文件中,那么很方便的是,我们在pipelines中可以什么也不用写,即可完成这一功能。只需要在命令行中执行爬虫时,指定一个文件。如下所示

scrapy crawl wxnews -o result.csv

wxnews是爬虫名字,result.csv是结果文件。

获取需要将结果写入数据库,那么需要在pipelines中写一个自定义的process_item函数,包括怎么连接数据库,和对数据库增删改查的操作。

编写下载中间件,模拟鼠标点击

在本例中,也并非最简单的例子,因为,我们需要模拟鼠标点击的动作,使网页加载出完整内容。我们需要在middlewares.py的process_request函数写这一功能。它涉及到下载这一步骤,接受request,返回response,所以叫下载中间件。详细代码如下:

#-*- coding:utf-8 -*-
from selenium import webdriver
from scrapy.http import HtmlResponse
import time
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from random import choice

class SeleniumMiddleware(object):
    def process_request(self, request, spider):
        click_page_url="http://weixin.sogou.com"
        if request.url==click_page_url:
            driver = webdriver.PhantomJS()
            try:
                driver.get(request.url)
                driver.implicitly_wait(3)
                time.sleep(5)

                look_more=".//div[@class='jzgd']/a"
                for n in range(4):
                    driver.find_element_by_xpath(look_more).click()  # 数据由js来控制,点击后加载数据
                    time.sleep(5)

                true_page = driver.page_source
                driver.close()

                return HtmlResponse(request.url,body = true_page,encoding = 'utf-8',request = request,)

            except:
                print "get news data failed"
        else:
            return None

上述代码引入一个模块叫selenium,它用来模拟浏览器以及鼠标的各种行为。这里的鼠标行为即点击某个元素,比如这里是“look_more”。PhantomJS叫无头浏览器,它是selenium里的,当然selenium里可以模拟很多浏览器,比如chrome,火狐等。无头浏览器不同点是它不需要渲染出花花绿绿的页面,名字起的很到位。从代码中可以看到,模拟了浏览器请求页面以及超时等待等操作。

爬取结果

所讲的例子包含的工作量就是这些。运行之后,看看我们成果:
这里写图片描述

总共获取约100条数据,因为每页20条新闻,鼠标点击4次,首页新闻可全部加载完。

查看评论

创业,我为什么失败??? http://www.vchome.net

2002年11月至2003年5月,这段时间是阿蒙(http://www.vchome.net)的第一次创业,显然是失败的,深圳是个充满诱惑同时也充满陷阱的城市,年轻人需要这样的城市,创业者更需要这样的...
  • harrymeng
  • harrymeng
  • 2003-07-02 16:12:00
  • 4558

python中scrapy点击按钮

最初遇到的问题的是在用scrapy爬取微博时需要按照指定关键字来爬取特定微博,主要还是解决需要输入关键字然后点击搜索按钮的问题。于是: 首先, 找了scrapy的官方文档,发现有FormRequest...
  • wuzqChom
  • wuzqChom
  • 2016-09-27 08:59:25
  • 3263

python selenium的模拟点击,模拟滑动等操作

http://blog.csdn.net/nhudx061/article/details/43601065 #coding:utf-8 from selenium import webdriver...
  • u012745777
  • u012745777
  • 2016-01-12 21:26:51
  • 15971

python爬虫 scrapy框架 知乎zhihu 模拟登陆

这几天了解了一下scrapy框架,想爬取知乎用户信息来练习一下。然后发现在进入每个用户的followers和followees网页时,需要用户登录,否则无法爬取。 上网搜索了一下资料,网上说是要将用户...
  • zhm9484
  • zhm9484
  • 2015-08-11 17:00:33
  • 2636

selenium 模拟键盘及鼠标事件

1.模拟键盘事件 Actions action = new Actions(driver); action.keyDown(Keys.CONTROL); action.keyDown(Key...
  • qiaotong1
  • qiaotong1
  • 2016-03-10 17:23:38
  • 5970

Selenium的模拟鼠标和键盘演示

鼠标动作需要导入包:from selenium.webdriver.common.action_chains import ActionChains具体写法:ActionChains(wzj).con...
  • qq_22795513
  • qq_22795513
  • 2016-11-15 15:36:49
  • 922

python scrapy爬取微信公众号文章的爬虫

微信公众号文章爬取器 从搜狗微信公众号入口爬取公众号新闻列表 支持爬取新闻标题、Icon、作者、时间等 支持文章内容图片下载替换 支持去掉含有二维码的图片 支持去掉带有超链接的html 标签...
  • humanbeng
  • humanbeng
  • 2017-09-07 10:35:53
  • 2508

scrapy爬取某网站,模拟登陆过程中遇到的那些坑

最近接触scrapy,爬取了几个网站,用着还挺顺手的. 前几天,一个做业务的同事让我帮他爬取一个网站上的用户信息,我就满口承诺下来了.毕竟,通过前几次的爬取,已经自信心爆棚了(从此入坑). ...
  • amaomao123
  • amaomao123
  • 2016-09-12 11:13:40
  • 11201

scrapy爬取动态分页内容

难点:1) scrapy如何动态加载所有“下一页”:要知道scrapy本身是不支持js操作的。2) 如何确保页面内容加载完成后再进行爬取:由于内容是通过js加载的,如果不加控制,很可能出现爬到空页...
  • elecjack
  • elecjack
  • 2016-05-29 16:12:12
  • 10365

Scrapy如何实现抓取动态网页

作者:张昌昌          动态网页指几种可能:1)需要用户交互,如常见的登录操作;2)网页通过JS / AJAX动态生成,如一个html里有,通过JS生成aaa;3)点击输入关键字后进...
  • zcc_0015
  • zcc_0015
  • 2016-03-06 18:07:37
  • 13112
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 15万+
    积分: 2238
    排名: 2万+
    About Me
    博客专栏
    最新评论