使用requests+lxml爬取zol桌面壁纸
明确爬取路线
我们要爬取的是ZOL桌面壁纸的壁纸下载排行榜系列壁纸
而要获取到每个下载排行榜系列的图片必须点击对应专题进入专题详情页才能看到专题对应的壁纸,这些壁纸就是我们要爬取的对象,归纳一下:
- 获取到整个首页html
- 定位到各个下载排行榜的系列专题,取出指定专题的标题和详情页链接
- 拼接完整链接以循环的方式再次发起对专题详情页的请求
- 得到详情页的html,取出每个壁纸的下载链接进行下载保存。
具体实现步骤请继续往下看
实现技术
requests、lxml、re和os这四个python库,其中requests、lxml是第三方库,需要另行安装,使用pip install requests pip install lxml
安装即可
实现与代码解析
- 通过检查浏览器源代码发现可以直接看到首页所有代码元素,由此说明ZOL桌面壁纸没有做反爬虫,所以直接发起请求获取首页html
# 主页url
index_url = 'http://desk.zol.com.cn'
# 主页请求头
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36'
}
# 发起主页请求
response = requests.get(url=index_url + '/', headers=header)
response
是请求返回体,我们可以通过它得到首页htnml代码,现在我们要定位到下载排行榜代码位置,定位代码我们可以在网站按F12启动开发者模式
如下图,开启后先点击1
处,就能启动定位功能,然后把鼠标定位到2
并点击,在3
处就能到定位到的代码块了
- 定位完成后,我们需要得到它的xpath
如图所示,点击要查询的代码块右键,选择Copy
->Copy full XPath
即可得到 - 使用获取到的xpath得到各个专题链接再次发起请求
# 将请求回来的数据lxml化,方便使用xpath获取数据
response_lxml = etree.HTML(response.text)
# 通过xpath获取定位到所有壁纸类型下载排行版
side_response = response_lxml.xpath("//div[@class='side']/div[@class='model mt15']")
# 通过循环操作每个壁纸类型下载排行版
for side_item in side_response:
# 壁纸类型
side_title = side_item.xpath("./div[@class='mod-header']/text()")[0]
# 该类型下所有的壁纸专题
li_response = side_item.xpath("./ul/li")
# 通过循环操作每个壁纸专题
for li_item in li_response:
try:
# 专题标题
li_title = li_item.xpath("./a/text()")[0]
# 专题独立页面url
li_url = li_item.xpath("./a/@href")[0]
# 拼接合成专题url
desk_url = index_url + li_url
# 发起专题页面内容请求
desk_response = requests.get(url=desk_url, headers=header)
# 将请求回来的数据lxml化,方便使用xpath获取数据
desk_lxml = etree.HTML(desk_response.text)
desk_lxml
是详情页的html代码,通过desk_lxml我们可以定位和拼接出壁纸的下载链接(代码衔接在步骤4的代码后面
)
# 正则表达式匹配专题的图片展示数
img_index_search = re.compile(r"/(\d+))")
img_index_xpath = desk_lxml.xpath("//h3/span/text()")[1]
img_index = re.search(img_index_search, img_index_xpath).group(1)
# 正则表达式匹配专题url的独特数字
img_url_index_search = re.compile(r"_(.*?)_(.*?).html")
img_url = index_url + desk_lxml.xpath("//dd[@id='tagfbl']/a[@id='1366x768']/@href")[0]
img_url_index_1 = re.search(img_url_index_search, img_url).group(1)
img_url_index_2 = re.search(img_url_index_search, img_url).group(2)
- 这个时候我们要考虑好下载保存方式,因为是有多个下载排行榜的,所以存储时需要区分开来
# 为每个排行榜生成一个目录,判断目录是否存在 这个方法放到全局中
def is_exits(path):
path = path.strip()
path = path.rstrip('\\')
is_exit = os.path.exists(path)
if not is_exit:
os.mkdir(path)
print(path + '创建成功!')
else:
print(path + '已经存在!')
#(代码衔接在步骤5的代码后面)
# 调用is_exits判断目录是否存在,不存在则创建目录,存在则不做另外操作
is_exits(dir_name + "\\handle_desk.zol\\wallpaper\\" + li_title + "\\")
- 这个时候我们已经得到了所有壁纸的下载链接,因为每个专题的壁纸是多个的,我们页要通过循环来遍历下载(
代码衔接在步骤5的代码后面
)
# 根据每个专题的图片数定义循环次数
for index in range(int(img_index)):
# 根据获取到的内容拼接每个图片独立的页面url
img_install_html_url = 'http://desk.zol.com.cn/showpic/1366x768_' + str(int(img_url_index_1) + index) + '_' + img_url_index_2 + '.html'
# 防止拼接的图片页面url
try:
# 请求每个图片的独立页面
img_install_html_response = requests.get(url=img_install_html_url, headers=header)
# 将请求回来的数据lxml化,方便使用xpath获取数据
img_install_lxml = etree.HTML(img_install_html_response.text)
# 获取到页面中提高的图片下载url
img_install_url = img_install_lxml.xpath("//body/img[1]/@src")[0]
# 请求图片下载url
img_install_url_response = requests.get(url=img_install_url, headers=header)
- 最后对每个壁纸的链接发起请求,通过响应体得到图片数据,进行保存
# 根据每个专题的图片数定义循环次数
for index in range(int(img_index)):
# 根据获取到的内容拼接每个图片独立的页面url
img_install_html_url = 'http://desk.zol.com.cn/showpic/1366x768_' + str(int(img_url_index_1) + index) + '_' + img_url_index_2 + '.html'
# 防止拼接的图片页面url
try:
# 请求每个图片的独立页面
img_install_html_response = requests.get(url=img_install_html_url, headers=header)
# 将请求回来的数据lxml化,方便使用xpath获取数据
img_install_lxml = etree.HTML(img_install_html_response.text)
# 获取到页面中提高的图片下载url
img_install_url = img_install_lxml.xpath("//body/img[1]/@src")[0]
# 请求图片下载url
img_install_url_response = requests.get(url=img_install_url, headers=header)
# 实现图片下载操作,并进行归类
with open(dir_name + '\\handle_desk.zol\\wallpaper\\' + li_title + '\\' + str(int(img_url_index_1) + index) + '.jpg', 'wb') as f:
f.write(img_install_url_response.content)
print("排行版专题:" + side_title + "\n")
print("图片专题:" + li_title + "\n")
print("图片url:" + img_install_url + "\n")
print("下载成功~~~~~~~~")
print("---------------------------------------------------------")
except:
print(side_title + "---->" + li_title + "中请求的图片页面url->" + img_install_html_url + "不存在")
print("---------------------------------------------------------")
print("---------------------------------------------------------")
continue
break
except Exception as e:
print(e)
优化方向
- 可以使用
selenium
模拟点击操作,这样就能直接进入详情页而不用进行二次请求 - 这个方案循环次数太多,可以用
asyncio
异步或者多线程
提高爬取速度
总结
解析可能有点乱,请多包涵,可以直接看源代码 -> 源代码
本文来自博客园,作者:七夜魔手,转载请注明原文链接:https://www.cnblogs.com/ranbox/p/18461091