Python抓取優酷視頻(上):爬蟲使用及數據處理


緣起:

上篇因為工作需要(就是把騰訊新聞copy到單位自己網站上去每天15條更新)所以寫了一個抓取騰訊新聞的python小腳本

這次是因為想用手機看youku視頻,比如xiaoy的魔獸解說,但是打開瀏覽器輸入game.youku.com的時候,三星9003太不

給力,因而需要一個打開速度快的目錄小網站。

思路:

1.數據表設計:

  id(int),                    //主鍵自增

  title(varchar 50),    //速度優先,只需要title,不需要圖片

  href(varchar 50),   //視頻播放地址

  date(varchar 25),  //采集的date中有如“1小時前”,因此也設計成varchar

2.采集函數設計:

  視頻列表頁url = http://i.youku.com/u/UMTE0NDEzOTky/videos/order_1_view_1_page_id (id =1,2...)

  每頁視頻個數為20,采集內容為title,href,date,優酷的html很規整,因此正則提取很好寫,詳見代碼。

3.采集流程及入庫:

  采用多線程采集,開9個進程,每個進程提取一個列表頁20個視頻,總共采集180個視頻,如果想全站采集的話修改即可。

  數據庫采用mysql,如何使python支持mysql詳見Python網站建設,因為是多線程所以在插入數據的時候需要資源鎖。

  關於python多線程thread以及資源鎖,可以參照Python模塊學習

代碼:

 1 #!/usr/bin/env python
 2 #coding=utf-8
 3 import urllib2
 4 import re
 5 import MySQLdb
 6 import thread
 7 import time
 8 #創建鎖,用於訪問數據庫
 9 lock = thread.allocate_lock()
10 #抓取函數
11 def fetch(id=1,debug=False):
12     urlbase = 'http://i.youku.com/u/UMTE0NDEzOTky/videos/'
13     url = urlbase + 'order_1_view_1_page_' + str(id) + '/'
14     res = urllib2.urlopen(url).read()
15     abstarct = re.compile(r'<ul class="v".*?</ul>',re.DOTALL).findall(res)
16     
17     vid_list = []
18     for i in range(0,len(abstarct)):
19         title = re.compile(r'title="(.*?)"',re.DOTALL).findall(abstarct[i])
20         href = re.compile(r'href="(.*?)"',re.DOTALL).findall(abstarct[i])
21         date = re.compile(r'<span>(.*?)</span>',re.DOTALL).findall(abstarct[i])
22         if debug == True:
23             print title[0]+href[0]+date[0]
24         vid = {
25             'title' : title[0],
26             'href'  : href[0],
27             'date'  : date[0]
28         }
29         vid_list.append(vid)
30     #print thread.get_ident()    
31     return vid_list
32 #插入數據庫
33 def insert_db(page):
34     global lock
35     #執行抓取函數
36     vid_date = fetch(page,False)
37     sql = "insert into ykgame (title,href,date) values (%s,%s,%s)"
38     #插入數據,一頁20條
39     for i in range(0,len(vid_date)):
40         param = (vid_date[i]['title'],vid_date[i]['href'],
41                     vid_date[i]['date'])
42         lock.acquire() #創建鎖
43         cursor.execute(sql,param)
44         conn.commit()
45         lock.release() #釋放鎖
46                 
47 if __name__ == "__main__":
48     #連接數據庫
49     conn = MySQLdb.connect(host="localhost",user="root",
50             passwd="root",db="python_test",charset="utf8")
51     cursor = conn.cursor()
52     conn.select_db('python_test')
53     #創建表
54     sql = "CREATE TABLE IF NOT EXISTS \
55         ykgame(id int PRIMARY KEY AUTO_INCREMENT, title varchar(50), \
56         href varchar(50), date varchar(25))"        
57     cursor.execute(sql)
58     #插入數據庫
59     for i in range(1,10):
60         thread.start_new_thread(insert_db,(i,))
61         print '采集中...'
62     time.sleep(3)
63     #關閉數據庫
64     cursor.close()
65     conn.close()

說明:

  urllib2模塊:進行網頁內容抓取

  re模塊:進行正則表達式提取

  MySQLdb模塊:mysql操作

  thread模塊:多線程操作

  time模塊:time.sleep(3)

遇到的問題:

1.mysql中文亂碼:問題比較復雜,通用解決辦法如下

  程序中只要在開頭寫好:#coding=utf-8

  連接數據庫的時候設置編碼方式:conn=MySQLdb.connect(host="127.0.0.1",user="webdb",passwd="web123",db="web",charset="utf8")

      對於采集來的中文字符串,可以編碼轉換后插入str = str.decode("gbk").encode("utf-8")

 

2.Warning: Data truncated for column 'href' at row 1

  原因:href 數據庫中為 varchar(25),而實際長度>25

  解決辦法:將href 數庫中改為 varchar(50)

 

3.多線程問題:現象混亂有時候無報錯,注意事項如下

  使用相同資源是需要用資源鎖,不然出現異常

  線程處理時間短時,啟用線程后加time.sleep(3)

 

下篇預告:使用web.py搭建網站框架


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM