一、记一部老作品
以fg对黑白日漫的理解,它的巅峰时期已经过去了。虽然仍然具有强大实力,但是随着数字媒体和移动时代的到来,以往的黑白漫受众者长大成人,新生的小年轻更容易被全彩漫画吸引,尤其是一些漫画的分镜方式已经完全是在为移动端服务,不得不说这些能够方便地在手机上阅读的漫画更容易流行。
《东京美食家》,是fg初中时期喜爱的漫画,它连载的时期已经接近黑白日漫巅峰的尾声了。当时,它拥有着高水准的作画,以及与民工漫相比,毫不拖沓的精彩剧情。因此,直到多年以后,它仍然会被fg记起。然而,它的优秀却为自身引来了灾难。连载一段时间后,它被动画化,而后大火,而后被封。
被封后,资源难找,fg很长一段时间没有追它。直到今天,在毕业设计做到一半的时候,我突然想起了它。也居然找到了资源,为了永久收藏,我决定爬取一份保存。今天,就让我们回到二刺螈,那个没有毕业设计的地方!
二、分析对手
目标网站不便透露。
首先简单尝试了chrome,requests,Beautifulsoup老三样。然而这次的对手不一般,它有一定反爬机制,即使尽可能把header做的漂亮也存在被ban的概率。而且,他的页面是JS动态生成,这样一来会有点不方便。由于fg不会JS,因此遇到了困难。
然而,真男人怎么会被困难困住。我想到了它!跟我一起大喊! selenium!
三、战斗
首先配置selenium环境。
chrome输入 chrome://version/
然后从以下链接下载chrome驱动:
http://chromedriver.storage.googleapis.com/index.html
版本号向下取整。
然后把下载好的chromedriver放到喜欢的目录下,有的老哥把它放在环境变量配置好的目录下,这样比较方便,没毛病。不过我就随便放了。
然后就可以用selenium了,selenium能够高仿浏览器get到网页,实际上它确实用了浏览器。
下面这个链接是selenium中文文档:
https://python-selenium-zh.readthedocs.io/zh_CN/latest/
我还是稍微介绍一下他的用法,它有普通用法和无头用法。普通用法会有个浏览器窗口跟着弹,无头用法就不会了,我觉得正常都得用无头,我就介绍无头吧。
chrome_options = webdriver.ChromeOptions()# 定义一个options对象
chrome_options.add_argument('--headless')# 无头
chrome_options.add_argument('--disable-gpu')# 有人说加它防出错。
# 注意下面这里的options,也有人会写chrome_options,好像更新过,options是新写法
driver = webdriver.Chrome(executable_path=path,options=chrome_options)#定义driver
driver.get(old_url) # get
html = driver.page_source
这里driver作用相当于requests,但是更好用,能反反爬。selenium本身也可以用来分析网页,但是我还是习惯美丽汤了,所以后面都是美丽汤处理的。
这之后,能够爬取了,但是有时候会被远程主机掐掉,说明还是有反爬机制在,把它想象成概率问题,那就反复尝试呗。所以fg用上了循环加try-except的处理。考虑到《东京美食家》有两部,咱再来个多线程,没毛病吧。
完整代码贴下面了,fg还是菜的。但是快乐就完事了!
今晚,我要在二刺螈的海洋里畅游,👴不睡了!
还是那句话,只有你们想不到,没有fg做不到,干就完了,奥里给!(纪念另一位美食家)
class Ghoul_Crawler(threading.Thread):
def __init__(self,id, home_url,save_path, chapter, page):
threading.Thread.__init__(self)
path = 'D:/NormalSoftwares/chromedriver/chromedriver2.exe'
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
chrome_options.add_argument('- -disable-gpu')
self.id = id
self.driver = webdriver.Chrome(executable_path=path, options=chrome_options)
self.home_url = home_url
self.save_path = save_path
self.chapter = chapter
self.page = page
def run(self):
# 找所有home page
print(self.id, 'start')
chapters = []
while(len(chapters) ==0):
self.driver.get(self.home_url)
html = self.driver.page_source
soup = BeautifulSoup(html, 'lxml')
links = soup.select('#chapter-list-1 li a')
for link in links:
data = dict()
data['link'] = 'https://www.manhuadui.com' + link['href']
data['title'] = link['title']
chapters.append(data)
if len(chapters) ==0:
print(self.id,"home failed!")
time.sleep(5)
print(self.id,"home page OK! Chapter:", len(chapters))
for i in range(self.chapter, len(chapters)):
self.crawl_chapter(chapters[i], len(chapters))
while (True):
try:
start = self.chapter
for i in range(start,len(chapters)):
self.crawl_chapter(chapters[i], len(chapters))
break
except:
time.sleep(5)
print(self.id, self.chapter, self.page, 'gg!')
print(self.id,"胜利!")
def crawl_chapter(self,chapter,chapter_len):
link = chapter['link']
self.driver.get(link)
html = self.driver.page_source
soup = BeautifulSoup(html, 'lxml')
# 确认页数
page_num = soup.select('.btmBtnBox select option')[-1].text
page_num = int(page_num[1:-1])
while (True):
try:
start = self.page
for j in range(start, page_num+1): # 每一页
self.crawl_page(link+'?p='+str(j), self.save_path + chapter['title'], page_num)
self.chapter = (self.chapter + 1)
break
except:
time.sleep(5)
def crawl_page(self, link, save_path,page_num):
self.driver.get(link)
html = self.driver.page_source
soup = BeautifulSoup(html, 'lxml')
img = soup.select('.chapter-view .comic_wraCon #images>img')[0]['src']
self.save_img(img, save_path, str(self.page) + '.jpg')
self.page = (self.page)%page_num+1
def save_img(self, link, path, name):
if not os.path.exists(path):
os.mkdir(path)
urllib.request.urlretrieve(link, path + '/' + name) # , reporthook=loading)
def loading(self, blocknum, blocksize, totalsize):
"""
回调函数: 数据传输时自动调用
blocknum:已经传输的数据块数目
blocksize:每个数据块字节
totalsize:总字节
"""
percent = int(100 * blocknum * blocksize / totalsize)
if percent > 100:
percent = 100
print("\r正在下载>>>{}%".format(percent), end='')
time.sleep(0.5)