使用scrapy+mysql爬取拉勾网移动端页面

字数 4061

使用scrapy+mysql爬取拉勾网移动端页面


前期准备:

  • Python3.6
  • virtualenv ( pip install virtualenv )
  • Scrapy ( pip install Scrapy )
  • PyMySQL ( pip install pymysql )
  • Mysql服务器

1. 搜索职位页面

https://m.lagou.com/search.json?city=广州&positionName=python&pageNo=1

1.1 参数说明:
  • city:搜索的城市
  • positionName:职位名称
  • pageNo:页码

1.2 返回数据:

使用scrapy+mysql爬取拉勾网移动端页面_第1张图片


使用scrapy+mysql爬取拉勾网移动端页面_第2张图片


1.3数据处理:
  • pageSize 每页显示多少个职位信息。 json->content->data->page->pageSize )
  • totalCount 总共有多少个职位。 json->content->data->page->totalCount )
  • positionId 职位id,打开职位详情页面需要的参数,返回的类型为int型。 json->content->data->page->result[]->positionId )

以上是重要的数据,至于其他数据可选择性收集。

根据pageSizetotalCount可计算需要爬取多少个页面,代码如下:

  1. pages = totalPage//pageSize
  2. pages = pages+1 if totalPage%pageSize else pages


1.4 操作数据库
  1. import pymysql
  2. host = '127.0.0.1' # 数据库服务器.
  3. user = 'root' # 数据库用户.
  4. password = '' # 该用户的密码.
  5. dbName = 'lg' # 数据库名.
  6. cursor = None
  7. tyr:
  8. db = pymysql.connect(host=host, user=user, password=password, db=dbName)
  9. except Exception as e:
  10. print(e)
  11. else:
  12. cursor = db.cursor() # 创建游标对象.
  13. # 创建表.
  14. sql = '''
  15. CREATE TABLE IF NOT EXISTS `job`(
  16. `positionId` INT,
  17. `positionName` VARCHAR(50),
  18. `salary` VARCHAR(10),
  19. `createTime` VARCHAR(10),
  20. `companyFullName` VARCHAR(50),
  21. PRIMARY KEY (`positionId`)
  22. )
  23. '''
  24. sql = sql.replace('\t', '').replace('\n', '') # 消掉sql里的制表符和换行符.
  25. if cursor:
  26. try
  27. cursor.execute(sql)
  28. except Exception as e:
  29. print(e)
  30. # 插入数据.
  31. sql = '''
  32. INSERT INTO `job`(
  33. `positionId`,
  34. `positionName`,
  35. `salary`,
  36. `createTime`,
  37. `companyFullName`
  38. ) VALUES (%d, '%s', '%s', '%s', '%s')
  39. ''' % (positionId, name, salary, time, company)
  40. if cursor:
  41. try:
  42. cursor.execute(sql)
  43. db.commit() # 提交到数据库执行.
  44. except Exception as e:
  45. print(e)

2. 职位详情页面

https://m.lagou.com/jobs/1234.html

2.1 参数说明:
  • 该链接中的1234为positionId。


2.2 返回数据:

该链接返回的是html,因此可以使用css选择器或xpath选择器对html中的数据进行采集。

返回的部分html如下:

  1. class="detail">
  2. class="items">
  3. class="item salary"> class="icon"> class="text">8k-15k
  4. class="item workaddress"> class="icon"> class="text">北京
  5. class="item jobnature"> class="icon"> class="text">全职
  6. class="item workyear"> class="icon"> class="text">3-5年
  7. class="item education"> class="icon"> class="text"> 学历不限
    1. class="content">
    2. 岗位职责:  />负责Android手机客户端开发。

    3. />
    4. />任职要求:  />1、熟练的Java 编程经验,扎实的计算机知识基础,丰富的实际代码编写经验;  />2、精通Android系统架构及相关技术,1年以上实际 Android平台开发经验;  />3、具备团队合作精神,有良好的沟通及协调能力;  />4、积极主动,具备独立解决问题及自我学习能力。

    2.3 数据处理
    • 获取工作经验信息:
    1. workyear = response.xpath('//div[@class="items"]/span[@class="item workyear"]/span[@class="text"]/text()').extract_first()

    • 获取岗位职责信息:
    1. content = response.xpath('//div[@class="content"]/p/text()').extract()

    div[@class="content"]下有多个p标签,所以获取到的信息为列表形式。

    html中有多余的制表符,换行符和br标签等等,要将这些去掉。

    1. # str.split()将字符串中所有的空格符作为分隔符,分割为list.
    2. # ''.join(list) 将list以无间隔的形式组合起来.
    3. # 两种方法结合,可去掉多余的制表符,换行符和br标签等空格符.
    4. workyear = ''.join(workyeay.split())
    5. content = ''.join(content) # 因为content为list类型,需要先以无间隔的形式组合成字符串.
    6. content = ''.join(content.split()) # 再用老方法那啥.


    2.4 操作数据库
    • 按照1.4的方法创建个job_detail数据表。
    • 从job数据表中获取所有的positionId。
    1. sql = 'SELECT DISTINCT `positionId` FROM `job`'
    2. if cursor:
    3. try:
    4. cursor.execute(sql)
    5. result = cursor.fetchall()
    6. except Exception as e:
    7. print(e)

    • 查看job_detail已保存了哪些职位详情信息。 
      (已保存的就不再爬取)
    1. id_list = []
    2. sql = 'SELECT `positionId` FROM `job_detail`'
    3. if cursor:
    4. try:
    5. cursor.execute(sql)
    6. data = cursor.fetchall()
    7. except Exception as e:
    8. print(e)
    9. else:
    10. for d in data:
    11. id_list.append(d['positionId'])
    • 构建需要爬取的url
    1. urls = []
    2. for r in result:
    3. if r['positionId'] not in id_list:
    4. url = 'https://m.lagou.com/jobs/' + str(r['positionId']) + '.html' # 别忘了positionId是int型.
    5. urls.append(url)

    • 将url交给scrapy
    1. def start_requests(self):
    2. for url in urls:
    3. # dont_Filter默认为False,为True时可重复爬取同一页面,不然scrapy自动帮你无视已爬取的页面.
    4. # 当爬虫不断爬取时,容易被网站服务器拒绝访问,所以当返回的status不为200时,之后再重复爬取该页面.
    5. yield scrapy.request(url=url, dont_filter=True)


    默认情况下,Scrapy对响应状态为非20x的页面不进行任何处理。
    所以如果要处理响应状态为302,404,502,504这些页面时,需要在爬虫中定义:

    1. handle_httpstatus_list = [302, 404, 407, 502, 504]


    结果展示

    1. SELECT positionId, positionName 职位, salary 工资, createTime 发布时间, companyFullName 公司, FROM job;

    使用scrapy+mysql爬取拉勾网移动端页面_第3张图片


    1. SELECT
    2. job.companyFullName 公司,
    3. job.positionName 职位,
    4. job.salary 薪资,
    5. job.createTime 发布时间,
    6. job_detail.workyear 工作经验,
    7. substring_index(job_detail.info, '/', -1) 公司相关信息,
    8. left(job_detail.content, 25) 职位描述
    9. FROM job_detail
    10. LEFT JOIN job on job.positionId=job_detail.positionId;

    说明
    1. substring_index(str,delim,count): strdelim作为分割符进行截取,获取截取后第count个内容。
    2. left(str, conut): 获取str从左边起的count个字符。

    使用scrapy+mysql爬取拉勾网移动端页面_第4张图片

    结语

    大致的处理过程就是这样,其中还可以开启多线程来存取数据,主线程就爬取网页。

    该项目保存地址badboy


    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hcolde/article/details/80696841

    你可能感兴趣的:(Scrapy)