zoukankan      html  css  js  c++  java
  • 【Python爬虫学习实践】基于Xpath和lxml库解析网站

    在之前的学习笔记中,介绍了Xpath语法规则和lxml库的基本使用,同时也列举出了一部分示例代码。为了更加深入地学习和运用好这两大工具,下面以爬取Tencent招聘网站职位信息为实例介绍在实践中基于Xpath和lxml库编写爬虫的基本流程和方法。

    Tencent招聘网址:https://hr.tencent.com/

    image

    进入网站后,我们来浏览一下社会招聘一栏,并输入搜索关键字为’python’,之后方可进入如下页面:

    image

    此后,在爬取前,我们先任意选择一个职位进入职位详情页,分析一下我们所要爬取的信息有哪些。在如下详情页中我们可以看到欲获取的信息有职位名称、工作地点、职位类别、招聘人数、工作职责和要求。

    image

    这么一来,爬取需求就已经明确,那么接下来就是分析爬取过程。回顾一下,我们是如何进入职位详情页——在社会招聘先输入关键字后进入职位列表页,然后点击一个职位,浏览器便打开了一个新的url地址,而这也就是职位详情页。因此总体过程是:发送请求获取职位列表页,然后从列表中检索每一个职位详情页的url,再发送新的请求进入详情页,此后便可开展信息提取工作。

    第一部分——获取职位详情页url

    通过上述分析知,职位详情页url蕴含在职位列表中,所以我们先从职位列表页分析。我们要爬取的是所有职位信息,而这些职位是分布在不同的组(页)中,因此我们先依次点击几页看看这些不同页的url都有什么关联。

    经实践后得到如下URL

    第2页:https://hr.tencent.com/position.php?lid=&tid=&keywords=python&start=10#a

    第3页:https://hr.tencent.com/position.php?lid=&tid=&keywords=python&start=20#a

    第4页:https://hr.tencent.com/position.php?lid=&tid=&keywords=python&start=30#a

    这里我们可以发现其URL是有一定规律的,它们的大体构成都相同,只是参数start的值不同。经分析后我们可以知道其实start代表的是当前显示职位列表在全部职位中的起始序号,这个与每页显示的职位个数有关,比如每页显示10条,第2页起始为10,那么第3页起始就是10+10=20,第4页就是20+10=30……如此一来,我们就基本上找到了URL的构成法,那么是不是都这样的呢?以第1页为例,按照我们的分析,第1页URL中应该对应的是10-10=0,我们从其他页点击第1页来验证一下,结果发现确实是0,也印证了我们推测的正确性。考虑到后面锚点’#a’对请求无关紧要,因此职位列表URL结构为:’https://hr.tencent.com/position.php?lid=&tid=&keywords=python&start={}’

    在此之后我们便可以结合之前学习的Xpath与lxml来获取相应的URL信息。这里我们要注意一点的是在获取href属性时,我们检查元素发现其前面没有域名,同上分析详情页URL我们可以得知其构成法为’域名+href’,故在获取href后需要做适当修改。

    image

    ## 获取职位详情页URL
    import requests
    from lxml import etree
    
    # 设置请求头
    HEADERS = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36'
    }
    
    # 设置域名
    BASE_DOMAIN = 'https://hr.tencent.com/'
    
    # 定义获取详情页URL函数
    def get_detail_page(url):
        response = requests.get(url, headers=HEADERS)
        html = etree.HTML(response.content.decode('utf-8'))
        urls = html.xpath('//table[@class="tablelist"]//tr[@class="even" or @class="odd"]//a/@href')
        detail_page = list(map(lambda url: BASE_DOMAIN + url, urls))
        return detail_page

    第二部分——职位详细解析

    在获取了每一个职位详情页url后,便可再次发送请求以获取数据。经分析发现数据都存放在了一个table标签里,我们便可先获取这个标签,然后在使用Xpath来解析其他数据。这里解析方法和之前一样,也相对比较简单,这里不再叙述。

    image

    ## 解析详情页面数据
    def parse_page(url):
        response = requests.get(url, headers=HEADERS)
        html = etree.HTML(response.content.decode('utf-8'))
        infotable = html.xpath('//table[contains(@class,"tablelist")]')[0]
        info = {
            'title': infotable.xpath('.//td[@id="sharetitle"]//text()')[0],
            'address': infotable.xpath('.//tr[2]/td[1]//text()')[1],
            'category': infotable.xpath('.//tr[2]/td[2]//text()')[1],
            'number': infotable.xpath('.//tr[2]/td[3]//text()')[1],
            'responsibility': ''.join(infotable.xpath('.//tr[3]//ul//text()')),
            'requirement': ''.join(infotable.xpath('.//tr[4]//ul//text()'))
        }
        return info

    第三部分——爬虫集成

    其实这一部分并不是一个独立的部分,只是运用上述两部分的方法集成为了一个Spider函数供封装使用。

    ## 爬虫集成
    def Spider():
        BASE_URL = 'https://hr.tencent.com/position.php?lid=&tid=&keywords=python&start={}'
        jobs = []
        for index in range(0, 53): #职位列表页数
            url = BASE_URL.format(index * 10)
            #获取详情页URL
            details_urls = get_detail_page(url)
            for page_url in details_urls: 
                #对单独的详情页进行解析
                info = parse_page(page_url)
                jobs.append(info)
                print(info) #为方便显示结果,直接在次进行输出

    这么一来,我们便可以在主程序中直接调用Spider()函数实现Tencent招聘职位信息的获取,部分结果如下:

    image

    以上便是利用Xpath和lxml爬取数据的一个小小实践,主要是为了加深对上述两个工具的理解和运用,其实,这里面还有很多可以完善的地方,如数据的永久化存储以及多进程爬虫等,而这些都还需要后续的多多学习与练习。


  • 相关阅读:
    js类型自动转换以及==对比规则
    js改变作用域链
    cookie简单实例
    js操作cookie
    body设置margin为0
    inline-block和block元素水平居中显示
    执行git clone遇到警告解决办法
    git中各大写字母表示含义
    git命令报错
    linux.txt
  • 原文地址:https://www.cnblogs.com/Unikfox/p/9671239.html
Copyright © 2011-2022 走看看