使用scrapy+mysql爬取拉勾网移动端页面
@hcolde
字数 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 返回数据:
1.3数据处理:
- pageSize 每页显示多少个职位信息。 ( json->content->data->page->pageSize )
- totalCount 总共有多少个职位。 ( json->content->data->page->totalCount )
- positionId 职位id,打开职位详情页面需要的参数,返回的类型为int型。 ( json->content->data->page->result[]->positionId )
以上是重要的数据,至于其他数据可选择性收集。
根据pageSize和totalCount可计算需要爬取多少个页面,代码如下:
pages = totalPage//pageSize
pages = pages+1 if totalPage%pageSize else pages
1.4 操作数据库
import pymysql
host = '127.0.0.1' # 数据库服务器.
user = 'root' # 数据库用户.
password = '' # 该用户的密码.
dbName = 'lg' # 数据库名.
cursor = None
tyr:
db = pymysql.connect(host=host, user=user, password=password, db=dbName)
except Exception as e:
print(e)
else:
cursor = db.cursor() # 创建游标对象.
# 创建表.
sql = '''
CREATE TABLE IF NOT EXISTS `job`(
`positionId` INT,
`positionName` VARCHAR(50),
`salary` VARCHAR(10),
`createTime` VARCHAR(10),
`companyFullName` VARCHAR(50),
PRIMARY KEY (`positionId`)
)
'''
sql = sql.replace('\t', '').replace('\n', '') # 消掉sql里的制表符和换行符.
if cursor:
try:
cursor.execute(sql)
except Exception as e:
print(e)
# 插入数据.
sql = '''
INSERT INTO `job`(
`positionId`,
`positionName`,
`salary`,
`createTime`,
`companyFullName`
) VALUES (%d, '%s', '%s', '%s', '%s')
''' % (positionId, name, salary, time, company)
if cursor:
try:
cursor.execute(sql)
db.commit() # 提交到数据库执行.
except Exception as e:
print(e)
2. 职位详情页面
https://m.lagou.com/jobs/1234.html
2.1 参数说明:
- 该链接中的1234为positionId。
2.2 返回数据:
该链接返回的是html,因此可以使用css选择器或xpath选择器对html中的数据进行采集。
返回的部分html如下:
<div class="detail">
<div class="items">
<span class="item salary"> <em class="icon"></em> <span class="text">8k-15k</span> </span>
<span class="item workaddress"> <em class="icon"></em> <span class="text">北京</span> </span>
<span class="item jobnature"> <em class="icon"></em> <span class="text">全职</span> </span>
<span class="item workyear"> <em class="icon"></em> <span class="text">3-5年</span> </span>
<span class="item education"> <em class="icon"></em> <span class="text"> 学历不限 </span> </span>
</div>
</div>
<div class="content">
<p><strong>岗位职责:</strong> <br />负责Android手机客户端开发。</p>
<br />
<p><br /><strong>任职要求:</strong> <br />1、熟练的Java 编程经验,扎实的计算机知识基础,丰富的实际代码编写经验; <br />2、精通Android系统架构及相关技术,1年以上实际 Android平台开发经验; <br />3、具备团队合作精神,有良好的沟通及协调能力; <br />4、积极主动,具备独立解决问题及自我学习能力。</p>
</div>
2.3 数据处理
- 获取工作经验信息:
workyear = response.xpath('//div[@class="items"]/span[@class="item workyear"]/span[@class="text"]/text()').extract_first()
- 获取岗位职责信息:
content = response.xpath('//div[@class="content"]/p/text()').extract()
div[@class="content"]下有多个p标签,所以获取到的信息为列表形式。
html中有多余的制表符,换行符和br标签等等,要将这些去掉。
# str.split()将字符串中所有的空格符作为分隔符,分割为list.
# ''.join(list) 将list以无间隔的形式组合起来.
# 两种方法结合,可去掉多余的制表符,换行符和br标签等空格符.
workyear = ''.join(workyeay.split())
content = ''.join(content) # 因为content为list类型,需要先以无间隔的形式组合成字符串.
content = ''.join(content.split()) # 再用老方法那啥.
2.4 操作数据库
- 按照1.4的方法创建个job_detail数据表。
- 从job数据表中获取所有的positionId。
sql = 'SELECT DISTINCT `positionId` FROM `job`'
if cursor:
try:
cursor.execute(sql)
result = cursor.fetchall()
except Exception as e:
print(e)
- 查看job_detail已保存了哪些职位详情信息。
(已保存的就不再爬取)
id_list = []
sql = 'SELECT `positionId` FROM `job_detail`'
if cursor:
try:
cursor.execute(sql)
data = cursor.fetchall()
except Exception as e:
print(e)
else:
for d in data:
id_list.append(d['positionId'])
- 构建需要爬取的url
urls = []
for r in result:
if r['positionId'] not in id_list:
url = 'https://m.lagou.com/jobs/' + str(r['positionId']) + '.html' # 别忘了positionId是int型.
urls.append(url)
- 将url交给scrapy
def start_requests(self):
for url in urls:
# dont_Filter默认为False,为True时可重复爬取同一页面,不然scrapy自动帮你无视已爬取的页面.
# 当爬虫不断爬取时,容易被网站服务器拒绝访问,所以当返回的status不为200时,之后再重复爬取该页面.
yield scrapy.request(url=url, dont_filter=True)
默认情况下,Scrapy对响应状态为非20x的页面不进行任何处理。
所以如果要处理响应状态为302,404,502,504这些页面时,需要在爬虫中定义:
handle_httpstatus_list = [302, 404, 407, 502, 504]
结果展示
SELECT positionId, positionName 职位, salary 工资, createTime 发布时间, companyFullName 公司, FROM job;
SELECT
job.companyFullName 公司,
job.positionName 职位,
job.salary 薪资,
job.createTime 发布时间,
job_detail.workyear 工作经验,
substring_index(job_detail.info, '/', -1) 公司相关信息,
left(job_detail.content, 25) 职位描述
FROM job_detail
LEFT JOIN job on job.positionId=job_detail.positionId;
说明
substring_index(str,delim,count): 将str以delim作为分割符进行截取,获取截取后第count个内容。
left(str, conut): 获取str从左边起的count个字符。
结语
大致的处理过程就是这样,其中还可以开启多线程来存取数据,主线程就爬取网页。
该项目保存地址badboy
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.****.net/hcolde/article/details/80696841