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

本文介绍Scrapy爬虫框架的特点及应用场景,并通过爬取搜狗微信新闻的实际案例,演示如何搭建项目、编写爬虫代码、使用下载中间件模拟鼠标点击加载动态内容等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

第1关:Scrapy是一个强大的Python爬虫框架,它能够自动化抓取网页数据并整理成结构化的信息。如果你想将爬取的数据存储到MongoDB数据库中,你可以按照以下步骤操作: 1. **安装依赖**: - 安装Scrapy本身:`pip install scrapy` - 安装Scrapy-MongoDB适配器:`pip install scrapy-mongodb` 2. **创建Scrapy项目**: 使用命令行创建一个新的Scrapy项目:`scrapy startproject my_crawler` 3. **配置settings.py**: 在项目的`settings.py`文件中,添加MongoDB的连接设置: ```python MONGO_URI = 'mongodb://localhost:27017/mydatabase' ITEM_PIPELINES = {'my_crawler.pipelines.MongoDBPipeline': 300} ``` 4. **编写管道(Pipeline)**: 创建一个名为`MongoDBPipeline.py`的文件,这是用于处理数据并将其保存到MongoDB的地方。这里你会使用Scrapy的Item Pipeline机制,如示例所示: ```python from pymongo import MongoClient from scrapy.item import Item, Field class MyItem(Item): # 定义你要存储在MongoDB中的字段 class MongoDBPipeline: def __init__(self): self.client = MongoClient(MONGO_URI) self.collection = self.client['mydatabase']['mycollection'] def process_item(self, item, spider): self.collection.insert_one(dict(item)) return item ``` 5. **定义Spider**: 在spiders目录下,创建一个Spider,比如`myspider.py`,并在其中定义下载和解析规则。采集到的数据会自动通过Pipeline传入MongoDB。 6. **运行爬虫**: 最后,在命令行运行你的爬虫:`scrapy crawl myspider` 完成上述步骤后,Scrapy会在每次请求成功后将数据存储到指定的MongoDB集合中。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值