Python 爬蟲學習筆記之多線程爬蟲,python學習筆記

來源:互聯網
上載者:User

Python 爬蟲學習筆記之多線程爬蟲,python學習筆記

XPath 的安裝以及使用

1 . XPath 的介紹

剛學過Regex,用的正順手,現在就把Regex替換掉,使用 XPath,有人表示這太坑爹了,早知道剛上來就學習 XPath 多省事 啊。其實我個人認為學習一下Regex是大有益處的,之所以換成 XPath ,我個人認為是因為它定位更準確,使用更加便捷。可能有的人對 XPath 和Regex的區別不太清楚,舉個例子來說吧,用Regex提取我們的內容,就好比說一個人想去天安門,地址的描述是左邊有一個圓形建築,右邊是一個方形建築,你去找吧,而使用 XPath 的話,地址的描述就變成了天安門的具體地址。怎麼樣?相比之下,哪種方式效率更高,找的更準確呢?

2 . XPath 的安裝

XPath 包含在 lxml 庫中,那麼我們到哪裡去下載呢? 點擊此處 ,進入網頁後按住 ctrl+f 搜尋 lxml ,然後進行下載,下載完畢之後將檔案拓展名改為 .zip ,然後進行解壓,將名為 lxml 的檔案夾複製粘貼到 Python 的 Lib 目錄下,這樣就安裝完畢了。

3 . XPath 的使用

為了方便示範,我利用 Html 寫了個簡單的網頁,代碼如下所示(為了節省時間,方便小夥伴們直接進行測試,可直接複製粘貼My Code)

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Test Html</title></head><body><div id="content">  <ul id="like">    <li>like one</li>    <li>like two</li>    <li>like three</li>  </ul>  <ul id="hate">    <li>hate one</li>    <li>hate two</li>    <li>hate three</li>  </ul>  <div id="url">    <a href="http://www.baidu.com">百度一下</a>    <a href="http://www.hao123.com">好123</a>  </div></div></body></html>

用Google瀏覽器開啟這個網頁,然後右擊,選擇檢查,會出現如下所示介面

這個時候你滑鼠右擊任何一行 html 代碼,都可以看到一個 Copy,將滑鼠放上去,就可以看到 Copy XPath ,先複製下來,怎麼用呢?

# coding=utf-8from lxml import etreef = open('myHtml.html','r')html = f.read()f.close()selector = etree.HTML(html)content = selector.xpath('//*[@id="like"]/li/text()')for each in content:  print each

看看列印結果

like onelike twolike three

很顯然,將我們想要的內容列印下來了,注意我們在 xpath() 中使用了 text() 函數,這個函數就是擷取其中的內容,但是如果我們想擷取一個屬性,該怎麼辦?比如說我們想得到 html 中的兩個連結地址,也就是 href 屬性,我們可以這麼操作

content = selector.xpath('//*[@id="url"]/a/@href')for each in content:  print each

這個時候的列印結果就是

http://www.baidu.comhttp://www.hao123.com

看到現在大家大概也就對 xpath() 中的符號有了一定的瞭解,比如一開始的 // 指的就是根目錄,而 / 就是父節點下的子節點,其他的 id 屬性也是一步一步從上往下尋找的,由於這是一種樹結構,所以也難怪方法的名字為 etree()。

4 . XPath 的特殊用法

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Title</title></head><body><div id="likeone">like one</div><div id="liketwo">like two</div><div id="likethree">like three</div></body></html>

面對上面的一個網頁,我們應該如何擷取到三行的內容的 ? 嗯哼,很簡單,我寫三個 XPath 語句不就好了,so easy 。 如果真是這樣,那麼我們的效率好像是太低了一點,仔細看看這三行 div 的 id 屬性,好像前四個字母都是 like, 那就好辦了,我們可以使用 starts-with 對這三行進行同時提取,如下所示

content = selector.xpath('//div[starts-with(@id,"like")]/text()')

不過這樣有一點麻煩的地方,我們就需要手動的去寫 XPath 路徑了,當然也可以複製粘貼下來在進行修改,這就是提升複雜度來換取效率的問題了。再來看看標籤嵌套標籤的提取情況

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Title</title></head><body><div id="content">  <div id="text">    <p>hello      <b> world        <font color="#ffe4c4">          Python        </font>      </b>    </p>  </div></div></body></html>

像上面這樣的一個網頁,如果我們想擷取到  hello world Python 語句,該怎麼擷取呢?很明顯這是一種標籤嵌套標籤的情況,我們按照正常情況進行提取,看看結果如何

content = selector.xpath('//*[@id="text"]/p/text()')for each in content:  print each

運行之後,很遺憾的,只列印出了 hello 字樣,其他字元丟失了,該怎麼辦呢?這種情況可以藉助於 string(.)如下所示

content = selector.xpath('//*[@id="text"]/p')[0]info = content.xpath('string(.)')data = info.replace('\n','').replace(' ','')print data

這樣就可以列印出正確內容了,至於第三行為什麼存在,你可以將其去掉看看結果,到時候你自然就明白了。

Python 並行化的簡單介紹

有人說 Python 中的並行化並不是真正的並行化,但是多線程還是能夠顯著提高我們代碼的執行效率,為我們節省下來一大筆時間,下面我們就針對單線程和多線程進行時間上的比較。

# coding=utf-8import requestsfrom multiprocessing.dummy import Pool as ThreadPoolimport timedef getsource(url):  html = requests.get(url)if __name__ == '__main__':  urls = []  for i in range(50, 500, 50):    newpage = 'http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=' + str(i)    urls.append(newpage)  # 單線程計時  time1 = time.time()  for i in urls:    print i    getsource(i)  time2 = time.time()  print '單線程耗時 : ' + str(time2 - time1) + ' s'  # 多線程計時  pool = ThreadPool(4)  time3 = time.time()  results = pool.map(getsource, urls)  pool.close()  pool.join()  time4 = time.time()  print '多線程耗時 : ' + str(time4 - time3) + ' s'

列印結果為

http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=50http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=100http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=150http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=200http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=250http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=300http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=350http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=400http://tieba.baidu.com/f?kw=python&ie=utf-8&pn=450單線程耗時 : 7.26399993896 s多線程耗時 : 2.49799990654 s

至於以上連結為什麼設定間隔為 50,是因為我發現在百度貼吧上沒翻一頁,pn 的值就會增加 50。 通過以上結果我們發現,多線程相比於單線程效率提升了太多太多。至於以上代碼中多線程的使用,我就不再過多講解,我相信只要接觸過 Java 的人對多線程的使用不會陌生,其實都是大差不差。沒有接觸過 Java ?那就對不起了,以上代碼請自行消化吧。

實戰 -- 爬取噹噹網書籍資訊

一直以來都在噹噹網購買書籍,既然學會了如何利用 Python 爬取資訊,那麼首先就來爬取一下噹噹網中的書籍資訊吧。本實戰完成之後的內容如下所示

在噹噹網中搜尋 Java ,出現了89頁內容,我選擇爬取了前 80 頁,而且為了比較多線程和單線程的效率,我特意在這裡對二者進行了比較,其中單線程爬取所用時間為 67s,而多線程僅為 15s 。

如何爬取網頁,在上面 XPath 的使用中我們也已經做了介紹,無非就是進入網頁,右擊選擇檢查,查看網頁 html 代碼,然後尋找規律,進行資訊的提取,在這裡就不在多介紹,由於代碼比較短,所以在這裡直接上原始碼。

# coding=utf8import requestsimport reimport timefrom lxml import etreefrom multiprocessing.dummy import Pool as ThreadPoolimport sysreload(sys)sys.setdefaultencoding('utf-8')def changepage(url, total):  urls = []  nowpage = int(re.search('(\d+)', url, re.S).group(1))  for i in range(nowpage, total + 1):    link = re.sub('page_index=(\d+)', 'page_index=%s' % i, url, re.S)    urls.append(link)  return urlsdef spider(url):  html = requests.get(url)  content = html.text  selector = etree.HTML(content)  title = []  title = selector.xpath('//*[@id="component_0__0__6612"]/li/a/@title')  detail = []  detail = selector.xpath('//*[@id="component_0__0__6612"]/li/p[3]/span[1]/text()')  saveinfo(title,detail)def saveinfo(title, detail):  length1 = len(title)  for i in range(0, length1 - 1):    f.writelines(title[i] + '\n')    f.writelines(detail[i] + '\n\n')if __name__ == '__main__':  pool = ThreadPool(4)  f = open('info.txt', 'a')  url = 'http://search.dangdang.com/?key=Java&act=input&page_index=1'  urls = changepage(url, 80)  time1 = time.time()  pool.map(spider, urls)  pool.close()  pool.join()  f.close()  print '爬取成功!'  time2 = time.time()  print '多線程耗時 : ' + str(time2 - time1) + 's'  # time1 = time.time()  # for each in urls:  #   spider(each)  # time2 = time.time()  # f.close()  # print '單線程耗時 : ' + str(time2 - time1) + 's'

可見,以上代碼中的知識,我們都在介紹 XPath 和 並行化 中做了詳細的介紹,所以閱讀起來十分輕鬆。

好了,到今天為止,Python 爬蟲相關係列的文章到此結束,謝謝你的觀看。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.