目录
一、requests模块
1.res = requests.get(url, headers)
返回值res是requests.models.Response类对象
2.requests模块res属性 对应 urllib.request模块res的方法:
res.text -> res.read().decode('utf8)
tes.content -> res.read()
tes.status_code -> res.getcode()
res.url -> res.geturl()
二、互联网图片抓取
说明:
图片、音频、视频在计算机中均已二进制方式存储
实现:
找到所要抓取图片的url地址
向图片的url地址发请求,获取二进制响应内容(bytes)
正常打开文件,将响应内容以wb方式保存至本地
三、xpath的使用
1.注意:
只要涉及到条件,加[ ]://li[@class='xxx'] //li[2]
只要获取属性值,加@://li[@class='xxx'] //li/@href
2.//:从所有节点中查找(包括子节点和后代节点)
3.@:获取属性值
使用场景1(属性值作为条件)://div[@class='xxx']
使用场景2(直接获取属性值)://div[@class='xxx']/a/img/@src
4.匹配多路径(或)
xpath表达式1 | xpath表达式2 | xpath表达式3
5.contains():匹配属性值中包含某些字符串节点
查找id属性值中包含字符串"car_"的li节点
//li[contains(@id, "car_")]
6.text():获取节点的文本内容
查找所有汽车的价格
//ul[@class='CarList']/li/p[@class='price']/text()
7.总结
使用xpath表达式匹配结果为两种情况:字符串和节点对象,解析如下:
(1)xpath表达式的末尾为:/text()、/@href 得到的列表中为字符串
(2)其他剩余所有情况得到的列表中均为 节点对象
四、lxml解析库
1.安装
Ubuntu:sudo pip3 install lxml
Windows:python -m pip install lxml
2.使用流程
导模块:from lxml import etree
创建解析对象:parse_html = etree.HTML(html)
解析对象调用xpath:r_list = parse_html.xpath('xpath表达式')
3.注意
只要使用了xpath,则得到的数据类型一定为 列表 类型
五、综合案例
百度贴吧图片抓取
目标:抓取指定贴吧的所有帖子中的图片
程序运行效果:
请输入贴吧名:赵丽颖
请输入起始页:1
请输入终止页:2
则程序将抓取赵丽颖吧前2页的所有帖子中的所有图片到本地当前目录
代码如下:
from urllib import parse
import requests
from lxml import etree
import os
import time
import random
class TieBaImg(object):
def __init__(self):
self.word = input('请输入贴吧名:')
self.start = input('请输入起始页:')
self.end = input('请输入终止页:')
self.url = 'https://tieba.baidu.com/f?kw={}&pn={}'
self.filename = './tieba_images/{}/'.format(self.word)
self.page = int(self.start) # 记录当前抓取的第几页数据
self.link_count = 1 # 记录当前抓取页面第几个链接
self.img_count = 1 # 记录一个链接里抓取的图片数目
# if not os.path.exists(filename):
# os.makedirs(filename)
# self.file = open(filename, 'wb')
def get_html(self, url):
"""
功能函数:获取网页源码html
:param url:
:return:
"""
headers = {'User-Agent':'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)'}
html = requests.get(url=url, headers=headers).text
return html
def get_href(self, html, x):
"""
功能函数:使用xpath,获取html中所需要的链接
:param html:
:return:
"""
parse_html = etree.HTML(html) # 创建解析对象
href_list = parse_html.xpath(x)
return href_list
def parse_data(self):
"""
功能函数:解析数据
:return:
"""
word = parse.quote(self.word) # 将输入的关键字转为url编码
first_x = '//ul[@id="thread_list"]//div[@class="threadlist_title pull_left j_th_tit "]/a/@href'
second_x = '//div[@class="d_post_content_main d_post_content_firstfloor"]//img/@src'
for i in range(int(self.start), int(self.end) + 1):
url = self.url.format(word, (i-1)*50)
first_html = self.get_html(url)
# print(first_html)
href_list = self.get_href(first_html, first_x) # 获取一级页面中二级页面的链接
# print(href_list)
time.sleep(random.uniform(1, 8)) # 每发起一次请求随机休眠的时间
for href in href_list:
second_url = 'https://tieba.baidu.com{}'.format(href) # 二级页面的链接
second_html = self.get_html(second_url)
src_list = self.get_href(second_html, second_x)
# print(src_list)
for src in src_list:
direct = '{}page_{}link_{}/'.format(self.filename, self.page, self.link_count)
self.save_img(direct, src) # 保存一张图片到本地
print('成功保存第 {} 页链接 {} 的图片 {} '.format(self.page, self.link_count, self.img_count))
self.img_count += 1
self.link_count += 1
self.img_count = 1 # 图片数量重至1
time.sleep(random.uniform(1, 8)) # 每发起一次请求随机休眠的时间
self.page += 1
def save_img(self, filename, url):
"""
功能函数:保存一张图片至本地
:param url:
:return:
"""
if not os.path.exists(filename):
os.makedirs(filename)
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'}
img_b = requests.get(url=url, headers=headers).content # 获取图片的字节编码
with open('{}img_{}.jpg'.format(filename, self.img_count), 'wb') as f:
f.write(img_b)
if __name__ == '__main__':
img = TieBaImg()
img.parse_data()