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

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

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
当使用 ScrapySelenium 结合进行网页动态加载数据的爬取时,可以按照以下步骤进行操作: 1. 安装所需库:确保已安装 ScrapySelenium 库。可以使用以下命令进行安装: ``` pip install scrapy pip install selenium ``` 2. 创建 Scrapy 项目:使用以下命令创建一个新的 Scrapy 项目: ``` scrapy startproject dynamic_scraping ``` 3. 创建 Spider:进入项目目录,并使用以下命令创建一个新的 Spider: ``` cd dynamic_scraping scrapy genspider example example.com ``` 这将在 `spiders` 目录下创建一个名为 `example.py` 的 Spider。 4. 配置 Spider:打开 `example.py` 文件,并按照以下示例进行配置: ```python import scrapy from scrapy_selenium import SeleniumRequest from scrapy.selector import Selector class ExampleSpider(scrapy.Spider): name = 'example' allowed_domains = ['example.com'] def start_requests(self): yield SeleniumRequest( url='https://example.com', callback=self.parse ) def parse(self, response): sel = Selector(response) # 在这里使用 XPath 或 CSS 选择器提取动态加载的数据 # 示例:提取标题 title = sel.xpath('//h1/text()').get() print(title) ``` 在上面的示例中,我们使用了 `SeleniumRequest` 替代了普通的 `scrapy.Request`,这使得 Scrapy 可以使用 Selenium 来处理动态加载的内容。 5. 配置 Selenium:为了使用 Selenium,你需要配置相关的 Web 驱动程序。根据你使用的浏览器,下载并安装相应的驱动程序,并将其添加到系统的 PATH 环境变量中。 6. 运行 Spider:使用以下命令运行 Spider: ``` scrapy crawl example ``` 这将启动爬取过程,并在控制台上打印出提取的动态加载数据。 通过以上步骤,你可以使用 ScrapySelenium 结合进行爬取动态加载数据的操作。你可以根据实际需求修改 Spider 中的代码来提取所需的数据,并将其保存到文件或数据库中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值