爬虫进阶之scrapy项目实战

爬虫进阶之scrapy项目实战

前言

觉得Scrapy确实挺强大的,并且要想更加熟悉和了解这个框架,应该要多做一些项目来强化对Scrapy的理解,本次的项目是针对Boss直聘,想要爬取boss直聘根据关键词(地点和工作)的工作岗位的详细情况,包括薪资、学历要求、地点、工作描述等等…此次设置的爬虫规则是通过CSS选择器进行的,因此说明时也会介绍CSS选择

正文

初始化爬虫项目

scrapy startproject zhipin_com #后面是项目的名字

从得到的文件架构中也能清楚知道整个Scrapy的框架,具体我们在上一章博客中也介绍了

scrapt genspider zhipin #创建一个名为zhipin的爬虫

在这里插入图片描述
当初始化完成后,接下来我们就应该设置item,其实item很好理解,就是我们所要爬取的参数,我们需要爬取多少参数,就可以设置多少个items,这里我们需要设置如下items:
在这里插入图片描述
如上,这些都是我们需要爬取的,我们在items.py先将他们说明,接下来就是设置爬虫规则了,在这里先说明一下CSS选择器
http://www.scrapyd.cn/doc/185.html
现附上scrapy对于CSS选择器的官方文档,个人感觉讲的很详细了,下面举一些例子来说明:

<ol class="page-navigator">
  <li class="current"><a href="http://lab.scrapyd.cn/page/1/">1</a></li>
  <li><a href="http://lab.scrapyd.cn/page/2/">2</a></li>
  <li><a href="http://lab.scrapyd.cn/page/3/">3</a></li>
  <li><a href="http://lab.scrapyd.cn/page/4/">4</a></li>
</ol>

如果我们想提取该html中的URL,我们应该如何提取呢?
在这里插入图片描述
这里列举了一些重要的匹配,如果我们是要选择class中的元素,我们只需要在response.css(".class"),其实在设置匹配规则时,我们要操作的无非是这三个,response.css(“css表达式”)、extract()、extract_first()
提取属性我们是用:“标签名::attr(属性名)”,因此在上面html中,匹配URL应该是

url = response.css(".page-navigator a::attr(href)").extract()

在使用scrapy匹配时返回的都是selectorList的对象实例,而extract()可以看成是将对象实例变成列表的形式

再比如这个例子:

<div class="left">
  scrapy中文网左边
</div>

<div class="center">
  scrapy中文网中部
</div>

<div class="right">
  scrapy中文网右侧
</div>

我们想要第二段文字,应该如何匹配?这时::text能够匹配标签中的内容,因此我们应该这样匹配

text = response.css(".center::text").extract()

这里需要注意的是,CSS高级用法中,response.css(".div1 .div2")表示的是选择div1中的所有div2元素,不一定是父子关系,而response.css(".div1>.div2")则这俩者一定是父子关系的,那如果<div>标签中的class属性的值本来就含有空格,例如
在这里插入图片描述
这里本来就含有空格,但是我们是相匹配的这个<div>标签的话,此时就应该把空格当成.处理:

div = response.css("div.wrapper_new.wrapper_s")#这样进行匹配

CSS选择器说明完之后,接下来我们就来配置规则了:
在这里插入图片描述
先设置开始的url和当前页数
在这里插入图片描述
设置好请求头(注意:请求头的设置尤为重要,现在很多网页都有反爬取措施,不设置请求头很可能不会有response)

具体的job参数对应html哪个位置,我们可以将鼠标移动到job参数右击检查,即可在开发者工具中看到对应的位置,因此我们只需要一个一个进行查找即可,每一个工作都是放在<ul><li></li></ul>下,for循环即可

这里还需要动态爬取页面,当第一页爬取完后主动爬取第二页,因此还要构造一个方法

    def next_request(self):
        return scrapy.http.FormRequest(self.position_url+"&page={}&ka=page-{}".format(self.cur_page,self.cur_page),headers=self.headers,callback=self.parse)
        pass

爬取完一页后cur_page+=1然后调用next_request()这样继续爬取第二页的数据
在这里插入图片描述
当写完项目后,在命令行中scrapy crawl zhipin -o data.json便能生成data的json数据,看一眼效果图
在这里插入图片描述

写到最后

然后前几次可以,多爬取几次后就翻车了…
在这里插入图片描述
应该是boss直聘有反爬措施,并且我设置的time.sleep()是一个定值,可能也被检测出了,在这里我尝试了一种新的思路,随着爬虫项目的变大应该也很常见,就是设置代理,通过不断随机的代理和UA头来骗取服务器的信任,认为这是一个合法的用户,那么如何设置代理呢?

setting.py

settings.py中设置好相应的代理参数和UA头:
在这里插入图片描述
免费代理可以去google上找找

middlewares.py

这其实是scrapy的一个中间件,scrapy的下载器中间件位于调度器和下载器之间,可用于给请求头中添加user-agent等应用
在这里插入图片描述这就是这个中间件的大致作用,当然还有其他的作用,如添加cookie等
在这里插入图片描述
我们设置好相应的代理和随机UA头的处理,注意设置好后需要在settings.py中配置好中间件,即DOWNLOADER_MIDDLEWARES
在这里插入图片描述
这样自建中间件才会发挥作用,配置好后我们重新进行

scrapy crawl zhipin -o data.json

…很不幸的是,我找到的代理都挂了,反正一直请求不了,显示目标计算机积极拒绝之类的,大概率是免费代理太辣鸡了,这里留个坑以后明白了再来玩一玩代理池这些。之前成功的图忘记截了,然后第二次爬取就被ban了IP,这里就附上设置代理挂了的截图吧…
在这里插入图片描述

好在是爬到了一些数据,为了避开反爬取,我想的是应该设置time.sleep()为随机值,并且时间要足够的长,这样才会让我的IP变得像是合法用户而不是spiders

第二天顺着思路设置了随机的time.sleep()后发现能爬四页左右,然后需要重新爬取,但是IP不会被封了。附上截图吧
在这里插入图片描述