天天看點

爬蟲(三)lxml+requests(豆瓣Top250電影)

回家之後就不想學習了…

這次用的是lxml庫,因為聽說比起BeautifulSoup它的速度更快,然後就想了解一下。(全部的代碼在最下面)

import庫
from lxml import etree
import requests
import json
# from time import sleep
           

這是要用到的庫。requests請求html,lxml解析html文檔,然後得到的資料通過json存儲在json檔案。

分析豆瓣網頁

第一頁:https://movie.douban.com/top250

第二頁:https://movie.douban.com/top250?start=25&filter=

第三頁:https://movie.douban.com/top250?start=50&filter=

發現一頁有25個電影介紹,每多一頁start=的數目遷移25。是以嘗試:

https://movie.douban.com/top250?start=0

發現成功後,分析網頁源代碼。

這次抓取的隻是電影名、排名、分數、和簡介。還是跟之前那樣子通過Chrome的審查元素抓取Xpath路徑。

分别有:

# info
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[1]/em index
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1] name
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[2] rate
# //*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/p[2]/span quote
           

這是第一個電影的資訊,可以看出來我們要抓取的内容都在一個統一的節點

div

上。而每個電影都在不同的

li

裡面。

重點代碼
def get_one_page(url):
    try:
        response = requests.get(url)
        if response.status_code == :
            return response.content
        return None
    except requests.RequestException:
        return None
           

這是通過

request

來請求一個頁面的函數。使用的

RequestException

request

庫自帶的,代表連接配接出錯。

status_code

等于200時代表連接配接正常,這時候我們傳回頁面。

更多狀态碼可以上菜鳥:http://www.runoob.com/http/http-status-codes.html

def parse_one_page(content):
    html = etree.HTML(content)
    films = html.xpath('//div[@class="article"]/ol/li')
    for film in films:
        yield{
            'name': film.xpath('./div//span[@class="title"][1]/text()'),
            'index': film.xpath('./div//div[@class="pic"]/em/text()'),
            'quote': film.xpath('./div//span[@class="inq"]/text()'),
            'rating_num': film.xpath('./div//span[@class="rating_num"]/text()'),
        }
           

xpath用法中,//表示搜尋所有的子孫節點,而/是直接的子節點。我們先通過class屬性選擇對應的

div

,再選擇它分支的所有

li

節點。這個時候,我們再疊代所有的

li

節點。

需要注意的是,我們在疊代的時候隻操作目前節點,是以我們路徑都有個

./

最後選擇的是yield,這樣子這個函數就是個疊代器了。在主函數中,我們疊代這個函數收集資訊就可以了。

def write(data):
    with open('douban_top250.json', 'a', encoding='utf-8') as f:
        f.write(json.dumps(data, ensure_ascii=False) + '\n')
           

這裡把資訊寫到自己建的檔案

douban_top250.json

中。

if __name__ == '__main__':
    douban_films = 'https://movie.douban.com/top250?start='
    for i in range(, , ):
        # print(i)
        page = douban_films + str(i)
        content = get_one_page(page)
        if content is not None:
            for item in parse_one_page(content):
                # print(item)
                write(item)
        else:
            print('Request Error')
        # sleep(5)
           

這個是總的過程。自己設定

i

周遊25個頁面,然後通過自己構造的函數來解析資訊,最後輸入到檔案中。需要解釋的是,這裡注釋掉的三個語句是我在測試的時候檢查錯誤先寫上去的。

最終的代碼如下(好簡短):

from lxml import etree
import requests
import json

def get_one_page(url):
    try:
        response = requests.get(url)
        if response.status_code == :
            return response.content
        return None
    except requests.RequestException:
        return None


def parse_one_page(content):
    html = etree.HTML(content)
    films = html.xpath('//div[@class="article"]/ol/li')
    for film in films:
        yield{
            'name': film.xpath('./div//span[@class="title"][1]/text()'),
            'index': film.xpath('./div//div[@class="pic"]/em/text()'),
            'quote': film.xpath('./div//span[@class="inq"]/text()'),
            'rating_num': film.xpath('./div//span[@class="rating_num"]/text()'),
        }

def write(data):
    with open('douban_top250.json', 'a', encoding='utf-8') as f:
        f.write(json.dumps(data, ensure_ascii=False) + '\n')


if __name__ == '__main__':
    douban_films = 'https://movie.douban.com/top250?start='
    for i in range(, , ):
        page = douban_films + str(i)
        content = get_one_page(page)
        if content is not None:
            for item in parse_one_page(content):
                write(item)
        else:
            print('Request Error')
           

效果如圖:

爬蟲(三)lxml+requests(豆瓣Top250電影)