初识爬虫 - scrapy 爬取 51 (一)

刚学会了建 scrapy 框架,当然就忍不住想去练练手了,就挑个 51 job 去了解一下职位需求情况。

前面我们已经说了如何去创建一个 scrapy 框架,以及改一下 setting 配置文件,这里我们还要先再改一下 setting 文件:

改这里是因为现在很多网站都设置了反爬虫的保护机制,如果我们不加自己设的 user-agent ,就很容易被 “ban” ,从而爬取不到我们所要的数据,当然这只是防反爬虫的一种机制,大多数情况下都是可以的。下面是加的两行代码:

'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,  # 这一行是取消框架自带的useragent
'positionspiders.rotateuseragent.RotateUserAgentMiddleware': 400    #使用自己新置的 useragent 代理 ,第一个表示我们的工程名称,第二个是我们要新建的配置 user-agent 池的文件

那么下面先说下配置 useragent 池的文件 rotateuseragent (文件名字自己起):

import random
# 导入useragent用户代理模块中的UserAgentMiddleware类
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware

# RotateUserAgentMiddleware类,继承 UserAgentMiddleware 父类
# 作用:创建动态代理列表,随机选取列表中的用户代理头部信息,伪装请求。
#       绑定爬虫程序的每一次请求,一并发送到访问网址。

# 发爬虫技术:由于很多网站设置反爬虫技术,禁止爬虫程序直接访问网页,
#             因此需要创建动态代理,将爬虫程序模拟伪装成浏览器进行网页访问。
class RotateUserAgentMiddleware(UserAgentMiddleware):
    # the default user_agent_list composes chrome,I E,firefox,Mozilla,opera,netscape
    # for more user agent strings,you can find it in http://www.useragentstring.com/pages/useragentstring.php
    # 编写头部请求代理列表
    user_agent_list = [ \
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1" \
        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", \
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", \
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", \
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", \
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", \
        "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", \
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
        "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", \
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", \
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", \
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", \
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", \
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
    ]

    def __init__(self, user_agent=''):
        self.user_agent = user_agent

    def process_request(self, request, spider):
        #这句话用于随机轮换user-agent
        ua = random.choice(self.user_agent_list)
        if ua:
            # 输出自动轮换的user-agent
            print("本次访问伪造的请求头是:", ua)
            request.headers.setdefault('User-Agent', ua)
            pass
        pass

    pass

现在我们设置了动态代理,接着就可以去写我们的爬虫代码了。先获取我们的目标网址,这里爬的是 python 的一些职位信息:

start_urls = ['https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare=']

接下来我们要去目标网页中找到目标路径,因为我们需要用到 xpath 路径表达式去获取我们需要的节点,所以我们先要去查看目标网页源码,找到目标节点:

即 class='el' 的div 节点下,下面就用到我们的 xpath 路径表达式去获取目标,如果对 xpath 不熟悉的,可以看下另一篇博客 xpath 全解

jobDivItems=response.xpath("//div[@class='el']")

我们这里获取的所有 div 下 class 属性值等于 el 的标签节点,是一个复数列表,下面我们需要对其中的一条标签,详细获取其内容,这里我们要用到 scrapy 框架下的 items 文件 ,该文件的用途见 Items 理解 。

接下来我们还需要继续去网页中定位我们的目标节点:

下面获取该节点,并将获取的目标字段,通过 Item 类进行实例化:

        jobDivItems=response.xpath("//div[@class='el']")    #这里获取的是当前页下所有的职位信息
        for jobDivItem in jobDivItems:
            pItem=PositionspidersItem()         # 创建 Item 类的一个对象
            pItem['joblanguage']=PositionspiderSpider.jobType       #将字段通过 Item 对象实例化
            #print(jobDivItem.extract())

            #print(jobDivItem.extract("//p[@class='t1']/span/a/text()"))

            jobTitle = jobDivItem.xpath("//p[@class='t1 ']/span/a/text()").extract()
            # extract(): 这个方法返回的是一个数组list,里面包含了多个string,如果只有一个string,则返回['ABC']这样的形式。

            if len(jobTitle)>0:
                pItem['jobTitle']=jobTitle[0].strip()
                pass
            else:
                continue

            jobComp=jobDivItem.xpath("span[@class='t2']/a/text()").extract()
            jobAddress=jobDivItem.xpath("span[@class='t3']/text()").extract()
            jobSalary=jobDivItem.xpath("span[@class='t4']/text()").extract()
            jobTime=jobDivItem.xpath("span[@class='t5']/text()").extract()

            if len(jobComp)>0:
                pItem['jobComp'] = jobComp[0].strip()
                pass
            else:
                continue
            if len(jobAddress)>0:
                pItem['jobAddress'] = jobAddress[0].strip()
                pass
            else:
                continue
            if len(jobSalary)>0:
                pItem['jobSalary'] = jobSalary[0].strip()
                pass
            else:
                continue
            if len(jobTime)>0:
                pItem['jobTime'] = jobTime[0].strip()
            else:
                continue

            print(jobTitle)
            print(jobComp)
            print(jobAddress)
            print(jobSalary)
            print(jobTime)
            yield pItem
            pass

至于这个输出,我们在管道文件中也有定义:

到这里,我们如果输出的话就没问题了,但这只是一页的数据,才几十个,有点太少了,那下面我们就去爬下一页的,注意这里,是爬取下一页的,而不是指定前几页,意思就是如果我们不停止程序,它会一直往后爬,直到最后一页(现在都1337页了,爬完不知道得多长时间,我是没试过)。那下面就是去找下一页的跳转,我们看到当前页面最下面,是关于页数的跳转:

我们考虑一下这里会不会就有我们想到的信息,审查一下元素:

审查后发现,这里的下一页中含有一个链接,而这个链接就是下一页的地址。到这里就好办了,我们只需要获取对应路径结点下的内容信息就行了,下面我们仍使用 xpath 来定位结点,并获取下页的内容:

        #开始解析下一页代码 获得下一页的超链接地址
        nextPageURL=response.xpath("//div[@class='p_in']/ul/li[@class='bk']/a/@href").extract()
        print("*****************",nextPageURL)
        if nextPageURL:  #如果判断一个列表为TUre 它是以这个列表的长度作为判断条件
            url=response.urljoin(nextPageURL[-1])
            print('url',url)

            yield scrapy.Request(url,self.parse,dont_filter=False)      #这一行我也比较迷
            pass
        else:
            print("退出")
        return
        pass

这里面关键的那行代码我就有点迷,当时也没记住,爬虫还没深入学,也不清楚具体的使用,如果想了解的读者,可以自行去找一下,我因为时间问题,没空再深入学了。

到这里,简单 scrapy 爬取 51 就完成了, 后面是将爬取的内容保存入库,方面我们去看职位信息,见下一篇博客:scrapy 爬取51(二),顺便把这个小项目打包放网盘里分享一下。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章