一、urllib库基础
1.urllib可以提供一个高级接口,通过url在网上获取数据
2.url编码是基于utf-8的,在url中不允许出现空格
3.urllib方法:
(1)urllib.request.urlopen:发送请求,即发送想要爬取的网页链接,会返回网页的html代码
request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
参数含义:
①url: 输入一个链接,该链接可以是一个字符串或者一个 Request 对象
②data: 参数为一个字节类型对象 ,表示发送到服务器的附加数据。如果不需要发送数据,可以为None。
③timeout: 连接时的阻塞等待时间,如果不设定该参数,将启用全局默认的超时时间。
④cafile和capath: 用来为https请求指明一套可信的CA证书。cafile 必须是包含了一套证书的单独的文件,capath则应该指定这些证书文件的目录。
⑤context: 如果 context 参数被指定,它必须是一个带有各样SLL选项的ssl.SSLContext实例。
(2)urllib.request.Request:抓取URL内容,即发送一个GET请求到指定的页面,然后返回HTTP的响应:
注:urllib.request返回的响应经read()读取及设定编码格式为utf-8后,会将HTML代码以字符串形式返回,需要使用lxml库的etree模块转换成HTML代码
urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
①url: 请求链接,此参数为必传参数。
②data: 此参数为一个字节类型对象 ,表示发送到服务器的附加数据。如果不需要发送数据,可以为None。
③headers: 此参数为 HTTP 请求的头部信息,参数形式为字典。
④origin_req_host: 此参数为请求方的 host 名称或者 IP 地址。
⑤unverifiable: 此参数表示该请求是否可以验证,默认值为False,即用户没有权限接收该请求的结果。如果需要接收,需要将 unverifiable 的值设置成 True。
⑥method: 此参数为是发起的 HTTP 请求的方式,可以为GET、POST、DELETE、PUT等。
二、xpath解析HTML
1.xpath简介:xpath是一门在XML和HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历,从而实现对HTML代码的解析功能。
2.xpath语法
(1)常用路径表达式
(2)谓语:被嵌在方括号内,用来查找某个特定的节点或包含某个制定的值的节点
(3)选取多个路径:使用“|”运算符可以选取多个路径
(4)xpath轴:轴可以定义相对于当前节点的节点集
(5)功能函数:使用功能函数能够更好的进行模糊搜索
例:
import urllib.request as ur
from lxml import etree
import requests
for i in range(1,5): #循环爬取四页数据
url = "http://bj.ganji.com/zpdiangong/o%d/"%i #输入网页链接,链接中%d为循环的页数,链接后的%i可以将循环变化后的i替换为链接中的d值
print("正在爬取第",i,"页 ",url)
html_str = requests.get(url).text #获取网页信息,返回str形式的网页HTML代码
html = etree.HTML(html_str) #把字符串形式的html转换成HTML
names = html.xpath("//dl[@class='list-noimg job-list clearfix new-dl']") #解析HTML代码
#注:如果只加一个/,则必须从跟标签(HTML标签)开始查找,如果加两个//,则可以直接定位到想要得到的标签。通过属性进行筛选时,需要用[]将属性括起来,并在属性之前加@
print(names)
break
三、urllib爬虫操作实例——爬取赶集网就业信息
1.导入相关库
import urllib.request as ur #爬取网页信息,获得网页的HTML响应
import requests #爬取网页信息,代码较上一种更简单
from lxml import etree #将爬取的HTML响应转换为HTML代码
import xlrd #将爬取的数据写入Excel表格中
from xlutils.copy import copy
import random #生成随机数,用于在列表中随机选取可用的代理ip
from telnetlib import Telnet #检测ip是否可用
2.设置代理ip
#添加代理ip
ip_ports = ["188.131.137.105:8118", "136.228.128.6:46196","163.125.114.178:8118"]
def get_ip_port():
ip_port = random.choice(ip_ports) #从ip_ports列表中随机抽取代理ip
# 检测ip是否可用
try:
Telnet(ip_port.split(":")[0], ip_port.split(":")[1], timeout=0.5)
print(ip_port,"有效")
result = True
except:
result = False
if result:
proxy_support = ur.ProxyHandler({"http": ip_port})
opener = ur.build_opener(proxy_support)
ur.install_opener(opener)
else:
print(ip_port,"无效")
ip_ports.remove(ip_port)
get_ip_port()
3.获取赶集网职位类别
#获取赶集网职位类别
def get_job_type(url,headers):
html_str = requests.get(url,headers=headers).text #获取网页信息返回str形式的HTML代码
#headers为浏览器信息,用于伪装爬虫请求,放置被服务器判定为恶意程序
#注:get中的属性**kwargs:不定长参数,**时为字典,*时为元组
html = etree.HTML(html_str) #将字符串转换为HTML代码
types = html.xpath("//div[@class='f-hot']/dl/dd/i/a/@href") #解析HTML代码 获取职位类型,用于拼接链接
names = html.xpath("//div[@class='f-hot']/dl/dd/i/a/text()") #获取职位类型文字
return types
4.根据类别爬取数据
def get_data(url,headers):
with xlrd.open_workbook("diangong.xls") as work_book: #可自动关闭Excel表格
sheet = work_book.sheet_by_index(0)
index = sheet.nrows
work_book_copy = copy(work_book)
sheet_copy = work_book_copy.get_sheet(0)
html_str = requests.get(url,headers=headers).text
html = etree.HTML(html_str)
dls = html.xpath("//dl[@class='list-noimg job-list clearfix new-dl']")
for dl in dls:
try:
name = dl.xpath("./dt/a/text()")[0]
company = dl.xpath("./dt/div/a/@title")[0]
sheet_copy.write(index, 0, name)
sheet_copy.write(index, 1, company)
work_book_copy.save("diangong.xls")
index += 1
except:
pass
5.爬取页数
#爬取页数
def get_total_pages(url,headers):
html_str = requests.get(url,headers=headers).text
html = etree.HTML(html_str)
total_page = html.xpath("//div[@class='pageBox']/ul/li[last()-1]/a/span/text()")[0]
# li[last()-1]为倒数第二个li标签
return total_page
if __name__ == "__main__":
headers = {
"Accept": "*/*",
"Content-Type": "text/plain;charset=UTF-8",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"
}
url_base = "http://bj.ganji.com" #将此链接与职位类型拼接,即可得到职位类别链接
url = url_base+"/zhaopin/"
ts = get_job_type(url,headers) #将get_job_type方法的返回值设为ts,即ts为所有职位类别组成的列表
for t in ts:
get_ip_port()
url0 = url_base + t #拼接得到职位类别链接
tp = int(get_total_pages(url0, headers)) #总页数,将get_total_pages方法的返回值改为int类型
for i in range(1, tp + 1):
print("正在获取", t, "类型的第", i, "页,共", tp, "页")
url0_0 = url0 + "o%d/" % i
get_data(url0_0, headers)