关闭

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

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

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次,首页新闻可全部加载完。

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

python中scrapy点击按钮

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

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

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

利用微信搜索抓取公众号文章

我喜欢看微信公众号里的技术文章,但是总是有一些鸡汤文阻碍我的实现,我是怎么让机器帮我自动摆脱鸡汤文的呢?接下来的几个章节讲述我的解决方案,让你感兴趣的文章扑面而来,无关的鸡汤文随风而去。本章节先将怎么...
  • bjash
  • bjash
  • 2017-03-01 10:05
  • 1732

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

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

Scrapy+splash抓取js生成的数据

一、python、lua、js间参数传递原理 抓取过程是python调用splash的lua脚本,lua中又调用了js代码实现相关页面内容的提取及js动作的模拟。在python中通过meta的spl...
  • zcc_0015
  • zcc_0015
  • 2016-03-17 17:16
  • 4623

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

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

Android开发——Accessibility机制实现模拟点击(微信自动抢红包实现)

1.何为Accessibility机制? 许多Android使用者因为各种情况导致他们要以不同的方式与手机交互。对于那些由于视力、听力或其它身体原因导致不能方便使用Android智能手机的用户,A...
  • SEU_Calvin
  • SEU_Calvin
  • 2016-07-14 20:46
  • 24517

使用电脑模拟微信内置浏览器

转载至 最近在弄微信开发,需要微信请求,其实很好改 只要把请求头改了就好了。 浏览器呢 就使用 chrome 我在这使用360极速浏览器了。 首先...
  • lu1005287365
  • lu1005287365
  • 2016-10-09 16:58
  • 18190

Android开发——Accessibility机制实现模拟点击(微信自动抢红包实现)

1. 何为Accessibility机制许多Android使用者因为各种情况导致他们要以不同的方式与手机交互。对于那些由于视力、听力或其它身体原因导致不能方便使用Android智能手机的用户,Andr...
  • chaishen10000
  • chaishen10000
  • 2016-11-10 21:48
  • 1400

selenium 模拟键盘及鼠标事件

1.模拟键盘事件 Actions action = new Actions(driver); action.keyDown(Keys.CONTROL); action.keyDown(Key...
  • qiaotong1
  • qiaotong1
  • 2016-03-10 17:23
  • 5253
    个人资料
    • 访问:113111次
    • 积分:1853
    • 等级:
    • 排名:千里之外
    • 原创:73篇
    • 转载:0篇
    • 译文:2篇
    • 评论:84条
    About Me
    博客专栏
    最新评论