一、 下载scrapy
windows:
方法一: 下载Anacoda, 在Anacoda中下载scrapy
方法二: 直接pip install scrapy;期间部分依赖的包可能会报错,此时需要我们手动去网上下载对应包的whl,pip install之后,再重新pip install scrapy
linux:
一般会自动安装相关依赖的包
sudo pip install scrapy
tips: 以下所有代码以ubuntu18.04系统为准
二、创建scrapy项目,初始化一个爬虫
# 此处ALiHR为项目目录名
***@ubuntu:~/Desktop/Python/MyScrapy$ scrapy startproject Tencent
New Scrapy project 'ALiHR', using template directory '/home/***/.local/lib/python3.6/site-packages/scrapy/templates/project', created in: /home/***/Desktop/Python/MyScrapy/ALiHR
# 以下两句代码提示我们,可以通过下面的操作,初始化一个爬虫模板
# example 代表爬虫文件及爬虫的名字
# example.com 数据类型为列表,允许爬虫后续爬取的域名;不在此域名列表之内的url请求会被略过
You can start your first spider with:
cd Tencent
scrapy genspider example example.com
创建项目完成后, 我们按照终端的提示信息,创建爬虫文件
在这里,以爬取阿里的招聘信息为例,进行以下所有操作
***@ubuntu:~/Desktop/Python/MyScrapy$ cd Tencent
***@ubuntu:~/Desktop/Python/MyScrapy/ALiHR$ scrapy genspider tencent_post hr.tencent.com
Created spider 'alihr' using template 'basic' in module:
Tencent.spiders.tencent_post
爬虫文件创建完成后,我们的项目目录会是以下结构
├── Tencent
│ ├── __init__.py
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ └── settings.cpython-36.pyc
│ ├── settings.py
│ └── spiders
│ ├── tencent_post.py
│ ├── __init__.py
│ └── __pycache__
│ └── __init__.cpython-36.pyc
└── scrapy.cfg
__pycache__: python的自带文件,默认隐藏,不必理会
items.py:在此处定义爬取到的数据的字段(职位名称、职位类别、工作地点等)
middleware.py: 在此处定义爬虫中间件
pipelines.py:数据处理管道
settings.py: 配置文件
alihr.py: 我们的爬虫文件
三、爬虫的相关配置
日志记录及默认协议
在终端运行爬虫的时候,终端会打印很多INFO级别的信息,大多信息我们并不想看到,可以做以下设置
# 在项目目录中,找到settings.py文件,添加以下代码
LOG_LEVEL = 'WARNING'
# robots协议,一般为网站自定义的可爬取的范围,scrapy默认遵循该协议
# scrapy爬虫启动后,会先请求网站的robots.txt文件,遵循其规定
# 一般情况下,我们可以直接将该值设置为False即可不遵循协议
# 该值为True, 可能会出现报错:Forbidden by robots.txt
ROBOTSTXT_OBEY = True
用户代理
用户代理(User-Agent)的作用是伪装我们的爬虫为浏览器请求,达到反反爬的目的。
tips:当然,反反爬不仅仅需要这一种手段
# Crawl responsibly by identifying yourself (and your website) on the user-agent
# 在settings.py文件中,找到USER_AGENT字段,更改其值为浏览器的用户代理
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 ' \
'(KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36'
四、开始爬虫
我们以招聘网站为例,简单介绍下scrapy的整体应用
数据分析及items.py
分析网页信息,我们需要的信息分别是:职位名称、类别、工作地点、招聘人数、发布时间
点击一条招聘信息,我们发现还有数据:工作职责、要求
接下来,需要操作items.py文件
items.py
import scrapy
class TencentItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field()
type = scrapy.Field()
number = scrapy.Field()
position = scrapy.Field()
time = scrapy.Field()
scrapy.Item类是一个类似dict的类,可以对该类对象的属性进行['arrt']赋值及调用
scrapy.Field类类似于mysql字段类
此处需要注意:未在item类中定义的属性,在爬虫过程中,均不能额外添加使用,否则会报错
开启管道
settings.py
# Configure item pipelines
# See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'Tencent.pipelines.TencentPipeline': 300,
}
将此处的注释打开即可
开始爬虫
spider/tencent_post.py
# -*- coding: utf-8 -*-
import scrapy
from ..items import TencentItem
class TecentPostSpider(scrapy.Spider):
name = 'tencent_post'
allowed_domains = ['hr.tencent.com']
start_urls = ['https://hr.tencent.com/position.php']
def parse(self, response):
for i in response.xpath('//table//tr')[1:-2]:
item = TencentItem()
item['name'] = i.xpath('./td[1]/a/text()').extract_first()
item['type'] = i.xpath('./td[2]/text()').extract_first()
item['number'] = i.xpath('./td[3]/text()').extract_first()
item['position'] = i.xpath('./td[4]/text()').extract_first()
item['time'] = i.xpath('./td[5]/text()').extract_first()
yield item
name: 此处的name属性,即为爬虫名,以后shell命令行运行爬虫的时候会用到
allowed_domains: 允许爬去的域名,凡是超出该域名的网址都将会被过滤
start_urls : 起始爬去的url,默认有原始spider类的start_requests实例方法进行调用操作
parse(): 实例方法,处理start_urls的爬取结果
parse函数体详解
xpath: 一种html数据提取方法,此处不详解,有兴趣的可以自己网上查询学习。该方法基于C,执行速度较快
在scrapy中,所有提取方法提取出来的结果,都是Selector对象列表
<Selector xpath='//table//tr' data='<tr class="odd">\r\t\t \t\t<td class="l sq'>
extract_first: 提取Selector对象列表中的而第一个元素的data属性
yield item: 生成器关键字yield。将parse函数改变为生成器。我们上面开启的管道会调用parse方法的返回值,进行处理
pipelines.py
class TencentPipeline(object):
def process_item(self, item, spider):
print(item)
return item
结果
E:\pyCharmWorkspace\Spider\Tencent>scrapy crawl tencent_post
<Selector xpath='//table//tr' data='<tr class="even">\r\t\t \t\t<td class="l s'>
{'name': '17759-产品分析经理(北京)',
'number': '1',
'position': '北京',
'time': '2018-08-20',
'type': '市场类'}