当前位置:   article > 正文

Scrapy爬虫框架案例学习之三(爬取网易招聘页面信息写入Mysql数据库)_scrap爬取网易招聘

scrap爬取网易招聘

1、网易招聘

1.1 问题梳理

(1)该网站是一个JSON数据渲染的动态网页,网页源码里面并没有数据,这个地方不能直接用Xpath解析。 

(2)打开这个页面一共有2856个职位,有286页,因此需要翻页。

(3)爬取的数据信息要保存到Mysql数据库,写一个通用的数据库的类进行保存。

2、页面分析(这个是关键,找到这个请求页面动态加载JSON数据的请求)

这就是json数据格式,里面的信息都包含了,因此就不需要通过每一个职位的详情页面链接再次获取相关的信息,后面的案例会有。

因此start_url页面的地址就不是第一个地址了,而且请求的方式为POST请求,带有相关的参数。相关参数见Payload

下面是在job.py构建的POST请求函数,keyword大家可以去掉,我这里只是学习,不想爬取太多的信息,因此用关键字Python限制了下,就相当于,我这里只是获取有关Python的职位信息。小伙伴们重点关注下yield  scrapy.Request()里面的POST请求的写法。这里将请求获得的结果送给parse()函数进一步处理。

start_urls = ["https://hr.163.com/api/hr163/position/queryPage"]

def start_requests(self):
        url = self.start_urls[0]
        print(url)
        # 起始url参数
        payload = {
            "currentPage": "1",
            "keyword":"Python",
            "pageSize": "10"
        }
        print(json.dumps(payload))
        # 构建post请求
        yield scrapy.Request(
            url=url,
            body=json.dumps(payload),
            method='POST',
            callback=self.parse,
            headers={'Content-Type': 'application/json'}
        )

3、相关代码

3.1 items.py 

  1. import scrapy
  2. class WangyinewItem(scrapy.Item):
  3. # define the fields for your item here like:
  4. # name = scrapy.Field()
  5. name = scrapy.Field()
  6. productName = scrapy.Field()
  7. postTypeFullName = scrapy.Field()
  8. description = scrapy.Field()
  9. recruitNum = scrapy.Field()
  10. reqEducationName = scrapy.Field()
  11. reqWorkYearsName = scrapy.Field()
  12. requirement = scrapy.Field()
  13. firstPostTypeName = scrapy.Field()
  14. workPlaceNameList = scrapy.Field()
  15. #下面2个变量主要是为了做通用的数据库表写入程序用的。
  16. table_fields = scrapy.Field() # 字段名称
  17. table_name = scrapy.Field() # 插入表的名称

3.2 job.py

  1. import scrapy
  2. from wangyinew.items import WangyinewItem
  3. import json
  4. next_page =1 #用来控制翻页的变量,主要是给URL传递参数
  5. class JobSpider(scrapy.Spider):
  6. name = "job"
  7. allowed_domains = ["163.com"]
  8. #start_urls = ["https://hr.163.com/job-list.html"]
  9. start_urls = ["https://hr.163.com/api/hr163/position/queryPage"]
  10. def __init__(self):
  11. self.table_name = 'wangyijob'
  12. self.table_fields = ['name','productName','postTypeFullName','description','recruitNum',
  13. 'reqEducationName','reqWorkYearsName','requirement','firstPostTypeName','workPlaceNameList']
  14. def start_requests(self):
  15. url = self.start_urls[0]
  16. print(url)
  17. # 起始url参数
  18. payload = {
  19. "currentPage": "1",
  20. "keyword":"Python",
  21. "pageSize": "10"
  22. }
  23. print(json.dumps(payload))
  24. # 构建post请求
  25. yield scrapy.Request(
  26. url=url,
  27. body=json.dumps(payload),
  28. method='POST',
  29. callback=self.parse,
  30. headers={'Content-Type': 'application/json'}
  31. )
  32. def parse(self, response):
  33. dic = response.json()
  34. job_list = dic['data']['list']
  35. item = WangyinewItem()
  36. item['table_fields'] = self.table_fields
  37. item['table_name'] = self.table_name
  38. for job in job_list:
  39. item['name'] = job['name']
  40. item['productName'] = job['productName']
  41. item['postTypeFullName'] = job['postTypeFullName']
  42. item['description'] = job['description'].replace('\t','').replace('\n','')
  43. item['recruitNum'] = job['recruitNum']
  44. item['reqEducationName'] = job['reqEducationName']
  45. item['reqWorkYearsName'] = job['reqWorkYearsName']
  46. item['requirement'] = job['requirement'].replace('\t','').replace('\n','')
  47. item['firstPostTypeName'] = job['firstPostTypeName']
  48. item['workPlaceNameList'] = str(job['workPlaceNameList']).replace('[','').replace(']','').replace("'",'')
  49. # 处理数据
  50. yield item
  51. #模拟翻页
  52. # 返回的数据中来判断是否为最后一页 true为最后一页
  53. page_stutas = dic['data']['lastPage']
  54. global next_page
  55. next_page = next_page + 1
  56. print(next_page)
  57. if page_stutas == False: # 回调出口
  58. payload = {
  59. "currentPage":"{}".format(next_page),
  60. "keyword":"Python",
  61. "pageSize": "10"
  62. }
  63. print(payload)
  64. url = self.start_urls[0]
  65. yield scrapy.Request(
  66. url=url,
  67. body=json.dumps(payload),
  68. method='POST',
  69. callback=self.parse,
  70. headers={'Content-Type':'application/json'}
  71. )

我写代码的解释部分较少,如果有看不明白的小伙伴留言。

4、mysql数据库

MySQL是一种开源的关系型数据库管理系统,它采用了客户机-服务器模式,通过在服务器上存储数据并管理数据来提供数据管理服务。它支持多用户使用,并且能够高效地处理大量数据,被广泛应用于Web应用程序的开发、数据存储和数据分析等领域。MySQL使用SQL语言进行数据的管理和查询,并且具有高度灵活性、可移植性和可扩展性。它可以运行在各种操作系统上,包括Windows、Linux、Unix等。MySQL的特点是速度快、可靠性高、易学易用、易扩展等。

我用的mysql数据库是5.7经典解压版的,现在已经更新到Mysql8,我没有用安装包安装,小伙伴们可以自己选择下载安装,这玩意最好一次装好,如果报错,再次安装仍然出现问题,非常麻烦,除非重装系统,如果不幸的话叫我说中了,可以通过虚拟机安装mysql解决。

装好mysql配置环境变量,修改密码这一套还是很麻烦的。网上有教程。mysql-5.7.37-winx64解压版安装超详细图文教程_浩瀚之水_csdn的博客-CSDN博客

不出意外的话,我也是用navicat for Mysql软件进行数据库管理。

一顿操作猛如虎,在建个表用来保存数据,建表的命令在数据库下面的查询里面新建个查询,输入SQL语句的。这个我就不再赘述了,以后有机会再聊。

建表的SQL语句:(这个代码不是放到Python代码的,大家也可以通过函数来实现比较简单,我这没有写,小伙伴可以根据我给的代码组装下就OK了,不过每次运行的时候如果已经创建表了,就加个判断或异常即可)

  1. import pymysql
  2. def sqlexe(sql):
  3. db = pymysql.connect( host='127.0.0.1', port=3306, user='root', password='123456', database='mydb', charset='utf8')
  4. cursor = db.cursor()
  5. cursor.execute(sql)
  6. sqlret = cursor.fetchall()
  7. # col_result = cursor.description
  8. cursor.close()
  9. db.close()
  10. return sqlret
  1. CREATE TABLE `wangyijob` (
  2. `name` varchar(255) NOT NULL ,
  3. `productName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  4. `postTypeFullName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  5. `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  6. `recruitNum` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  7. `reqEducationName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  8. `reqWorkYearsName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  9. `requirement` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  10. `firstPostTypeName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  11. `workPlaceNameList` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
  12. )

 说了这么多,最后放pipelines文件的代码,如果有什么格式问题,大家自己调整,本学习系列并非基础面向小白来的,如果有机会,我再详细讲解遇到的一些坑坑洼洼。

  1. from itemadapter import ItemAdapter
  2. import pymysql
  3. import logging
  4. class WangyinewPipeline:
  5. """
  6. 同步插入数据库
  7. """
  8. def __init__(self):
  9. self.connect=pymysql.connect(host='localhost',user='root',passwd='123456',db='mydb',charset='utf8',port=3306)
  10. self.cursor=self.connect.cursor()
  11. def process_item(self, item, spider):
  12. table_fields = item.get('table_fields')
  13. table_name = item.get('table_name')
  14. if table_fields is None or table_name is None:
  15. raise Exception('必须要传表名table_name和字段名table_fields,表名或者字段名不能为空')
  16. values_params = '%s, ' * (len(table_fields) - 1) + '%s'
  17. keys = ', '.join(table_fields)
  18. values = ['%s' % str(item.get(i, '')) for i in table_fields]
  19. insert_sql = 'insert into %s (%s) values (%s)' % (table_name, keys, values_params)
  20. try:
  21. self.cursor.execute(insert_sql, tuple(values))
  22. logging.info("数据插入成功 => " + '1')
  23. except Exception as e:
  24. logging.error("执行sql异常 => " + str(e))
  25. pass
  26. finally:
  27. # 要提交,不提交无法保存到数据库
  28. self.connect.commit()
  29. return item
  30. def close_spider(self, spider):
  31. self.connect.close()
  32. self.cursor.close()

5、最后上配置文件,这个比较简单。

USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"    填写下自己浏览器的USER_AGENT,尽量不要注释掉,有些网站没有这个请求参数,服务器不返回响应                                                                        ROBOTSTXT_OBEY = False  # Obey robots.txt rules,这个爬虫协议对于我们这种桀骜不驯,不羁放纵爱自由的人来说,肯定不能遵守。
COOKIES_DEBUG = True
LOG_LEVEL = 'WARNING'只显示警告以上级别的信息,如果想看日志的小伙伴就给注释掉。掉。DOWNLOAD_DELAY = 1 建议大家每次都设置下延时,看看效果,如果慢可以关闭,但是如果关闭,服务器可能会识别过于频繁的请求,认为是爬虫程序,从而封禁IP。

最后把管道打开,让数据源源不断的流入数据库。

 本案例仅供学习使用GitHub - wangluixn/scrapy_neteasejob

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/818738
推荐阅读
相关标签
  

闽ICP备14008679号