今天我们来爬取另外个网站https://tu.fengniao.com/ 没错就是这个地址,不用翻其他的标签栏,,这个网站最大的特点就是一直往下翻都会有一个加载的操作,不断加载新的图片上去。可以试着滑动鼠标不断往下翻,不断往下翻,不断往下翻。。。。

Python《搞事情==蜂-鸟-图-片(二)》_html

与上一篇博文不同的是,我们不是拿到第一张图片点进去,然后while循环去找下一张图片,今天我们换了个大标签,仔细发现网站的url也不一样了,而且我们今天是使用selenium来模拟实现鼠标的往下滑动,这样全部的图片group就能拿到了,这样我们就可以使用正常的方式解析出所有的图片。

第一部分我们先试一试模拟鼠标上下滑动的

import time

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chromeExeLoc = 'D:/software/chrome/chromedriver_win32/chromedriver.exe'

# 无头浏览器 这样浏览器就不会弹出那个chrome的web浏览器界面
options = Options()
options.add_argument('--headless')

browser = webdriver.Chrome(chromeExeLoc, options=options)
browser.maximize_window()
browser.implicitly_wait(5)

browser.get('https://tu.fengniao.com/')
js="window.scrollTo(0,document.body.scrollHeight)"

while 1:
browser.execute_script(js)
a_s = browser.find_elements_by_class_name('picA')
print('Total Ims group is: ' + len(a_s))
time.sleep(5)

效果如下:

Python《搞事情==蜂-鸟-图-片(二)》_爬虫_02

发现,效果是可以的,成功模拟了鼠标往下滑动,且获得了越来越多的图片组。

思路是,一个线程去不断地模拟滑动,然后有了新的数据了,就去给一个线程去操作下载。
为了演示方便,我们保守点,别太贪心,每个子标签下只抓取200个图片组。

那么进入一个照片组后我们如何爬取呢?

假如我们进入到 http://bbs.fengniao.com/forum/pic/slide_101_11158474_100945009.html

发现这个该组图的所有图片都是在一个页面存在的,也就是点击下一页的时候不用刷新页面,所以我们需要从本html中获得所有的img信息。

Python《搞事情==蜂-鸟-图-片(二)》_chrome_03

于是我就把“下载原图”的所在的img的url拿了出来。

Python《搞事情==蜂-鸟-图-片(二)》_selenium_04

做个搜索,果然一下就搜到了所有图片的url信息。

所有的图片信息都是存在于下面这个js的这个picList变量里面的

Python《搞事情==蜂-鸟-图-片(二)》_chrome_05

而且地址都是很完整的,只不过存在一些重复罢了。因此我们通过这个变量的字符串即可得到所有的这个组图的图片。
测试代码如下:

import time
import os
import requests
from bs4 import BeautifulSoup

def find_all(sub, s):
index_list = []
index = s.find(sub)
while index != -1:
index_list.append(index)
index = s.find(sub, index + 1)

if len(index_list) > 0:
return index_list
else:
return -1

def tagSpider(url):

html = BeautifulSoup(requests.get(url).text, features="html.parser")
html = str(html)
a = html[html.find("var picList = eval") : html.find("var picListNum = picList.length")]
idx1 = find_all('https', a)
idx2 = find_all('jpg', a)
print(idx1)
print(idx2)

bb = set()
for i in range(len(idx1)):
img_url = a[idx1[i] : idx2[i]+3]
img_url = img_url.replace('\\', '')
bb.add(img_url)
print(bb)

url = 'http://bbs.fengniao.com/forum/pic/slide_101_11151649_100820943.html'
tagSpider(url)

效果如下:

Python《搞事情==蜂-鸟-图-片(二)》_selenium_06

嗯呢,不错,组图的数量也是没错的。

上面写了俩demo,接下来我们需要把这几个demo拼接在一起了。

那么完整代码如下:

import time
from concurrent.futures import ThreadPoolExecutor
import time
import os
import re
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

rootrurl = 'https://tu.fengniao.com'
save_dir = 'D:/estimages/'
chromeExeLoc = 'D:/software/chrome/chromedriver_win32/chromedriver.exe'

headers = {
"Referer": rootrurl,
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
'Accept-Language': 'en-US,en;q=0.8',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive'
} ###设置请求的头部,伪装成浏览器

def saveOneImg(dir, img_url):
new_headers = {
"Referer": img_url,
'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
'Accept-Language': 'en-US,en;q=0.8',
'Cache-Control': 'max-age=0',
'Connection': 'keep-alive'
} ###设置请求的头部,伪装成浏览器,实时换成新的 header 是为了防止403 http code问题,防止反盗链,

try:
img = requests.get(img_url, headers=new_headers) # 请求图片的实际URL
if (str(img).find('200') > 1):
with open(
'{}/{}.jpg'.format(dir, img_url.split('/')[-1]), 'wb') as jpg: # 请求图片并写进去到本地文件
jpg.write(img.content)
print(img_url)
jpg.close()
return True
else:
return False
except Exception as e:
print('exception occurs: ' + img_url)
print(e)
return False


def find_all(sub, s):
index_list = []
index = s.find(sub)
while index != -1:
index_list.append(index)
index = s.find(sub, index + 1)

if len(index_list) > 0:
return index_list
else:
return -1

def downPics(dir, url):

# 得到所与图片的链接
html = BeautifulSoup(requests.get(url).text, features="html.parser")
html = str(html)
a = html[html.find("var picList = eval") : html.find("var picListNum = picList.length")]
idx1 = find_all('https', a)
idx2 = find_all('jpg', a)

# 图片去重与,url整理组装
bb = set()
for i in range(len(idx1)):
img_url = a[idx1[i] : idx2[i]+3]
img_url = img_url.replace('\\', '')
bb.add(img_url)

# 逐个下载啊
for img in bb:
saveOneImg(dir, img)


def getSubTitleName(str):
cop = re.compile("[^\u4e00-\u9fa5^a-z^A-Z^0-9]") # 匹配不是中文、大小写、数字的其他字符
string1 = cop.sub('', str) # 将string1中匹配到的字符替换成空字符
return string1

def tagSpider(tag, url):
# 无头浏览器 这样浏览器就不会弹出那个chrome的web浏览器界面
options = Options()
options.add_argument('--headless')

browser = webdriver.Chrome(chromeExeLoc, options=options)
browser.maximize_window()
browser.implicitly_wait(5)

browser.get(url)
js = "window.scrollTo(0,document.body.scrollHeight)" # 定义鼠标滑倒底部的动作

pics = None
while 1:
browser.execute_script(js) # 每次往下滑到底部,直到有了200个组图就推出了
pics = browser.find_elements_by_class_name('picA')
print('current length is %d:', len(pics))
if len(pics) >= 200:
break
time.sleep(5)

# 开始爬取图片
for li in pics:

# 创建目录
subDir = getSubTitleName(li.find_element_by_class_name('pic').get_attribute('title'))
new_dir = '{}{}/{}'.format(save_dir, tag, subDir)
if not os.path.exists(new_dir):
os.makedirs(new_dir)

# 下载组图
downPics(new_dir, li.get_attribute('href')) # 爬取每个图片组


def getAllTags():
list = {}
html = BeautifulSoup(requests.get(rootrurl).text, features="html.parser")
a_s = html.find('div', {'class' : 'labelMenu module90'}).find_all('a')
for a in a_s:
list[a.get_text()] = rootrurl + a.get('href')
return list


if __name__ == '__main__':
# 获得所有标签
taglist = getAllTags()
print(taglist)
#
# 给每个标签配备一个线程
# with ThreadPoolExecutor(max_workers=15) as t: # 创建一个最大容纳数量为20的线程池
# for tag, url in taglist.items():
# t.submit(tagSpider, tag, url)

# 单个连接测试下下
tagSpider('美女', 'https://tu.fengniao.com/13/')

# 等待所有线程都完成。
while 1:
print('-------------------')
time.sleep(1)

所有效果如下:

Python《搞事情==蜂-鸟-图-片(二)》_selenium_07


Python《搞事情==蜂-鸟-图-片(二)》_selenium_08

Python《搞事情==蜂-鸟-图-片(二)》_selenium_09

Python《搞事情==蜂-鸟-图-片(二)》_html_10