2022年3月至6月,上海經(jīng)歷了自疫情以來最嚴(yán)格的封控。2022年3月28日上午5時(shí),上海市浦東、浦南及周邊區(qū)域被列為第一批核酸篩查區(qū)域,正式進(jìn)入分區(qū)封控模式。4月2日,上海正式進(jìn)入全域靜態(tài)管理狀態(tài)。5月29日,上海宣布進(jìn)入社會(huì)面全面復(fù)工復(fù)產(chǎn)階段,直到5月30日,仍有531個(gè)區(qū)域,共19萬余人處于封控管理之中。
許多行業(yè)因?yàn)橐咔槎艿接绊懀瑫?huì)展是其中之一。在上海這個(gè)曾被稱作“會(huì)展之都”的城市里,從業(yè)者的嚴(yán)冬已經(jīng)持續(xù)了一年多。自去年6月以來,上海的會(huì)展相比去年同期數(shù)量銳減。在經(jīng)歷了2022年上半年的疫情之后,無論是對(duì)參展者還是展會(huì)主辦方來說,未來都是不確定的。
5月初,國內(nèi)規(guī)模最大的綜合性同人展會(huì)之一,第29屆“Comicup魔都同人祭”(Comicup 29)再一次發(fā)布了延期公告。Comicup平均每半年一屆,Comicup 29本應(yīng)在2021年12月舉行,這是它第三次延期,距離Comicup 28已經(jīng)過去了整整一年。根據(jù)Comicup組委會(huì)的說法,延期時(shí)間未定。
在延期的這段時(shí)間里,Comicup經(jīng)歷了什么?Comicup 29什么時(shí)候才能到來?我們與Comicup策展人香菇取得了聯(lián)系,討論數(shù)次延期背后的原因,與未來可能的方向。
靜默之前
2021年11月。
直到發(fā)布延期公告前的最后一刻,香菇都還以為Comicup 29可以如期舉行。
2021年的上海,會(huì)展行業(yè)從業(yè)者們并不好過。相比起2020年,這一年在上海舉辦的展會(huì)數(shù)量少了許多。8月,有媒體報(bào)道,盡管沒有接到上級(jí)部門關(guān)于展會(huì)取消或延期的文件,仍有多個(gè)展會(huì)宣布延期。
但香菇的態(tài)度一直很樂觀:“我們那個(gè)時(shí)候覺得自己很安全,畢竟Comicup檔期很晚,都接近新年了。”
這種樂觀源于主辦方的收益一直不錯(cuò)。上一屆付完場地費(fèi)用之后,資金尚有結(jié)余,她們還開了一個(gè)新的原創(chuàng)漫畫項(xiàng)目。“漫畫項(xiàng)目一開始都是虧的,要花錢嘛。”香菇解釋,“但我們手上暫時(shí)有錢,不怕虧。”
如今,Comicup的策劃與舉辦已經(jīng)十分正規(guī)而體系化,香菇她們因此成立了一家公司。她向我介紹了公司的組成部分:負(fù)責(zé)展會(huì)的Comicup組委會(huì)、負(fù)責(zé)無差別同人站CPP的開發(fā)與運(yùn)營部門,以及負(fù)責(zé)周邊制作與發(fā)行的文創(chuàng)部門。值得一提的是,文創(chuàng)是現(xiàn)在唯一還在盈利的部門。
公司桌面上的立牌是文創(chuàng)部門的產(chǎn)品
疫情爆發(fā)之前,公司收入絕大部分依賴于展會(huì)。展會(huì)的收入主要分為兩個(gè)部分:門票與參展費(fèi)。參展費(fèi)又可以細(xì)分為商業(yè)展位和同人攤位。對(duì)于Comicup來說,商業(yè)入駐展位在收入中的占比要遠(yuǎn)高于同人攤位,盡管后者才是展會(huì)的主力軍。香菇估算了一個(gè)大致的收入占比:門票占40%,商業(yè)展位費(fèi)占50%,同人攤位費(fèi)占10%。
這與Comicup低廉的同人攤位費(fèi)定價(jià)有關(guān)。根據(jù)經(jīng)驗(yàn),香菇十分熟悉同人志作者的收入:除了少數(shù)熱門“大手”,大部分作者只能賣出幾十本,按每本80元的定價(jià)算,加起來也不過幾千元。如果扣掉印刷成本與前往上海的交通、住宿費(fèi)用,同人作者幾乎沒有利潤可言。更加隱性的成本是作者付出的時(shí)間和精力。一個(gè)自由畫手曾透露,如果在繪制商業(yè)稿件的同時(shí)創(chuàng)作同人漫畫,差不多會(huì)讓她的收入減半,付出時(shí)間,但不算賺錢。考慮到這一點(diǎn),在同人方面,Comicup只收取每攤200元的攤位費(fèi)。在CPP上完成作者認(rèn)證,確定作者本人參展之后,還能額外減免50元。
香菇透露,目前舉辦一場Comicup的成本已經(jīng)到了千萬元級(jí)別。2015年,公司曾接受過一輪融資,但當(dāng)時(shí)百萬元左右的融資金額對(duì)她們來說只能算杯水車薪。去年她原本準(zhǔn)備再推進(jìn)一個(gè)融資計(jì)劃,不過當(dāng)時(shí)公司的運(yùn)營狀況還算良好。“如果能自給自足,就不想再去融資,怕投資方影響我們內(nèi)部的決策。”香菇說。可是,誰也沒料到之后的發(fā)展。
去年11月5日,中國國際進(jìn)口博覽會(huì)在上海成功舉行,對(duì)上海會(huì)展行業(yè)從業(yè)者來說,這是一個(gè)令人振奮的信號(hào)。Comicup 29原本預(yù)計(jì)在12月舉行,與“進(jìn)博會(huì)”之間還有一個(gè)多月的緩沖期。正因如此,香菇與許多策展者都覺得自己“很安全”。
不過,事情沒有向期待的方向發(fā)展。11月15日,香菇接到了上級(jí)部門關(guān)于大型活動(dòng)參與者48小時(shí)核酸與疫苗接種的要求。11月19日,同行業(yè)內(nèi)開始流傳一個(gè)消息:盡管沒有對(duì)外公開,但同展館的臨期展會(huì)都已決定延期。
進(jìn)博會(huì)之后,香菇就向有關(guān)部門提交了審核資料,卻遲遲沒有收到回信。不久后,她通過一位業(yè)內(nèi)朋友得知,不僅是Comicup 29,全上海的大型活動(dòng)都要推遲或取消。什么時(shí)候能辦,哪個(gè)能辦,都不好說。
“你知道《魷魚游戲》里的玻璃橋嗎?”香菇對(duì)我說,“一個(gè)人先走,前面一塊玻璃踩碎了,后面的人才知道該走另一塊。我們也是這樣,大家得看排在前面那個(gè)展能不能辦,再想自己的展能不能辦。”
《魷魚游戲》中的玻璃橋。玩家需要通過一座由雙排玻璃組成的橋梁,每一排玻璃里都有一塊普通玻璃和一塊鋼化玻璃,踩到普通玻璃的人就會(huì)從橋上摔落
11月23日,經(jīng)過與各方管理部門多次溝通,香菇確定Comicup 29在原檔期成功舉辦的可能性十分微小。最終,她以Comicup組委會(huì)的名義,宣布Comicup 29延期。
但舉辦Comicup 29的成本早在半年前就開始陸續(xù)投入,無論是場地、物流還是運(yùn)營,作為會(huì)展舉辦方,這些花銷必不可少。“場地的錢半年前就付了,場地方還給我們打了一張欠條。”香菇告訴我,上海大部分展會(huì)方手里都有這樣的“檔期欠條”。每一個(gè)策展企業(yè)都在觀望形勢,等待并尋找著那塊能通過的鋼化玻璃。
事實(shí)是,直到最后也沒有多少展會(huì)成功通過“玻璃橋”。在去年年底的這個(gè)時(shí)候,香菇她們還未曾預(yù)料到接下來會(huì)發(fā)生什么。在公告里,她寫道:“Comicup 29將延期至2022年春(舉行)。”
封控之中
2022年3月。
3月19日,迫于上海疫情壓力,Comicup組委會(huì)宣布,Comicup 29再度延期至6月。
香菇和Comicup組委會(huì)的成員們都在上海。當(dāng)?shù)匾咔楸l(fā)時(shí),幾乎整個(gè)公司的同事都處在封控管理之下,大多數(shù)人都待在自己的樓棟里。
包括香菇和同事們?cè)趦?nèi),所有身處上海的人一起度過了幾個(gè)月難熬的日子。為了方便團(tuán)購,一夜之間,同事們的微信名字都變成了“某棟某單元幾零幾”。
“每天就想著吃什么。”香菇感嘆。
最早小區(qū)內(nèi)團(tuán)購仍未興起的時(shí)候,香菇嘗試過聯(lián)系物流為公司里的同事們運(yùn)送物資,“一個(gè)點(diǎn)一個(gè)點(diǎn)地跑,一個(gè)點(diǎn)就要100塊錢”。即便如此,能收到物資的同事也是幸運(yùn)的。當(dāng)時(shí)上海已經(jīng)開始了“鴛鴦鍋”,早一步開始封控的浦東“根本送不進(jìn)去”。
封控的日子里,香菇她們舉辦Comicup的經(jīng)驗(yàn)意外地在社區(qū)中發(fā)揮了作用。
“當(dāng)時(shí)的物資配送遇到了一個(gè)‘最后100米’的問題,從街道到小區(qū)戶主的手里這段路程很難解決,這其實(shí)和我們?cè)谕苏箷?huì)中遇到的問題十分相似。展會(huì)上,為了把攤主們的制品與刊物盡快運(yùn)送到攤位上,我們準(zhǔn)備了專用的小推車來負(fù)責(zé)場內(nèi)物流的職責(zé)。”香菇以頗為專業(yè)的口吻說。后來,她們把用于同人展會(huì)的小推車借給了街道和小區(qū)。
原本用來運(yùn)送刊物的推車,此刻承載了生活物資的重量
香菇說,沒封控前看過一些視頻,有社區(qū)靠工作人員一個(gè)接一個(gè)傳遞物資,一些人質(zhì)疑這種方式不合理,結(jié)果到她自己經(jīng)歷小區(qū)封控,才明白其中的苦衷。“一個(gè)大型小區(qū)里住著上千戶,如果居委會(huì)只有一個(gè)小推車,每次最多也就送個(gè)四五戶,還不如志愿者人力接龍來得快。但是這樣太耗人了,除非有更好的運(yùn)輸工具,比如一次能裝載十幾戶物資的運(yùn)輸筐,它的效率才能跟上。”
Comicup現(xiàn)場,熱門攤位前往往會(huì)排起長隊(duì),NPC(工作人員)們需要在擁擠的會(huì)場中舉著牌子或指揮棒引導(dǎo)游客前進(jìn),標(biāo)示隊(duì)尾所在的位置。疫情之下,指揮棒發(fā)揮作用的場所從展會(huì)會(huì)場變成了小區(qū)里的核酸檢測點(diǎn)。
“我們把指揮棒借給了居委會(huì)。有一天要晚上做核酸,他們用得可開心了。”香菇說,“NPC維持秩序經(jīng)驗(yàn)都很豐富,還有喇叭,一下子就有了漫展的氣氛……可惜沒把指路的牌子帶上,不然就更像了。”
為了讓同人活動(dòng)繼續(xù)下去,2月時(shí),Comicup組委會(huì)在廣州舉辦了“Comicup 29 mini展”與第二屆“黑白魂”黑白漫畫比賽頒獎(jiǎng)儀式。礙于疫情壓力,香菇她們只能在上海遠(yuǎn)程辦公。但進(jìn)入4月之后,無論是后續(xù)展會(huì)的策劃,還是無差別同人站、線上展會(huì)Comicup Online 2.0的開發(fā)與運(yùn)營,都陷入了停滯。“不止是組委會(huì),應(yīng)該說是整個(gè)上海的人,除了自己吃的東西以外忙不了別的事。”香菇說。
真正的Comicup 29愈發(fā)遙遙無期。沒人知道什么時(shí)候能解封,浦東剛剛進(jìn)入封控管理時(shí),同事之間經(jīng)常流傳著“5天后解封”“7天后解封”的消息。4月底,人們又說5月就會(huì)解封。再后來,整個(gè)5月過去了。
香菇對(duì)我說,3月時(shí)之所以會(huì)宣布延期到6月,是因?yàn)楫?dāng)時(shí)上海處于“鴛鴦鍋”封控期間,不少同事認(rèn)為可以錯(cuò)開時(shí)間上班。“我們就覺得還有希望,賭一把。”
日子一天天過去,到了4月,Comicup 29的預(yù)定場館,被稱作“四葉草”的國家會(huì)展中心(上海)被改建為方艙醫(yī)院。這條新聞在微博等平臺(tái)上引起熱議,許多人在組委會(huì)的微博評(píng)論區(qū)里問:“‘四葉草’變方艙了,那Comicup怎么辦?”
國家會(huì)展中心成為了上海最大的方艙醫(yī)院
香菇其實(shí)并不擔(dān)心方艙醫(yī)院的問題。方艙醫(yī)院關(guān)閉后,經(jīng)過消殺,病毒不會(huì)殘留。最大的問題是場地本身的改建——“四葉草”改建成方艙醫(yī)院時(shí),內(nèi)部結(jié)構(gòu)有了一些變化,要把它從方艙醫(yī)院改造回展會(huì)場館,需要額外的工期。組委會(huì)曾經(jīng)考慮過向場館方預(yù)訂七八月份的檔期,讓Comicup 29早日舉辦,但從實(shí)際情況看,光是等待場館改建,差不多就要到8月中旬。
5月4日,Comicup組委會(huì)發(fā)布了第三次延期公告。這一次沒有給出具體的時(shí)間,公告里只給出了模糊的說法:在爭取檔期,希望能在年內(nèi)舉辦。
解封之后
6月,組委會(huì)里最后一個(gè)同事終于解封。基本恢復(fù)正常辦公之后,香菇她們需要面對(duì)的是展會(huì)停辦帶來的巨大資金缺口。會(huì)展行業(yè)的特性決定了公司的資金運(yùn)轉(zhuǎn)方式:籌備展會(huì)期間,只有持續(xù)的支出,如果不開展,就幾乎沒有收入。
組委會(huì)嘗試過將一部分展會(huì)移至其他城市,比如2021年9月、2022年3月受廣州同人展舉辦方Y(jié)ACA邀請(qǐng),組委會(huì)在廣州舉辦了Comicup 2021 SP與Comicup 29 mini兩屆分展。但迄今為止,在廣州舉辦的同人展還沒能實(shí)現(xiàn)盈利。在香菇眼里,上海之外其他城市的受眾還在培養(yǎng)參與Comicup的習(xí)慣,而習(xí)慣的養(yǎng)成、氛圍的建立是一個(gè)更加長線的投入。另一方面,廣州的投資商也更傾向于投資漫展而非同人展。
2022在廣州舉辦的Comicup 29 mini
香菇和我算了算廣州分展的賬:不包括運(yùn)營成本,Comicup 2021 SP大約虧了50萬元,Comicup 29 mini大約虧了30萬元。“我覺得有進(jìn)步,”香菇說,“畢竟虧損越來越少了。下次再辦廣州Comicup 2022 SP,目標(biāo)就是不虧。”
但不論如何,其他城市的展會(huì)規(guī)模都無法與上海相比。受疫情影響,2020年之后,上海市規(guī)定室內(nèi)舉辦的大型活動(dòng),參與人數(shù)只能達(dá)到場地容納上限的50%,這直接導(dǎo)致疫情后的首屆Comicup(Comicup 26)入場人數(shù)打了對(duì)折,門票收入也直接砍半。然而隨著同人文化的發(fā)展,近兩年來Comicup的規(guī)模迅速擴(kuò)大,參展攤位數(shù)量由Comicup 24的2044個(gè)逐步增長至Comicup 28的6049個(gè),希望入場的人數(shù)更是不斷增長。為了配合50%限制,Comicup組委會(huì)只能選擇繼續(xù)增加場地面積——Comicup 28的總場地面積是Comicup 25的兩倍,多出來的場地成本也要由主辦方承擔(dān)。
Comicup 28的盛況
在實(shí)際操作中,需要解決的問題遠(yuǎn)遠(yuǎn)不止增加場館面積一項(xiàng)。“經(jīng)常有游客抱怨Comicup入場的路程越來越長,這其實(shí)是有關(guān)部門要求的。”香菇解釋說,“展會(huì)人流量太大了,所以要求我們必須設(shè)置一個(gè)治安緩沖區(qū),要根據(jù)入場人流量與總?cè)藬?shù)計(jì)算緩沖區(qū)里需要容納的人數(shù)。同時(shí)緩沖區(qū)還得保持流動(dòng)性,以免出現(xiàn)踩踏等安全事故。”
規(guī)模龐大,人數(shù)眾多,確保安全……種種因素加在一起,意味著在上海以外,甚至在國家會(huì)展中心以外的地方舉辦Comicup 29的可能性都微乎其微。在國內(nèi)其他城市找到另一個(gè)能承載10萬以上人流量的場地本就不是一件易事,還要保證交通便捷、物流順暢,滿足最新的防疫政策需求更是近乎天方夜譚。香菇告訴我,他們?cè)趶V州附近找到了能勉強(qiáng)滿足人流量的場地,但最后計(jì)劃還是沒有推進(jìn)下去。另一方面,上海成熟的同人文化氛圍也是Comicup賴以生存的土壤。根據(jù)統(tǒng)計(jì),每屆展會(huì)差不多有一半的參與者是本地人。“我們不可能放棄這一半。”香菇說。
但對(duì)于香菇和Comicup組委會(huì)而言,一天不辦展就一天沒有收入。“現(xiàn)在公司就是在空轉(zhuǎn)。吃老本,硬耗著。”
何時(shí)到來
香菇無法保證Comicup 29什么時(shí)候能辦。她告訴我,公司準(zhǔn)備了好幾個(gè)不同的計(jì)劃,用以應(yīng)對(duì)各種可能。“已經(jīng)申請(qǐng)了10月和12月的檔期,希望能批下來。”香菇說,與此同時(shí),其他城市的展會(huì)也要爭取辦下去。
我問香菇公司目前的經(jīng)濟(jì)狀況。她回答:“我們做的最壞打算是空耗到明年5月,以此為前提來打生存的硬仗。”
文創(chuàng)銷售成了組委會(huì)能否支撐下去的關(guān)鍵。與一些熱門IP版權(quán)方聯(lián)動(dòng),販賣正版周邊,是Comicup目前為數(shù)不多的盈利方式。了解情況后,有不少版權(quán)方破例延長了授權(quán)期限。香菇?jīng)Q定,要在暑假里多賣一些周邊。“畢竟下半年可能更艱難,因?yàn)槔媳径嗟臅r(shí)候還好吃點(diǎn),越吃到底的時(shí)候越痛苦。”
即將在廣州的Comicup 2022 SP現(xiàn)場販賣的聯(lián)名特別周邊企劃
“但最晚一定會(huì)在明年開放,這是必然的。”在6月底,提到Comicup的未來,香菇再一次表現(xiàn)出了樂觀,“總不會(huì)永遠(yuǎn)不能辦展吧。”
在組委會(huì)第三次宣布延期的兩個(gè)月后,上海解封,不少企業(yè)恢復(fù)了正常運(yùn)作,但國家會(huì)展中心7月的排期仍是一片空白,展會(huì)列表里全部寫著“延期”。自去年11月5日的進(jìn)博會(huì)至今,國家會(huì)展中心沒有辦過任何展會(huì)。7月7日,上海疫情再次出現(xiàn)反復(fù),新增49個(gè)中風(fēng)險(xiǎn)區(qū)域與1個(gè)高風(fēng)險(xiǎn)區(qū)域。
空白的展會(huì)日歷
上海的春天已經(jīng)過去,但會(huì)展的春天尚未到來。
前言
本文的文字及圖片來源于網(wǎng)絡(luò),僅供學(xué)習(xí)、交流使用,不具有任何商業(yè)用途,版權(quán)歸原作者所有,如有問題請(qǐng)及時(shí)聯(lián)系我們以作處理。
作者:merlin&
操作環(huán)境
編譯器:pycharm社區(qū)版
python 版本:anaconda python3.7.4
瀏覽器選擇:Google瀏覽器
需要用到的第三方模塊:requests , lxml , selenium , time , bs4,os
網(wǎng)頁分析
明確目標(biāo)
首先我們打開騰訊動(dòng)漫首頁,分析要抓取的目標(biāo)漫畫。找到騰訊動(dòng)漫的漫畫目錄頁,簡單看了一下目錄,發(fā)現(xiàn)全站的漫畫數(shù)量超過了三千部(感覺就是爬下來也會(huì)把內(nèi)存撐爆)
于是我覺得爬取首頁的推薦漫畫會(huì)是一個(gè)比較好的選擇(爬取全站漫畫只需要稍稍改一下網(wǎng)址構(gòu)造就可以做到了)
提取漫畫地址
選定了對(duì)象之后,就應(yīng)該想辦法來搞到漫畫的地址了右擊檢查元素,粗略看一遍網(wǎng)頁的源代碼,這時(shí)我發(fā)現(xiàn)里面有很多連續(xù)的
標(biāo)簽,我猜測每部漫畫的地址信息就存儲(chǔ)在這些標(biāo)簽里面
隨便打開一個(gè)《li》標(biāo)簽,點(diǎn)擊里面包裹的鏈接地址會(huì)跳轉(zhuǎn)到一個(gè)新的網(wǎng)頁,這個(gè)網(wǎng)頁正是我想要找的漫畫地址,可以見得我的猜測是正確的,等到實(shí)際操作的時(shí)候再用表達(dá)式提取信息就非常容易了
提取漫畫章節(jié)地址
進(jìn)入漫畫的目錄頁,發(fā)現(xiàn)一頁最多可以展示20章的漫畫目錄,要想更換顯示還需要點(diǎn)擊章節(jié)名上面的選項(xiàng)卡來顯示其他章節(jié)的地址
接下來就需要我們來檢查網(wǎng)頁元素想辦法來獲取章節(jié)地址了,同樣右擊檢查元素在看到了源代碼后,我發(fā)現(xiàn)了一個(gè)非常驚喜的事情,這個(gè)源碼里面包含著所有的章節(jié)鏈接,而不是通過動(dòng)態(tài)加載來展示的,這就省去了我們提取其他章節(jié)鏈接的功夫,只需要花心思提取漫畫圖片就可以了
這里每個(gè)《p》標(biāo)簽下包含了五個(gè)《a》標(biāo)簽,每個(gè)《li》標(biāo)簽下包含了四個(gè)《p》標(biāo)簽,而每個(gè)漫畫的鏈接就存在每個(gè)《a》標(biāo)簽中,可以輕松通過語法來提取到每頁的鏈接信息
提取漫畫圖片
怎么將漫畫的圖片地址提取出來并保存到本地,這是這個(gè)代碼的難點(diǎn)和核心先是打開漫畫,這個(gè)漫畫頁應(yīng)該是被加上了某些措施,所以它沒辦法使用右鍵查看網(wǎng)頁源代碼,但是使用快捷鍵[ctrl + shift +i]是可以看到的
按下[ctrl + shift + i],檢查元素
通過第一次檢查,可以發(fā)現(xiàn)網(wǎng)頁的元素中只有前幾張圖片的地址信息,后面的信息都為后綴.gif的文件表示,這些gif文件就是圖片的加載動(dòng)畫
接著向下滑動(dòng)到底部,等待圖片全部顯示出來再次檢查元素
現(xiàn)在所有的漫畫圖片全部顯示出來,下方并無.gif 的文件,由此可知,騰訊動(dòng)漫是以js異步加載來顯示圖片的,要想獲取頁面的全部圖片,就必須要滑動(dòng)滾動(dòng)條,將全部的圖片加載完成再進(jìn)行提取,這里我選擇selenium模塊和chromedriver來幫助我完成這些操作。下面開始進(jìn)行代碼的編寫。
編寫代碼
導(dǎo)入需要的模塊
import requests
from lxml import etree
from selenium import webdriver #selenium模擬操作
from time import sleep
from bs4 import BeautifulSoup
from selenium.webdriver.chrome.options import Options #谷歌無頭瀏覽器
import os
獲取漫畫地址
這里我使用的是xpath提取漫畫地址信息,在谷歌瀏覽器中使用xpath helper插件輔助編寫xpath表達(dá)式
#打開騰訊動(dòng)漫首頁
url = 'https://ac.qq.com/'
#給網(wǎng)頁發(fā)送請(qǐng)求
data = requests.get(url).text
#將網(wǎng)頁信息轉(zhuǎn)換成xpath可識(shí)別的類型
html = etree.HTML(data)
#提取到每個(gè)漫畫的目錄頁地址
comic_list = html.xpath('//a[@class="in-rank-name"]/@href')
print(comic_list)
print一下輸出的comic_list,提取成功
提取漫畫的內(nèi)容頁
內(nèi)容頁的提取也很簡單,就像上面的分析一樣,使用簡單的xpath語法即可提取
然后我們?cè)賹⒙嫷拿痔崛〕鰜恚奖銥楸4娴奈募A命名
#遍歷提取到的信息
for comic in comic_list:
#拼接成為漫畫目錄頁的網(wǎng)址
comic_url = url + str(comic)
#從漫畫目錄頁提取信息
url_data = requests.get(comic_url).text
#準(zhǔn)備用xpath語法提取信息
data_comic = etree.HTML(url_data)
#提取漫畫名--text()為提取文本內(nèi)容
name_comic = data_comic.xpath("http://h2[@class='works-intro-title ui-left']/strong/text()")
#提取該漫畫每一頁的地址
item_list = data_comic.xpath("http://span[@class='works-chapter-item']/a/@href")
print(name_comic)
print(item_list)
print打印的信息:
提取章節(jié)名
剛剛我們輸出的是漫畫頁的地址字段,但是通過這些字段并不能請(qǐng)求到信息,還需在前面加上域名才可以構(gòu)成一個(gè)完整的網(wǎng)址提取章節(jié)名是為了在漫畫名的文件夾下再為每個(gè)章節(jié)創(chuàng)建一個(gè)文件夾保存漫畫圖片
for item in item_list:
#拼接每一章節(jié)的地址
item_url = url + str(item)
#print(item_url)
#請(qǐng)求每一章節(jié)的信息
page_mes = requests.get(item_url).text
#準(zhǔn)備使用xpath提取內(nèi)容
page_ming = etree.HTML(page_mes)
#提取章節(jié)名
page_name = page_ming.xpath('//span[@class="title-comicHeading"]/text()')
print(page_name)
打印章節(jié)名:
獲取漫畫源網(wǎng)頁代碼
這個(gè)部分的代碼是這個(gè)代碼的核心部分,也是花費(fèi)時(shí)間最久的部分首先我們知道通過正常的方式?jīng)]有辦法請(qǐng)求到所有的圖片地址信息,若是使用抓包方法會(huì)變得非常難分析,所以我采用的是模擬瀏覽器滑動(dòng)的方法來獲得圖片的地址信息為了方便看到結(jié)果,先將webdriver設(shè)置為有界面模式,等到實(shí)現(xiàn)想要的功能之后,再將它隱藏起來
#webdriver位置
path = r'/home/jmhao/chromedriver'
#瀏覽器參數(shù)設(shè)置
browser = webdriver.Chrome(executable_path=path)
#開始請(qǐng)求第一個(gè)章節(jié)的網(wǎng)址
browser.get(item_url)
#設(shè)置延時(shí),為后續(xù)做緩沖
sleep(2)
#嘗試執(zhí)行下列代碼
try:
#設(shè)置自動(dòng)下滑滾動(dòng)條操作
for i in range(1, 100):
#滑動(dòng)距離設(shè)置
js = 'var q=document.getElementById("mainView").scrollTop = ' + str(i * 1000)
#執(zhí)行滑動(dòng)選項(xiàng)
browser.execute_script(js)
#延時(shí),使圖片充分加載
sleep(2)
sleep(2)
#將打開的界面截圖保存,證明無界面瀏覽器確實(shí)打開了網(wǎng)頁
browser.get_screenshot_as_file(str(page_name) + ".png")
#獲取當(dāng)前頁面源碼
data = browser.page_source
#在當(dāng)前文件夾下創(chuàng)建html文件,并將網(wǎng)頁源碼寫入
fh = open("dongman.html", "w", encoding="utf-8")
#寫入操作
fh.write(data)
#關(guān)掉瀏覽器
fh.close()
# 若上述代碼執(zhí)行報(bào)錯(cuò)(大概率是由于付費(fèi)漫畫),則執(zhí)行此部分代碼
except Exception as err:
#跳過錯(cuò)誤代碼
pass
運(yùn)行之后會(huì)自動(dòng)打開漫畫的內(nèi)容頁,并拖動(dòng)右側(cè)的滑動(dòng)條(模擬了手動(dòng)操作,緩慢拖動(dòng)是為了讓圖片充分加載),其中的sleep方法和網(wǎng)速有一定的關(guān)系,網(wǎng)速好的可以適當(dāng)減少延時(shí)的時(shí)間,網(wǎng)速差可適當(dāng)延長在寫拖動(dòng)滑動(dòng)條的代碼時(shí),我嘗試了非常多種拖動(dòng)寫法,也模擬了按下方向鍵的操作,可是只有這一種方法使用成功了。我認(rèn)為失敗的原因可能是剛打開界面的時(shí)候會(huì)有一個(gè)導(dǎo)航條擋住滑塊,導(dǎo)致無法定位到滑塊的坐標(biāo)(因?yàn)槲矣闷渌W(wǎng)頁測試的時(shí)候都是可以拖動(dòng)的)
使用的try是為了防止有一些章節(jié)會(huì)彈出付費(fèi)窗口,導(dǎo)致程序報(bào)錯(cuò),使后續(xù)無法運(yùn)行,即遇到會(huì)報(bào)錯(cuò)的情況就跳過此段代碼,執(zhí)行except中的選項(xiàng)
這段程序運(yùn)行完之后有一個(gè)dongman.html文件保存在當(dāng)前文件夾下,里面就包含了所有圖片的url,接下來只要讀取這個(gè)文件的內(nèi)容就可以提取到所有的漫畫地址了
下載漫畫圖片
當(dāng)我們保存完網(wǎng)頁的源代碼之后,接下來的操作就變得簡單了 我們要做的就是提取文件內(nèi)容,將圖片下載到本地
#用beautifulsoup打開本地文件
html_new = BeautifulSoup(open('dongman.html', encoding='utf-8'), features='html.parser')
#提取html文件中的主體部分
soup = html_new.find(id="mainView")
#設(shè)置變量i,方便為保存的圖片命名
i = 0
#提取出主體部分中的img標(biāo)簽(因?yàn)閳D片地址保存在img標(biāo)簽中)
for items in soup.find_all("img"):
#提取圖片地址信息
item = items.get("src")
#請(qǐng)求圖片地址
comic_pic = requests.get(item).content
#print(comic_pic)
#嘗試提取圖片,若發(fā)生錯(cuò)誤則跳過
try:
#打開文件夾,將圖片存入
with open('comic/' + str(name_comic) + '/' + str(page_name) + '/' + str(i + 1) + '.jpg', 'wb') as f:
#print('正在下載第 ', (i + 1), ' 張圖片中')
print('正在下載' , str(name_comic) , '-' , str(page_name) , '- 第' , (i+1) , '張圖片')
#寫入操作
f.write(comic_pic)
#更改圖片名,防止新下載的圖片覆蓋原圖片
i += 1
#若上述代碼執(zhí)行報(bào)錯(cuò),則執(zhí)行此部分代碼
except Exception as err:
#跳過錯(cuò)誤代碼
pass
下載結(jié)果
到了這里代碼就寫完了,來看一下運(yùn)行結(jié)果:
打開文件夾看到:
完整代碼
import requests
from lxml import etree
from selenium import webdriver
from time import sleep
from bs4 import BeautifulSoup
from selenium.webdriver.chrome.options import Options
import os
'''
============================
python學(xué)習(xí)群:695185429
============================
'''
#打開騰訊動(dòng)漫首頁
url = 'https://ac.qq.com/'
#給網(wǎng)頁發(fā)送請(qǐng)求
data = requests.get(url).text
#將網(wǎng)頁信息轉(zhuǎn)換成xpath可識(shí)別的類型
html = etree.HTML(data)
#提取到每個(gè)漫畫的目錄頁地址
comic_list = html.xpath('//a[@class="in-rank-name"]/@href')
#print(comic_list)
#遍歷提取到的信息
for comic in comic_list:
#拼接成為漫畫目錄頁的網(wǎng)址
comic_url = url + str(comic)
#從漫畫目錄頁提取信息
url_data = requests.get(comic_url).text
#準(zhǔn)備用xpath語法提取信息
data_comic = etree.HTML(url_data)
#提取漫畫名--text()為提取文本內(nèi)容
name_comic = data_comic.xpath("http://h2[@class='works-intro-title ui-left']/strong/text()")
#提取該漫畫每一頁的地址
item_list = data_comic.xpath("http://span[@class='works-chapter-item']/a/@href")
# print(name_comic)
# print(item_list)
#以漫畫名字為文件夾名創(chuàng)建文件夾
os.makedirs('comic/' + str(name_comic))
#將一本漫畫的每一章地址遍歷
for item in item_list:
#拼接每一章節(jié)的地址
item_url = url + str(item)
#print(item_url)
#請(qǐng)求每一章節(jié)的信息
page_mes = requests.get(item_url).text
#準(zhǔn)備使用xpath提取內(nèi)容
page_ming = etree.HTML(page_mes)
#提取章節(jié)名
page_name = page_ming.xpath('//span[@class="title-comicHeading"]/text()')
#print(page_name)
#再以章節(jié)名命名一個(gè)文件夾
os.makedirs('comic/' + str(name_comic) + '/' + str(page_name))
#以下為代碼的主體部分
#設(shè)置谷歌無界面瀏覽器
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
#webdriver位置
path = r'/home/jmhao/chromedriver'
#瀏覽器參數(shù)設(shè)置
browser = webdriver.Chrome(executable_path=path, options=chrome_options)
#開始請(qǐng)求第一個(gè)章節(jié)的網(wǎng)址
browser.get(item_url)
#設(shè)置延時(shí),為后續(xù)做緩沖
sleep(2)
#browser.get_screenshot_as_file(str(page_name) + ".png")
#嘗試執(zhí)行下列代碼
try:
#設(shè)置自動(dòng)下滑滾動(dòng)條操作
for i in range(1, 100):
#滑動(dòng)距離設(shè)置
js = 'var q=document.getElementById("mainView").scrollTop = ' + str(i * 1000)
#執(zhí)行滑動(dòng)選項(xiàng)
browser.execute_script(js)
#延時(shí),使圖片充分加載
sleep(2)
sleep(2)
#將打開的界面截圖保存,證明無界面瀏覽器確實(shí)打開了網(wǎng)頁
browser.get_screenshot_as_file(str(page_name) + ".png")
#獲取當(dāng)前頁面源碼
data = browser.page_source
#在當(dāng)前文件夾下創(chuàng)建html文件,并將網(wǎng)頁源碼寫入
fh = open("dongman.html", "w", encoding="utf-8")
#寫入操作
fh.write(data)
#關(guān)掉無界面瀏覽器
fh.close()
#下面的操作為打開保存的html文件,提取其中的圖片信息,并保存到文件夾中
#用beautifulsoup打開本地文件
html_new = BeautifulSoup(open('dongman.html', encoding='utf-8'), features='html.parser')
#提取html文件中的主體部分
soup = html_new.find(id="mainView")
#設(shè)置變量i,方便為保存的圖片命名
i = 0
#提取出主體部分中的img標(biāo)簽(因?yàn)閳D片地址保存在img標(biāo)簽中)
for items in soup.find_all("img"):
#提取圖片地址信息
item = items.get("src")
#請(qǐng)求圖片地址
comic_pic = requests.get(item).content
#print(comic_pic)
#嘗試提取圖片,若發(fā)生錯(cuò)誤則跳過
try:
#打開文件夾,將圖片存入
with open('comic/' + str(name_comic) + '/' + str(page_name) + '/' + str(i + 1) + '.jpg', 'wb') as f:
#print('正在下載第 ', (i + 1), ' 張圖片中')
print('正在下載' , str(name_comic) , '-' , str(page_name) , '- 第' , (i+1) , '張圖片')
#寫入操作
f.write(comic_pic)
#更改圖片名,防止新下載的圖片覆蓋原圖片
i += 1
#若上述代碼執(zhí)行報(bào)錯(cuò),則執(zhí)行此部分代碼
except Exception as err:
#跳過錯(cuò)誤代碼
pass
# 若上述代碼執(zhí)行報(bào)錯(cuò)(大概率是由于付費(fèi)漫畫),則執(zhí)行此部分代碼
except Exception as err:
#跳過錯(cuò)誤代碼
pass