1. 程式人生 > 其它 >python爬蟲(含scrapy)

python爬蟲(含scrapy)

python爬蟲

1.解析HTML:

lxml 是一種python編寫的庫,可以迅速、靈活的處理xml和html

使用:根據版本的不同,有如下兩種:

  • 形式1:

    from lxml import etree

    轉換成樹形結構物件:

    obj=etree.HTML(htmlStr)

  • 形式2:

    from lxml import html

    getHtml=requests.get(url,headers=header)

    htmlObj=html.fromstring(getHtml.content.decode("utf8"))

    htmlObj.xpath("")

a、xpath語法:

表示式 說明
/ 從根節點選取
// 從匹配選擇的當前節點選擇文件中的節點,而不考慮它們的位置
@ 選取屬性
. 選擇當前節點
節點名 1選取此節點所有子節點
//book 選取所有book子元素,而不管它們在文件中的位置
div//book 選擇屬性div元素的後代的所有book元素,而不管它們位於div之下的什麼位置
//@lang 選取名為lang的所有屬性

b、舉例

路徑表示式 結果
/div/div[1] 選取資料div元素的第一個div元素
/div/div[last()] 選取屬於div元素的最後一個div元素
/div/div[last()-1] 選取屬於div元素的倒數第二個div元素
/div/div[position() < 3] 選取最前面的兩個屬於div元素的子元素的book元素
//title[@lang] 選取所有擁有名為lang屬性的title元素
//title[@lang='eng'] 選取所有lang屬性值為eng的title元素

2.解析json

import json
str='{"result":0,"data":[{"id":"664","numbers":"42235"}],"msg":"\u6210\u529f"}'
obj=json.loads(str)
xxrs=obj['data'][0]['numbers']
print(xxrs)#結果:42235

3.正則表示式

菜鳥教程:https://www.runoob.com/python/python-reg-expressions.html

正則表示式:

字元 描述
[…] 用來表示一組字元, 單獨列出, 例如, [amk]匹配a, m或k
[^…] 不在[]中的字元, 例如, [^abc]匹配除了a, b, c之外的字元
* 匹配0個或多個的表示式
+ 匹配1個或者多個的表示式
? 匹配0個或1個由前面的正則表示式定義的片段, 非貪婪方式
{n} 精確匹配n次前面的表示
{n,m} 匹配n到m次由前面的正則表示式定義的片段, 貪婪模式
a|b 匹配a或者b
( ) 匹配括號內的表示式, 也表示一個組
例項 描述
[Pp]ython 匹配 "Python" 或 "python"
rub[ye] 匹配 "ruby" 或 "rube"
[aeiou] 匹配中括號內的任意一個字母
[0-9] 匹配任何數字。類似於 [0123456789]
[a-z] 匹配任何小寫字母
[A-Z] 匹配任何大寫字母
[a-zA-Z0-9] 匹配任何字母及數字
[^aeiou] 除了aeiou字母以外的所有字元
. 匹配除 "\n" 之外的任何單個字元。要匹配包括 '\n' 在內的任何字元,請使用象 '[.\n]' 的模式。
\d 匹配一個數字字元。等價於 [0-9]。
\D 匹配一個非數字字元。等價於 [^0-9]。
\s 匹配任何空白字元,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。
\S 匹配任何非空白字元。等價於 [^ \f\n\r\t\v]。
\w 匹配包括下劃線的任何單詞字元。等價於'[A-Za-z0-9_]'。
\W 匹配任何非單詞字元。等價於 '[^A-Za-z0-9_]'。

a.常用方法:

  • re.findall()

使用案例:

import re
a="宣告:python是一門簡單的語言!python是一門好用的語言!"
#findall() 返回資料為list格式
result=re.findall("python(.*)!",a)# ['是一門簡單的語言!python是一門好用的語言']

result2=re.findall("python(.*?)!",a)#['是一門簡單的語言','是一門好用的語言']

# (.*)貪婪匹配,會盡可能的往後匹配
# (.*?) 非貪婪匹配,會盡可能少的匹配,是否加?影響匹配結果的長度

4.scrapy使用步驟:

  1. 新建資料夾(scrapyPro)存放scrapy檔案
  2. 到scrapyPro目錄下,執行:scrapy startproject scrapyOne
  3. 進入到scrapyOne下的spiders目錄執行:scrapy genspider 爬蟲名稱 xxx.com
  4. 用編碼工具修改settings.py 中的robots 設定為false
  5. 修改爬蟲程式程式碼
  6. 執行爬蟲:scrapy crawl 爬蟲名稱

a.scrapy使用小知識

  • Settings.py檔案介紹:

    專案名:BOT_NAME = ‘xxxx‘

    遵循ROBOT協議:ROBOTSTXT_OBEY = False

    使用者身份:USER_AGENT =‘xxxx’

    最大併發數:CONCURRENT_REQUESTS=32預設為16

    下載延遲:DOWNLOAD_DELAY = 3
    每個域名最大併發數:CONCURRENT_REQUESTS_PER_DOMAIN

    Cookie設定:COOKIES_ENABLED預設為true,下次請求帶上cookie
    預設請求頭設定:DEFAULT_REQUEST_HEADERS

    一系列中介軟體、快取、http請求的配置等(不常用)

  • 爬蟲專案的工程目錄及各個組成的作用:

    scrapy.cfg:專案配置檔案。
    settings.py:專案設定檔案。

    pipelines.py:專案管道檔案,主要用於對

    Items定義的資料進行加工與處理。

    middlewares.py:專案的中介軟體檔案。

    items.py:專案的資料容器檔案,用於定義獲取的資料。

    init.py:初始化檔案。
    spiders目錄:爬蟲目錄,例如,建立檔案、編寫爬蟲解析規則等

b.資料儲存的四種格式

  1. 以txt文字形式儲存:

    class xxxxPipeline:
        def __init__(self):
            self.file=open("test.txt","w",encoding="utf8")
            
        def process_item(self,item,spider):
            row='{},{},{},{}\n'.format(item['name'],
                                       item['age'],item['zy'],item['dy'])
            self.file.write(row)
            return item
        def close(self):
            self.file.close()
    
  2. CSV格式

    import csv
    
    class xxxxPipeline:
        def __init__(self):
            self.file = open('../moot2.csv','a',encoding='utf-8',newline='')
            self.writer = csv.writer(self.file,delimiter=';')
            self.writer.writerow(['表頭1','表頭2',.....])
            
        def process_item(self,item,spider):
           self.writer.writerow([item['title'],item['price'],......])
           return item
        def close(self):
            self.file.close()
    
  3. json格式:

    import json
    
    class xxxxPipeline:
        def __init__(self):
            self.file = open('../moot2.json','a',encoding='utf-8')
            
            
        def process_item(self,item,spider):
           jsonstr = json.dumps(dict(item),ensure_ascii=False)
           self.file.write(jsonstr+'\n')
           return item
        def close(self):
            self.file.close()
    
  4. mysql儲存

    import pymysql
    
    class xxxxPipeline:
        def __init__(self):
            self.conn = pymysql.connect(host='IP/localhost',
                                       user='root',password='123456',
                                        port=3306,db='資料庫名')
            self.cursor = self.conn.cursor()
            
        def process_item(self,item,spider):
           sql = "insert into tb_moot values(null,%s,%s,......)"
           self.cursor.execute(sql,(item['title'],item['price'],.......))
           self.conn.commit()
           return item
        
        def close(self):
            self.cursor.close()
            self.conn.close()