scrapy实战之spider篇
在我看来,使用scrapy框架相较于直接用python爬虫库的优点有两个
第一是scrapy更加有效率,而爬虫自然最注重的是效率
第二是scrapy将爬虫的过程分成模块化,使爬虫抓取过程更加清晰
scrapy主要有三个模块spider,pipeline,items.其中items代表的是容器(储存所需要爬取的数据),
spider代表的是爬虫模块(将爬取的html内容用Xpath或者bs或者正则表达式解析,并且储存在容器中),
pipeline代表的是数据处理模块(eg.数据去重,数据清洗,数据储存在mysql数据库)
现在开始爬取数据
首先是创建scrapy项目
然后开始写爬虫
第一是要明确需求,观察网页
分析的要爬取的字段有职位名(job),公司(company),地点(place),薪资(salary),
最高薪资(highest_salary),最低薪资(lowest_salary),发布时间(time)
再检查html网页,分析网页结构
分析得每段数据都是用div区分,而这种html结构用xpath解析比较方便
爬虫解析方法主流的有三种,bs和xpath和正则表达式,其中正则表达式效率最高但是难度也是最大的,xpath难度中等,bs较简单也是效率最低的
下面简单介绍下xpath
主要为/ 和//
//代表无论该节点的位置,均找到它
/代表找节点的子节点,注意不能找子孙节点
@表示属性
eg.//div[@class=”el”]代表的找到属性为el的所有div节点下的所有元素
下面有一段html大家可以练习
‘<html>
‘
<head>
<title>春晚</title>
</head>
<body>
<h1 name="title">个人简介</h1>
<div name="desc">
<p name="name">姓名:<span>小岳岳</span></p>
<p name="addr">住址:中国 河南</p>
<p name="info">代表作:五环之歌</p>
</div>’‘
然后讲解实战内容,先贴出spider代码
需要在python中进入项目目录再编写
“`
-- coding: utf-8 --
导入模块
import scrapy
from job.items import JobItem #第一个错误
class XsSpider(scrapy.Spider):
name = ‘xs’
allowed_domains = [‘51job.com’]
start_urls = [‘https://search.51job.com/list/000000,000000,0000,00,9,99,%25E9%2594%2580%25E5%2594%25AE%25E7%25BB%258F%25E7%2590%2586,2,1.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=4&dibiaoid=0&address=&line=&specialarea=00&from=&welfare=‘]
def parse(self, response):
#分析网页结构
#用xpath
main=response.xpath('//div[@class="el"]')
print(response.text)
#遍历并且储存
# 实例化容器类
for item in main:
item_1=JobItem()#需要在遍历里面 不能在外面
extract() 获取到网页标签的内容,返回列表
zw = item.xpath('p/span/a/text()').extract() # 职位
gs = item.xpath('span[@class="t2"]/a/text()').extract() # 公司名称
dd = item.xpath('span[@class="t3"]/text()').extract() # 地点
xz = item.xpath('span[@class="t4"]/text()').extract() # 薪资
rt = item.xpath('span[@class="t5"]/text()').extract() # 发布时间
href = item.xpath('p[@class="t1 "]/span/a/@href').extract() # 详细页面连接
# 数据存储
if zw:
item_1['job'] = zw[0]
else:
item_1['job'] = ''
if gs:
item_1['company'] = gs[0]
else:
item_1['company'] = ''
if dd:
item_1['place'] = dd[0]
else:
item_1['place'] = '-'
if xz:
item_1['salary'] = xz[0]
else:
item_1['salary'] = ''
if rt:
item_1['time'] = rt[0]
else:
item_1['time'] = ''
if href:
item_1['href'] = href[0]
yield item_1
# 取下一页的数据hred以列表形式
# 取下一页的数据hred以列表形式
# 跳转到下一页
# 错误的原因是没有注意缩进,导致逻辑错误,跳转是要在读取完一个页面后才能跳转 不能在for循环内
next_page = response.xpath('//div[@class="dw_page"]//ul/li[last()]/a/@href').extract()
if next_page:
# 从列表中取到下一页的连接
next_page_href = next_page[0]
# url:请求下一页的url
# callback:函数回调,请求到内容后调用哪个函数,写函数名
yield scrapy.Request(url=next_page_href, callback=self.parse,dont_filter=True)
`
针对一些复杂不易理解的地方进行讲解
main的作用是储存xpath解析到的内容,返回的是列表内容。所以要用for语句遍历,
JobItem()是容器,是从item中导入的,需要在遍历里面接受遍历的内容
if语句是防止用xpath解析的字段是空的,会导致后面的字段占位,所以需要用if语句判断字段是否是空的,如果是空的赋给它空字符串占位,如果不是空就占位
这一步很重要,如果不做if判断会造成数据错位
对于yield
yield是python的生成器,与return相似,但是这里需要用yield而不能用return,因为return是每循环一次返回一次值,没有记忆储存功能,yield具有记忆储存功能,它不返回值而是记忆该值并储存在容器中,而这正是我们需要的
这个是调用下一页,翻页的功能
可以调用模板,注意callback函数就好
下一篇是pipelines代码部分的讲解
有需要爬虫资料的可以call我