1.分析
<li><div class="item">電影信息</div></li>
每個電影信息都是同樣的格式,畢竟在服務器端是用循環生成的html,這樣解析出電影的信息就很簡單了
豆瓣電影top250的翻頁也很簡單,直接就在url上修改一個start就行了,start代表這一頁從start+1開始
比如 https://movie.douban.com/top250?start=0&filter=, 就是top1到top25,每頁25部電影,翻頁把start+=25就行了,一直加到225
2.獲取網頁的html
使用python內置的urllib庫
不過得到的網頁中並沒有中文,而是會出現這樣的字符串
\xe8\xae\xa9\xe5\xa5\xbd\xe7\x94\xb5\xe5\xbd\xb1\xe6\x9d\xa5\xe6\x89\xbe\xe4\xbd\xa0
這是中文的utf-8編碼的16進制版本
先將\x去除,變成
e8aea9e5a5bde794b5e5bdb1e69da5e689bee4bda0
然后每6位是一個中文字符
E8 AE A9 讓
E5 A5 BD 好
E7 94 B5 電
。。。
全文是【讓好電影來找你】
可以在這個網站上輸入16進制的UTF-8編碼來查找對應字符
def GetHtml(url): print('Url : '+url) f = request.urlopen(url.format(start)) data = f.read() htmls.append(data.decode('utf-8'))
3.解析網頁
簡單提下XPath的語法
nodename | 選取此節點的所有子節點。 |
/ | 從根節點選取。 |
// | 從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。 |
. | 選取當前節點。 |
.. | 選取當前節點的父節點。 |
@ | 選取屬性。 |
先解析出<div class="item">,再對這個div中的內容進行第二次解析
這里值得注意的是打印一個element內的html要用etree.tostring()
tree = etree.HTML(str) result = tree.xpath('//div[@class="item"]') //獲取所有<div class="item">元素 print(etree.tostring(result[0], encoding='unicode')) //隨便打印一個
打印出來的就是這樣的
<div class="item"> <div class="pic"> <em class="">1</em> <a href="https://movie.douban.com/subject/1292052/"> <img width="100" alt="肖申克的救贖" src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg" class=""/> </a> </div> <div class="info"> <div class="hd"> <a href="https://movie.douban.com/subject/1292052/" class=""> <span class="title">肖申克的救贖</span> <span class="title"> / The Shawshank Redemption</span> <span class="other"> / 月黑高飛(港) / 刺激1995(台)</span> </a> <span class="playable">[可播放]</span> </div> <div class="bd"> <p class=""> 導演: 弗蘭克·德拉邦特 Frank Darabont 主演: 蒂姆·羅賓斯 Tim Robbins /...<br/> 1994 / 美國 / 犯罪 劇情 </p> <div class="star"> <span class="rating5-t"/> <span class="rating_num" property="v:average">9.6</span> <span property="v:best" content="10.0"/> <span>996499人評價</span> </div> <p class="quote"> <span class="inq">希望讓人自由。</span> </p> </div> </div> </div>
以上<div class="item">已經拿到了,開始進行第二次解析(可以先用個list把這些div存起來,然后再弄個線程做第二次的解析,那是以后的事了,這里先不管)
記錄下這里踩的坑
print(result[0].xpath('//img/@src')) //會返回整個頁面的img的src
這個奇怪的問題簡直了,我甚至覺得是這個包的bug,我從result[0]那么一小段html用xpath查東西居然能查到整個html的,讓我覺得我雖然是用result[0]調用的xpath,但內部沒准根本不care誰調用的,一律使用最開始etree.HTML() 的到的這個對象調用xpath
我的解決辦法是改下xpath,指定從div開始找,或者是用 “."表示從當前節點開始找
print(result[0].xpath('div//img/@src')) print(result[0].xpath('.//img/@src'))
下面這段代碼中的XPath可能不夠簡潔,但It's just works,畢竟這是第一個版本,隨着我對python的熟練,還會繼續改動
主要是將一個p標簽下的字符串連接起來並去除空格,轉換各種特殊字符
需要注意的是XPath返回的基本都是list類型的,很多博客里都直接調方法都沒加下標取值,天知道是不是版本不一樣
def ProcessHtml(html): tree = etree.HTML(html) items = tree.xpath('//div[@class="item"]') for item in items: index = item.xpath('div//em/text()')[0] src = item.xpath('div//img/@src')[0] info = item.xpath('.//div[@class="bd"]/p')[0].xpath('string(.)').strip().replace(' ','').replace('\xa0',' ').replace('\n',' ') title = item.xpath('.//div[@class="hd"]/a')[0].xpath('string(.)').strip().replace(' ','').replace('\xa0',' ').replace('\n',' ') star = item.xpath('.//span[@class="rating_num"]/text()')[0] print ('''%s %s %s %s %s ''' % (index,title,info,star,src))
完整代碼https://github.com/arcsinw/project_douban
參考鏈接
scrapy xpath 從response中獲取li,然后再獲取li中img的src