Python爬虫案例与实战:Scrapy框架与Selenium

Python爬虫案例与实战:Scrapy框架与Selenium

1.4.1爬虫框架:Scrapy

按照官方的说法,Scrapy是一个“为了爬取网站数据,提取结构性数据而编写的Python应用框架,可以应用在包括数据挖掘、信息处理或存储历史数据等各种程序中”。Scrapy最初是为了网页抓取而设计的,也可以应用在获取API所返回的数据或者通用的网络爬虫开发之中。作为一个爬虫框架,可以根据自己的需求十分方便地使用 Scrapy编写出自己的爬虫程序。毕竟要从使用 Requests(请求)访问URL开始编写,把网页解析、元素定位等功能一行行写进去,再编写爬虫的循环抓取策略和数据处理机制等其他功能,这些流程做下来,工作量其实也是不小的。使用特定的框架有助于更高效地定制爬虫程序。作为可能是最流行的Python爬虫框架,掌握 Scrapy爬虫编写是在爬虫开发中迈出的重要一步。从构件上看,Scrapy这个爬虫框架主要由以下组件组成。
引擎(Scrapy):用来处理整个系统的数据流处理,触发事务,是框架的核心。
调度器(Scheduler):用来接收引擎发过来的请求,将请求放入队列中,并在引擎再次请求的时候返回。它决定下一个要抓取的网址,同时担负着网址去重这一项重要工作。
下载器(Downloader):用于下载网页内容,并将网页内容返回给爬虫。下载器的基础是twisted,一个Python网络引擎框架。
爬虫(Spiders):用于从特定的网页中提取自己需要的信息,即 Scrapy 中所谓的实体(Item)。也可以从中提取出链接,让 Scrapy继续抓取下一个页面。
管道(Pipeline):负责处理爬虫从网页中抽取的实体,主要的功能是持久化信息验证实体的有效性、清洗信息等。
下载器中间件(Downloader Middlewares):Scrapy 引擎和下载器之间的框架,主要处理 Scrapy引擎与下载器之间的请求及响应。
爬虫中间件(Spider Middlewares):Scrapy 引擎和爬虫之间的框架,主要工作是处理爬虫的响应输入和请求输出。
调度中间件(Scheduler Middewares):Scrapy 引擎和调度之间的中间件,从Scrapy 引擎发送到调度的请求和响应。
它们之间的关系示意如图1-6所示。
在这里插入图片描述
可以通过pip十分轻松地安装Scrapy,安装 Scrapy首先要使用以下命令安装lxml库:pip install lxml。
如果已经安装1xml,那就可以直接安装Scrapy:pip install scrapy。在终端中执行命令(后面的网址可以是其他域名,如 www.baidu.com):scrapy shell www.douban.com。
可以看到 Scrapy shell的反馈,如图1-7所示。
在这里插入图片描述
为了在终端中创建一个Scrapy项目,首先进入自己想要存放项目的目录下,也可以直接新建一个目录(文件夹),这里在终端中使用命令创建一个新目录并进入:

mkdir newcrawler
cd newcrawler/

之后执行 Scrapy框架的对应命令:

scrapy startproject newcrawler

会发现目录下多出了一个新的名为newcrawler的目录。其中items.py定义了爬虫的
“实体”类,middlewares.py是中间件文件,pipelines.py是管道文件,spiders文件夹下是具体的爬虫,scrapy.cfg则是爬虫的配置文件。然后执行新建爬虫的命令:scrapy genspider DoubanSpider douban.com
输出为:

Created spider'DoubanSpider'using template'basic'

不难发现,genspider命令就是创建一个名为 DoubanSpider的新爬虫脚本,这个爬虫对应的域名为douban.com。在输出中发现了一个名为basic的模板,这其实是Scrapy的爬虫模板。进人 DoubanSpider.py 中查看(见图1-8)。
在这里插入图片描述
可见它继承了scrapy.Spider类,其中还有一些类属性和方法。name用来标识爬虫。它在项目中是唯一的,每一个爬虫有一个独特的name。parse是一个处理response的方法,在 Scrapy 中,response由每个request下载生成。作为parse方法的参数,response是一个TextResponse的实例,其中保存了页面的内容。start_urls列表是一个代替 start_requests()方法的捷径,所谓的 start_requests方法,顾名思义,其任务就是从url生成scrapy.Request对象,作为爬虫的初始请求。之后会遇到的 Scrapy爬虫基本都有着类似这样的结构。
为了定制Scrapy爬虫,要根据自己的需求定义不同的Item,例如,创建一个针对页面中所有正文文字的爬虫,将Items.py 中的内容改写为:

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

之后编写DoubanSpider.py:

# -*-coding: utf-8 -*-
import scrapy 
from scrapy. selector import Selector 
from .. items import TextItem 

class DoubanspiderSpider(scrapy. Spider):
    name = ' DoubanSpider' 
    allowed_urls = ['https://www.douban.com/']
    start_urls = [' https://www. douban. com/']

    def parse(self, response):
        item = TextItem()
        hitext = response. xpath('//a/text()'). extract()
        print("Text is"+ ''. join(hltext))
        item[' text'] = hitext 
        return item

这个爬虫会先进人start_urls列表中的页面(在这个例子中就是豆瓣网的首页),收集信息完毕后就会停止。response.xpath(‘//a/text()’).extract()这行语句将从response(其中保存着网页信息)中使用 xpath语句抽取出所有“a”标签的文字内容(text)。下一句会将它们逐一打印。
运行爬虫的命令是:

scrapy crawl spidername

其中,spidername是爬虫的名称,即爬虫类中的name属性。
程序运行并进行爬取后,可以看到 Scrapy爬取时的Log输出,通过 Log内容可以看到爬取的进度以及结果。由于爬取目标网站的一些反爬措施,如限制USER_AGENT,因此在允信之前可能还需要在 setting.py 中修改一些配置,如 USER_AGENT等。
值得一提的是,除了简单的 scrapy.Spider,Scrapy还提供了诸如 CrawlSpider、csvfeed等爬虫模板,其中CrawlSpider是最为常用的。另外,Scrapy的Pipeline 和Middleware都支持扩展,配合主爬虫类使用将取得很流畅的抓取和调试体验。
当然,Python爬虫框架当然不止 Scrapy一种,在其他诸多爬虫框架中,还值得一提的是PySpider、Portia等。PySpider 是一个“国产”的框架,由国内开发者编写,拥有一个可视化的Web界面来编写调试脚本,使得用户可以进行诸多其他操作,如执行或停止程序、监控执行状态、查看活动历史等。除了Python,Java 语言也常常用于爬虫的开发,比较常见的爬虫框架包括 Nutch、Heritrix、WebMagic、Gecco等。爬虫框架流行的原因,就在于开发者需要“多、快、好、省”地完成一些任务,如爬虫的 URL管理、线程池之类的模块,如果自己从零做起,势必需要一段时间的实验、调试和修改。爬虫框架将一些“底层”的事务预先做好,开发者只需要将注意力放在爬虫本身的业务逻辑和功能开发上。有兴趣的读者可以继续了解如 PySpider这样的新框架。

1.4.2模拟浏览器:Selenium

我们知道,网页会使用JavaScript加载数据,对应于这种模式,可以通过分析数据接口来进行直接抓取,这种方式需要对网页的内容、格式和JavaScript代码有所研究才能顺利完成。但有时还会碰到另外一些页面,这些页面同样使用AJAX 技术,但是其页面结构比较复杂,很多网页中的关键数据由AJAX 获得,而页面元素本身也使用JavaScript 来添加或修改,甚至于人们感兴趣的内容在原始页面中并不出现,需要进行一定的用户交互(如不断下拉滚动条)才会显示。对于这种情况,为了方便,就会考虑使用模拟浏览器的方法来进行抓取,而不是通过“逆向工程”去分析AJAX 接口,使用模拟浏览器的方法,特点是普适性强,开发耗时短,抓取耗时长(模拟浏览器的性能问题始终令人忧虑),使用分析AJAX的方法,特点则刚好与模拟浏览器相反,甚至在同一个网站、同一个类别中的不同网页上,AJAX数据的具体访问信息都有差别,因此开发过程投人的时间和精力成本是比较大的。如果碰到页面结构相对复杂或者AJAX数据分析比较困难(如数据经过加密)的情况,就需要考虑使用浏览器模拟的方式了。
在Python模拟浏览器进行数据抓取方面,Selenium永远是绕不过去的一个坎。Selenium(意为化学元素“硒”)是浏览器自动化工具,在设计之初是为了进行浏览器的功能测试。Selenium的作用,直观地说,就是使得操纵浏览器进行一些类似普通用户的操作成为可能,如访问某个地址、判断网页状态、单击网页中的某个元素(按钮)等。使用 Selenium来操控浏览器进行的数据抓取其实已经不能算是一种“爬虫”程序,一般谈到爬虫,自然想到的是独立于浏览器之外的程序,但无论如何,这种方法有助于解决一些比较复杂的网页抓取任务,由于直接使用了浏览器,麻烦的AJAX数据和JavaScript动态页面一般都已经渲染完成,利用一些函数,完全可以做到随心所欲地抓取,加之开发流程也比较简单,因此有必要进行基本的介绍。
Selenium本身只是个工具,而不是一个具体的浏览器,但是Selenium 支持包括 Chrome和 Firefox在内的主流浏览器。为了在Python 中使用 Selenium,需要安装selenium库(仍然通过pip install selenium的方式进行安装)。完成安装后,为了使用特定的浏览器,可能需要下载对应的驱动。将下载到的文件放在某个路径下。并在程序中指明该路径即可。如果想避免每次配置路径的麻烦,可以将该路径设置为环境变量,这里就不再赘述了。
通过一个访问百度新闻站点的例子来引入 selenium库,代码如下:

from selenium import webdriver 
import time 
browser = webdriver.Chrome('yourchromedriverpath'#如"/home/zyang/chromedriver'
browser.get('http:www.baidu.com'print(browser.title)
#输出:“百度一下,你就知道”
browser.find_element_by_name("tj_trnews".click()#单击“新闻”  browser.find_element_by_class_name('hdline0').click()#单击头条
print(browser.current_url)
#输出:http://news.baidu.com/
time.sleep(10)
browser.quit()
#退出

运行上面的代码,会看到 Chrome 程序被打开,浏览器访问了百度首页,然后跳转到了百度新闻页面,之后又选择了该页面的第一个头条新闻,从而打开了新的新闻页。一段时间后,浏览器关闭并退出。控制台会输出“百度一下,你就知道”(对应browser.title)和http://
news.baidu.com/(对应browser.current_url)。这无疑是一个好消息,如果能获取对浏览器的控制权,那么爬取某一部分的内容会变得如臂使指。
另外,selenium库能够提供实时网页源码,这使得通过结合 Selenium 和 BeautifulSoup
(以及其他上文所述的网页元素解析方法)成为可能,如果对 selenium库自带的元素定位API不甚满意,那么这会是一个非常好的选择。总的来说,使用 selenium库的主要步骤如下。
创建浏览器对象,即使用类似下面的语句:

from selenium import webdriver 
browser-webdriver.Chrome()

访问页面,主要使用 browser.get方法,传入目标网页地址。
定位网页元素,可以使用 selenium自带的元素查找API,即

element-browser.find_element_by_id("id")
element-browser.find_element_by_name("name")
element-browser.find_element_by_xpath("xpath")
element-browser.find_element_by_link_text('link_text'#...

还可以使用browser,page_source 获取当前网页源码并使用 BeautifulSoup等网页解析工具定位:

from selenium import webdriver 
from bs4 import BeautifulSoup 

browser = webdriver.Chrome('yourchromedriverpath')
url ='https://www.douban.com'browser.get(url)
ht = BeautifulSoup(browser.page_source,'lxml'for one in ht.find_all('a',class_='title'):
    print(one.text)井输出:
#52倍人生--戴锦华大师电影课
......
#觉知即新生--终止童年创伤的心理修复课

网页交互,对元素进行输入、选择等操作。如访问豆瓣并搜索某一关键字(效果见图1-9)的代码如下。

from selenium import webdriver 
import time 
from selenium.webdriver.common.by import By browser = webdriver.Chrome('yourchromedriverpath')
browser.get('http://www.douban.com')
time.sleep(1)
search_box = browser.find_element(By.NAME,'q')
search_box.send_keys('')
button = browser.find element(By.CLASS NAME'bn')
button.click()

在这里插入图片描述
在导航(窗口中的前进与后退)方面,主要使用 browser.back 和browser.forward两个函数。
获取元素属性。可供使用的函数方法很多,例如:

#one应该是一个selenium.,webdriver.remote.webelement.WebElement类的对象
one,text 
one.get_attribute('href')
one.tag name 
one.id

之前曾对 Selenium的基本使用做过简单的说明,有了网站交互(而不是典型爬虫程序避开浏览器界面的策略)还能够完成很多测试工作,如找出异常表单、HTML排版错误、页面交互问题。
里程碑小结
之前介绍了Python 爬虫的一些基础知识,使读者对Python爬虫有一个初步的认识。主要介绍了Python语言的一些基本特性,以及Python解决爬虫问题的一些基本流程,如请求、下载、解析、数据存储;同时还介绍了一些爬虫常用的工具,如 Requests、XPath、Python解析JSON、正则表达式、BeautifulSoup、Selenium、Python操作文件等。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值