python 爬取https://wall.alphacoders.com上的壁纸
0,环境
python3.7
库:requests,BeautifulSoup4
1,目标
https://wall.alphacoders.com/popular_searches.php
这是网页search页面上前面几个热搜
点开第一个里面有很多图片,
目标就是爬取热搜前十所有这些壁纸
2,网站源码分析:批量获取热搜网址
先要获取热搜的网址:
进入https://wall.alphacoders.com/popular_searches.php 打开开发者选项F12
(有点不清晰,关键信息已经画出来了)
网址所在节点特征:
1)顶上是h3,其class=“search-term”
2)网址在这个h3子节点a标签中的href中
于是有了相关代码:
# search.py
import requests
from bs4 import BeautifulSoup
def search_all(url="https://wall.alphacoders.com/popular_searches.php", index=10):
html = requests.get(url) # index:排名数默认10,url指定了.
soup = BeautifulSoup(html.text, "lxml")
n = index
url_list = [] #存储热搜网址的列表
for i in soup.find_all(name='h3', attrs={'class': 'search-term'}): #寻找符合条件的父节点
url1: str = i.a["href"] #获取i的第一个a子节点的href属性值
url_list.append(url1)
n = n - 1
if n == 0:
return url_list #个数到了就返回
return url_list
if __name__ == "__main__":
print(search_all())
3,网站源码分析:批量获取图片
<img class="img-responsive big-thumb" width="600" height="375" src="https://images3.alphacoders.com/102/thumbbig-102135.jpg" alt="Earth Landscape HD Wallpaper | Background Image">
可以看出特征有如下几点:
- 标签名为img
- class = “img-responsive big-thumb”
- 网址在src属性值中
于是有了代码:
# main.py (与search.py同目录)
import requests
import threading
import time
from search import search_all
# import re
from bs4 import BeautifulSoup
class Spider:
def __init__(self, web="https://wall.alphacoders.com/search.php?search=landscape"):
self.web = web
def get_one(self):
html = requests.get(self.web)
soup = BeautifulSoup(html.text, 'lxml')
for i in soup.find_all(name='img', attrs={'class': 'img-responsive'}):
url = i['src'] #获取图片网址
threading.Thread(target=Downloader(url).work).start() #关于多线程用法自行学习,如不熟的可以改成Downloader(url).work()
# 封装事务
class Downloader:
def __init__(self, url):
self.url = url
print(f"At :{url}")
def work(self):
print(f"start..{self.url}")
name = self.url.split('/')[-1] # 获取网址对应的文件名
with open(f"image/{name}", 'wb') as f:
f.write(requests.get(self.url).content) # get网址内容并以二进制形式写入相应文件
print(f"end..{self.url}")
if __name__ == "__main__":
urls = search_all()
for j in urls:
threading.Thread(target=Spider(web=j).get_one).start()
项目结构如下:(一定要提前创建一个image文件夹, image.zip不需要啊)
注意!
1,main.py里面几乎都是采用多线程下载,速度虽然提升了
但开销非常大,建议电脑配置不好的将main.py最后几行代码改成阻塞代码即:
if __name__== "__main__":
t1 = time.time()
urls = search_all()
for j in urls:
Spider(web=j).get_one()
print(f"use: {time.time()-t1} s")
2,代码编辑可以在pycharm里面,但最好在外面的命令行跑main.py 因为我的pycharm因此死机了…
跑的结果:
控制台输出没有截图.
4,后记
爬图如此《顺利》原因:
网站似乎并没有对频繁同IP请求进行封杀
甚至User-Agent也没有伪装
如果有兴趣的同学可以查一查如何伪装IP和请求头.