Python 学习网络爬虫篇

Python的创世人是吉多·范罗苏姆。1989年圣诞节期间,吉多为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序作为ABC语言的一种继承。ABC是由吉多参加设计的一种教学语言。就吉多本人看来,ABC这种语言非常优美和强大,是专门为非专业程序员设计的。但是ABC语言并没有成功,究其原因,吉多认为是非开放造成的。吉多决心在Python中避免这一错误,并获取了非常好的效果,完美结合了C和其他一些语言,就这样,Python在吉多手中诞生了。

Python 特点

  1. 优点:简单、易学、速度快、免费、开源、高层语言、可移植、解释性、面向对象、可扩展、可嵌入、丰富的库、规范的代码
  2. 缺点:单行语句、运行速度慢、独特的语法(通过缩进区分语句关系)

Python应用

Python应用非常广泛,如系统编程、图形处理、数学处理、文本处理、数据库编程、网络编程、Web编程、多媒体应用、Pymo引擎、黑客编程、网络爬虫等,本篇文章就来学习一下Python的网络爬虫

Python爬虫框架

python爬虫框架有很多,如Scrapy、PySpider、Crawley、Portia、Newspaper、Beautiful Soup、Grab、Cola等,这么多框架不用学很多,学一个就可以,下面我们就来先学下一下比较热门的Scrapy框架

Scrapy框架

  • 简介

Scrapy是一个用于以一种快速、简单、可扩展的方式从网站中提取所需要数据的开源框架。用途广泛,可以用于数据挖掘、监测和自动化测试。Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitema等

  • 相关学习资料网址

scrapy官网:https://scrapy.org/
scrapy文档:https://docs.scrapy.org/en/latest/
github地址:https://github.com/scrapy/scrapy/
css选择器:http://www.w3school.com.cn/cssref/css_selectors.asp
xpath选择器:http://www.w3school.com.cn/xpath/index.asp

  • 配置环境

首先需要配置Python3的环境,mac配置非常简单,只需要在终端执行命令brew install python3,windows安装则需要到官网(http://www.python.org/download/)下载exe文件安装包, 然后再配置环境变量,这里就不多详细介绍。

Python环境配置好后,只需要在终端执行命令pip install scrapy,这样Scrapy环境就已安装配置完成

  • 项目搭建

在开始之前,建立一个新的Scrapy目录,进入到这个目录,并运行命令:

scrapy startproject helloScrapy

成功创建会有如下提示:

You can start your first spider with:
    cd helloScrapy
    scrapy genspider example example.com

这时就创建好了一个Scrapy项目, 可以按照这里的提示生成第一个spider, 第一个命令是进入到helloScrapy文件夹,第二个命令是生成模板,也就是在spiders文件夹下自动创建文件example.py。自动生成了name、allowed_domains、start_urls等属性和parse方法。name为spiders名,后面执行命令时只需要指定它就可以,allowed_domains为允许的域名访问,非该一级域名的网站都会被过滤掉,start_urls为开始爬取的网站url,该属性是一个数组可以为多个,parse方法为默认爬取到的所有数据回调,通过response对象接收,后面做处理都是通过response来搜索查询数据。简单说下项目的各个文件:

scrapy.cfg 为项目部署文件
items.py 为项目实体类文件
middlewares.py 为项目中间件文件
pipelines.py 为项目管道文件
settings.py 为项目设置配置文件
spiders文件夹用于存放Scrapy爬虫文件
example.py 是需要开发设计的爬虫文件

  • 设计items.py

这个文件存放的是Scrapy爬虫项目自定义封装的实体对象,需要爬取的元素都在这个类里面申明,这里我们以(http://quotes.toscrape.com/tag/humor/)这个网站的数据来学习,设计item.py如下:

class HelloscrapyItem(scrapy.Item):
    text = scrapy.Field()
    author = scrapy.Field()
    tags = scrapy.Field()
    description = scrapy.Field()
    pass
  • 设计example.py

需要修改allowed_domainsstart_urlsparse(self, response)方法,并添加parse_author(self, response)方法

# -*- coding: utf-8 -*-
import scrapy
from helloScrapy.items import HelloscrapyItem

class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = ['http://quotes.toscrape.com/tag/humor/']

    def parse(self, response):
        for quote in response.css('div.quote'):
            item = HelloscrapyItem()
            #用strip()方法过滤开头的\r\n\t和空格符
            item['text'] = quote.css('span.text::text').extract_first().strip()
            item['author'] = quote.css('small.author::text').extract_first().strip()
            item['tags'] = quote.css('div.tags a.tag::text').extract()

            author_page = quote.css('small.author+a::attr(href)').extract_first()
            yield scrapy.Request(url = response.urljoin(author_page), meta={'item': item}, callback=self.parse_author)

            next_page = response.css('li.next a::attr("href")').extract_first()
            if next_page is not None:
                yield scrapy.Request(response.urljoin(next_page), callback=self.parse)

    def parse_author(self, response):
        item = response.meta['item']
        item['description'] = {
            'author_born_date': response.css('.author-born-date::text').extract_first().strip(),
            'author_born_location': response.css('.author-born-location::text').extract_first().strip(),
            'authro_description': response.css('.author-born-description::text').extract_first().strip(),
        }
        yield item
        pass

parse方法中response参数是封装返回网页的所有数据,通过该参数对象可以获取任何你想要数据。

这里是通过css选择器来获取数据,也可以通过xpath选择器来获取,看个人喜好,不过推荐使用css选择器,它的语言简洁,运行速度更快。

通过浏览器的F12或对着网站上的数据鼠标右键检查,就可以定位到对应html代码区域,根据html代码可知,class=quote的div有多个,分别对应每条数据的Item,每个div下面有详细数据,所以我们可以通过response.css('div.quote')来获取到这一页面quote的数组列表,然后循环它,拿到里面的详细数据。例如我们要拿到author数据,可以看到quote div下面有一个class=author的small标签,所以我们可以通过quote.css('span.text::text').extract_first().strip()来获取数据,其中extract_first()方法是获取到第一个符合的数据,strip()方法是过滤过滤开头的\r\n\t和空格符。其它数据也是按照相同的方式去获取。

item html 预览图

我们可以看到quote div下有一个about链接进入到关于页面,通过css选择器我们可以获得这个链接地址quote.css('small.author+a::attr(href)').extract_first(),再通过response.urljoin(author_page)补全地址信息,最后通过scrapy.Request来发送一个请求,用parse_author回调方法接收,从上面的代码可以看到传递了一个meta={'item': item},目的是为了拿到关于页面的数据存储到item中再返回回来,关于页面的数据也是一样通过css选择器获取,这里就不多做解释。

about html代码预览图

最后我们会发现有下一页,如何去拿下一页数据呢?其实也很简单。通过css选择器拿到下一页的地址response.css('li.next a::attr("href")').extract_first(),然后判断存不存在下一页这个标签,表示有没有下一页,同样是通过scrapy.Request发送请求,不过这里用自身parse方法回调,因为逻辑代码都一样所以就直接可以调用自身。

简单在介绍下css选择器:
.quote 选择class=quote的所有元素
#quote 选择id=quote的所有元素
* 选择所有元素
div 选择

的所有元素
div,p 选择所有
元素和所有

元素
div p 选择

元素内部的所有

元素
div>p 选择父元素为

元素的所有

元素
div+p 选择紧接在

元素之后的所有

元素
[title] 选择带有title属性所有元素
[title=value] 选择title="value"的所有元素
以上是简单的css选择器用法,更过用法可以在前面介绍的相关学习资料网站中查看

  • 运行scrapy
crapy crawl example

通过上面命令代码执行即可。example是之前通过scrapy genspider example example.com里的值,也可以在代码中修改name属性来更改这个值。只执行这个命令不会保存任何数据,如果需要保存数据到文件中,则需要执行命令来保存

crapy crawl example -o example.json

保存到example.json文件中, 这里保存的是json格式,还可以保存'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle'这些文件格式。

  • 设置请求头

很简单,只需要添加start_requests(self)方法,去掉start_urls属性,加上headers属性。

headers = {
    'User-Agent': "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"
}

def start_requests(self):
    url = 'http://quotes.toscrape.com/tag/humor/'
    yield scrapy.Request(url, headers=self.headers, callback=self.parse)

这里header只添加了User-Agent,如果设置全局User-Agent的话可以再setting.py中添加USER_AGENT = ''即可。

  • 设置代理Proxy

首先在setting.py中添加PROXIES属性:

PROXIES = [
'http://84.47.174.197:8080',
'http://13.232.75.24:80'
]

然后再middlewares.py中添加ProxyMiddleware类:

class ProxyMiddleware(object):
    '''
    设置Proxy
    '''
    def __init__(self, ip):
        self.ip = ip

    @classmethod
    def from_crawler(cls, crawler):
        return cls(ip=crawler.settings.get('PROXIES'))

    def process_request(self, request, spider):
        ip = random.choice(self.ip)
        request.meta['proxy'] = ip

最后在setting.py中开启,注意的是helloScrapy是项目名

DOWNLOADER_MIDDLEWARES = {
   'helloScrapy.middlewares.HttpbinProxyMiddleware': 543,
}

以上三步就可以实现代理请求了,如果PROXIES有多个,则会随机切换。很多网站都会有反爬虫机制,访问太频繁,ip会被拉入黑名单,所以设置代理就很有必要。

  • 设置robots协议

setting.py中可以看到ROBOTSTXT_OBEY = True,默认是True表示遵守robots.txt的规则。robots.txt 是遵循Robot协议的一个文件,它保存在网站的服务器中,它的作用是,告诉搜索引擎爬虫,本网站哪些目录下的网页不希望你进行爬取收录。在Scrapy启动后,会在第一时间访问网站的robots.txt 文件,然后决定该网站的爬取范围。所以某些时候,我们就要将此配置项设置为False,拒绝遵守Robot协议!

以上就是网络爬虫篇的全部内容,通过上面学习,大家可以爬取大部分的网站了。如果喜欢这篇文章的内容,可以关注我的个人公众号Soaic,第一时间获取相关文章~

你可能感兴趣的:(Python 学习网络爬虫篇)