Python爬虫 - 笔记+样例

Document笔记
爬虫笔记

爬虫技术是一种一种使用代码抓取网页信息的技术,一般情况下使用Python语言来编写爬虫的脚本,其他的语言也部分的对爬虫技术有支持,但是应用不广泛。网络爬虫是一种能有条理并且系统化地浏览Web,以便收集网页数据的程序(通常也被称作“机器人”)。搜索引擎(例如谷歌,必应)利用爬虫来创建索引是网络爬虫最典型的使用案例。

下面是一个爬虫的简单例子,使用到了requets包和BeautifulSoup包。其中

  • request包用于抓取网页信息
  • BeautifulSoup包用于网页信息的提取
import requests
from bs4 import BeautifulSoup

# 搜索关键字为“数据挖掘”,工作地区为北京的url
# dps为工作地区的参数,010为猎聘网为北京地区指定的区域号
url="https://www.liepin.com/zhaopin/?key=数据挖掘&dqs=010"

# 发起访问GET请求
page = requests.get(url = url)
# 输出返回信息 
print(page.url)
# 初始化 soup 对象,page.text为爬取到的带有html标签页面
soup = BeautifulSoup(page.text,"html.parser")
# 找到<h3>标签,实质是获取所有包含职位名称及链接的标签内容
soup = soup.find_all("h3")
#在每个<h3>中进行抽取链接信息
times =0
for i in soup:
    #有些<h3>标签不包含求职信息,做简要判断
    if i.has_attr("title"):
        #抽取链接内容
        href=i.find_all("a")[0]["href"]
        print(href)
    if times ==1 :
        print("i = -----")
        print(i)

    times=times+1
# 输出为:
# https://www.liepin.com/job/1929399435.shtml
# https://www.liepin.com/job/1925362683.shtml
# https://www.liepin.com/job/1924144611.shtml
# https://www.liepin.com/job/1919418647.shtml

一般情况下也可以用正则表达式替代如果你对正则表达式感兴趣,可以去看我的另外一篇博客:Regular-Express01。

基础知识

需要学习爬虫,首先要了解计算机网络上的基础知识。
我们一般通过url,使用浏览器来访问互联网上的网页信息。

HTTP请求方法

HTTP 定义了一组请求方法, 以表明要对给定资源执行的操作。指示针对给定资源要执行的期望动作. 虽然他们也可以是名词, 但这些请求方法有时被称为HTTP动词. 每一个请求方法都实现了不同的语义。

  • GET - GET方法请求一个指定资源的表示形式. 使用GET的请求应该只被用于获取数据。爬虫一般会使用GET请求获取信息。
  • HEAD - HEAD方法请求一个与GET请求的响应相同的响应,但没有响应体。

URL结构

一个完整的启用了ssh加密的url结构如下(如过未启用ssh加密,则将https替换为http)

使用百度搜索spide的urlr: https://www.baidu.com/s?wd=spider&pn=90#button

我们来对上面的url进行拆解,可以得到以下的组成公式

[协议名] + [域名] + [路径] + [可选-参数] + [可选-浏览器锚点]

其中,必选参数:[协议名] + [域名] + [路径] 为https://www.baidu.com/s,一般情况下我们不需要特别的进行关心,我们需要关心的是[可选-参数],这里为wd=spyder和pn=90,[可选-参数]和前面的内容用?来进行分隔,[可选-参数]中的变量使用&来进行分隔。

这里wd=spyder就是我们传送给服务器的参数,百度的服务器通过这个来知道我们查询的内容是spyder,以此来返回我们需要的查询结果。

#button是浏览器锚点,一般用于同一个页面内的移动,我们可以不需要关心。

网页结构

一个简单的html结构如下,我们使用爬虫每次所获取的,就是一个类似下面结构的文本数据,一般情况下,我们所需要获取的内容就在body标签内,一般使用正则表达式或者XPATH等技术获取自己期望获得的信息。

<!-- 当前网页的标准规范声明 -->
<!DOCTYPE html>
<html>
    <!-- 网页头信息 -->
    <head>
        <title>这里是网站的标题</title>
    </head>
    <!-- 网页css样式 -->
    <style>
        *{
            text-align:center;
        }
    </style>
    <!-- 网页内容信息 -->
    <body>
        <h1>这是一个标题</h1>
        <div>这里是网页的一个块</div>
        <a href='https://example.com'>这里是一个超链接</a>
    </body>
    <script>
        console.log('hello world')   // 网页的JavaScript脚本
    </script>
</html>

反-反爬虫技术

Python爬虫要经历爬虫、爬虫被限制、爬虫反限制的过程。当然后续还要网页爬虫限制优化,爬虫再反限制的一系列道高一尺魔高一丈的过程。爬虫的初级阶段,添加headers和ip代理可以解决很多问题。

登陆状态模拟 - UA

服务器通过用户请求中的User-Agent信息来识别用户的浏览器信息,所以我们可以通过自定义headers中的User-Agent的值来将我们的爬虫伪装成浏览器。不过此方法仅限于解决部分网站简单的反爬虫机制,一些网站需要使用代理IP解决。

IP代理

IP代理通过使用随机的IP来爬取目标网站,让服务器误以为是来自不同的电脑的正常访问,从而达到反-反爬虫的目的。具体细节可以参考这篇博客

模拟Cookies

对于某些网站,内容会通过判断用户Cookies来进行动态加载,这时我们还需要在headers信息中添加自己浏览器的Cookies来进行内容的爬取,具体方式和UA模拟很像,不过也要注意防止同一Cookies访问次数过多而导致Cookies被封。

手把手教你爬取猎聘网

猎聘网是我们本次的目标爬取网站,计划爬取其中北京,上海,深圳,广州,武汉,杭州等地区的数据挖掘,图像算法工程师,java后端,互联网产品经理职位等信息。

首先我们对猎聘网的url进行分析:

下方是未选择城市时数据挖掘职位的url链接:

https://www.liepin.com/zhaopin/?key=数据挖掘

当对城市如北京,进行选择后,浏览器上面的url变成了

https://www.liepin.com/zhaopin/?dqs=010?key=数据挖掘

你实际上看到的url可能比我上面的url要复杂,原因是我将其中不重要的变量进行了删除,只保留了我们需要的变量,即城市和职位,一般情况下,手动删除url中的变量,尝试几次即可找到我们需要的变量。

通过上方的分析,我们可以知道猎聘网查询职位的url构成为

https://www.liepin.com/zhaopin/?key=[职位名]&[dqs=城市码]

这样我们可以使用Python根据上方的公式来构建url爬取不同地点的不同职位,这里我通过手动尝试的方式,找到了不同城市的dqs值并构建数组,代码如下:

# 猎聘网基础url
url = 'https://www.liepin.com/zhaopin/?'
# 待爬取的职位
jobs = ['数据挖掘', '图像算法工程师', 'java后端', '互联网产品经理']
# 待爬取的城市,和对应的dqs
citys = ['北京', '上海', '深圳', '广州', '武汉', '杭州']
cityIds = ['010', '020', '050090', '050020', '170020', '070020']

有了以上的信息,我们通过循环即可构造不同城市不同职位的url,如果想要实现翻页,原理也类似,这里不再进行叙述。

我们可以对代码进行一个简单的测试

import requests

# 这里填入上方的几个数组

# 构建url
target_url = url+'key='+jobs[0]+'&dqs='+cityIds[0]

# 用get方法爬取数据
getData = requests.get(url=target_url)

# 将获得的数据使用utf-8格式进行转码
finalHtmlData = getData.content.decode("utf-8")

# 预期的输出为爬取到的html内容
print(finalHtmlData)

上方就是一个最简单的爬取方式,你可以通过循环结构来构建不同职位的url来进行爬取,同时也可以通过正则或者其他包来对获取的finalHtmlData进行解析,获取我们需要的数据。

下面再来演示通过正则输出目标数据,假如我们想找到finalHtmlData中所有的职位url

regExpUrl = '<a[^>]*href=\"(https://www.liepin.com/job[^"]*)\"[^>]*'

import re

# 正则表达式匹配
finalAData = re.compile(regExpUrl).findall(finalHtmlData)

# 预期输出为一堆的url
for i in finalAData:
    print(i)

正则表达式及其使用说明见我的另外一篇博客

上方代码的完整整理如下:

import requests

# 这里填入上方的几个数组
# 猎聘网基础url
url = 'https://www.liepin.com/zhaopin/?'
# 待爬取的职位
jobs = ['数据挖掘', '图像算法工程师', 'java后端', '互联网产品经理']
# 待爬取的城市,和对应的dqs
citys = ['北京', '上海', '深圳', '广州', '武汉', '杭州']
cityIds = ['010', '020', '050090', '050020', '170020', '070020']

# 构建url
target_url = url+'key='+jobs[0]+'&dqs='+cityIds[0]

# 用get方法爬取数据
getData = requests.get(url=target_url)

# 将获得的数据使用utf-8格式进行转码
finalHtmlData = getData.content.decode("utf-8")

# 预期的输出为爬取到的html内容
# print(finalHtmlData)

regExpUrl = '<a[^>]*href=\"(https://www.liepin.com/job[^"]*)\"[^>]*'

import re

finalAData = re.compile(regExpUrl).findall(finalHtmlData)

for i in finalAData:
    print(i)

完整代码的Github仓库地址:FindJobsApp

REF