方法一html
r_list=re.findall('正則表達式',html,re.S)正則表達式
方法二 建立正則編譯對象json
pattern = re.compile('正則表達式',re.S)
r_list = pattern.findall(html)瀏覽器
正則表達式元字符:http://www.javashuo.com/article/p-fwmzwobw-s.htmlapp
類別 | 元字符 |
匹配字符 | . [...] [^...] \d \D \w \W \s \S |
匹配重複 | * + ? {n} {m,n} |
匹配位置 | ^ $ \A \Z \b \B |
其餘 | | () \ |
匹配任意一個字符的正則表達式框架
import re pattern = re.compile('.',re.S) # 方法一 pattern = re.compile('[\s\S]') # 方法二
貪婪匹配(默認)dom
非貪婪匹配ide
做用:在完整的模式中定義子模式,將每一個圓括號中子模式匹配出來。函數
import re s = 'A B C D' p1 = re.compile('\w+\s+\w+') print(p1.findall(s)) # # ['A B','C D'] p2 = re.compile('(\w+)\s+\w+') print(p2.findall(s)) # # ['A','C'] p3 = re.compile('(\w+)\s+(\w+)') print(p3.findall(s)) # # [('A','B'),('C','D')]
import re html = '''<div class="animal"> <p class="name"> <a title="Tiger"></a> </p> <p class="content"> Two tigers two tigers run fast </p> </div> <div class="animal"> <p class="name"> <a title="Rabbit"></a> </p> <p class="content"> Small white rabbit white and white </p> </div>''' pattern = re.compile( '<div class="animal">.*?title="(.*?)".*?' 'class="content">(.*?)</p>', re.S) r_list = pattern.findall(html) print(r_list)
分組總結工具
XPath即爲XML路徑語言,它是一種用來肯定XML文檔中某部分位置的語言,一樣適用於HTML文檔的檢索,咱們來利用xpath對HTML代碼進行檢索試試,如下是HTML示例代碼。
<ul class="book_list"> <li> <title class="book_001">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>69.99</price> </li> <li> <title class="book_002">Spider</title> <author>Forever</author> <year>2019</year> <price>49.99</price> </li> </ul>
匹配演示
一、查找全部的li節點
//li
二、查找li節點下的title子節點中,class屬性值爲'book_001'的節點
//li/title[@class="book_001"]
三、查找li節點下全部title節點的,class屬性的值
//li//title/@class
只要涉及到條件,加 []
只要獲取屬性值,加 @
選取節點
// :從全部節點中查找(包括子節點和後代節點)
@ :獲取屬性值
# 使用場景1(屬性值做爲條件) //div[@class="movie"] # 使用場景2(直接獲取屬性值) //div/a/@src
匹配多路徑(或)
xpath表達式1 | xpath表達式2 | xpath表達式3
contains() :匹配屬性值中包含某些字符串節點
# 查找class屬性值中包含"book_"的title節點 //title[contains(@class,"book_")] # 匹配ID名含qiushi_tag_字符串的div節點 //div[contains(@id,"qiushi_tag_")]
text() :獲取節點的文本內容
# 查找全部書籍的名稱 //ul[@class="book_list"]/li/title # 結果:<element title at xxxx> //ul[@class="book_list"]/li/title/text() # 結果:'Harry Potter'
練習貓眼電影xpath信息檢索:https://maoyan.com/board/4?offset=1
一、獲取貓眼電影中電影信息的 dd 節點
//dl[@class="board-wrapper"]/dd
二、獲取電影名稱
//dl[@class="board-wrapper"]/dd//p[@class="name"]/a/text()
三、獲取電影主演的
//dl[@class="board-wrapper"]/dd//p[@class="star"]/text()
四、獲取上映商檢的xpath
//dl[@class="board-wrapper"]/dd//p[@class="releasetime"]/text()
from lxml import etree html = """ <div class="wrapper"> <i class="iconfont icon-back" id="back"></i> <a href="/" id="channel">新浪社會</a> <ul id="nav"> <li><a href="http://domestic.firefox.sina.com/" title="國內">國內</a></li> <li><a href="http://world.firefox.sina.com/" title="國際">國際</a></li> <li><a href="http://mil.firefox.sina.com/" title="軍事">軍事</a></li> <li><a href="http://photo.firefox.sina.com/" title="圖片">圖片</a></li> <li><a href="http://society.firefox.sina.com/" title="社會">社會</a></li> <li><a href="http://ent.firefox.sina.com/" title="娛樂">娛樂</a></li> <li><a href="http://tech.firefox.sina.com/" title="科技">科技</a></li> <li><a href="http://sports.firefox.sina.com/" title="體育">體育</a></li> <li><a href="http://finance.firefox.sina.com/" title="財經">財經</a></li> <li><a href="http://auto.firefox.sina.com/" title="汽車">汽車</a></li> </ul> <i class="iconfont icon-liebiao" id="menu"></i> </div>""" # 問題1:獲取全部 a 節點的文本內容 parse_html = etree.HTML(html) r_list = parse_html.xpath('//a/text()') print(r_list) # ['新浪社會', '國內', '國際',.....] # 問題2:獲取全部 a 節點的 href 的屬性值 parse_html = etree.HTML(html) r_list = parse_html.xpath('//a/@href') print(r_list) # ['/', 'http://domestic.firefox.sina.com/', 'http://world.firefox.sina.com/'...] # 問題3: 獲取全部 a 節點的href的屬性值, 可是不包括 / parse_html = etree.HTML(html) r_list = parse_html.xpath('//ul[@id="nav"]/li/a/@href') print(r_list) # ['http://domestic.firefox.sina.com/', 'http://world.firefox.sina.com/'...] # 問題4: 獲取 圖片、軍事、...,不包括新浪社會 parse_html = etree.HTML(html) r_list = parse_html.xpath('//ul[@id="nav"]/li/a/text()') print(r_list) # ['國內', '國際',.....]
地址: 貓眼電影 - 榜單 - top100榜 https://maoyan.com/board/4
目標: 電影名稱、主演、上映時間
步驟:
xpath表達式
一、基準xpath: 匹配全部電影信息的節點對象列表
//dl[@class="board-wrapper"]/dd
二、遍歷對象列表,依次獲取每一個電影信息
for dd in dd_list:
遍歷後繼續xpath必定要以: . 開頭,表明當前節點
電影名稱 :
dd.xpath('./a/@title')[0].strip()
電影主演 :
dd.xpath('.//p[@class="star"]/text()')[0].strip()
上映時間 :
dd.xpath('.//p[@class="releasetime"]/text()')[0].strip()
完整代碼:
import requests from lxml import etree import time import random class MaoyanSpider(object): def __init__(self): self.page = 1 # 用於記錄頁數 self.url = 'https://maoyan.com/board/4?offset={}' self.ua_list = [ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.\ 163 Safari/535.1', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; \ .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)'] # 獲取頁面 def get_page(self, url): # 每次使用隨機的user-agent try: # 每次使用隨機的user-agent headers = {'User-Agent': random.choice(self.ua_list)} res = requests.get(url, headers=headers, timeout=5) res.encoding = 'utf-8' html = res.text self.parse_page(html) except Exception as e: print('Error') self.get_page(url) # 解析頁面 def parse_page(self, html): parse_html = etree.HTML(html) # 建立解析對象 # 基準xpath節點對象列表 dd_list = parse_html.xpath('//dl[@class="board-wrapper"]/dd') item = {} # 依次遍歷每一個節點對象,提取數據 if dd_list: for dd in dd_list: # ['喜劇之王'] 由於返回的是列表,因此取第0個值,獲得的是字符串 name_list = dd.xpath('.//p/a/@title') # 電影名稱 item['name'] = [name_list[0].strip() if name_list else None][0] star_list = dd.xpath('.//p[@class="star"]/text()') # 電影主演 item['star'] = [star_list[0].strip() if star_list else None][0] time_list = dd.xpath('.//p[@class="releasetime"]/text()') # 上映時間 item['time'] = [time_list[0].strip() if time_list else None] print(item) else: print('No Data') # 主函數 def main(self): for offset in range(0, 31, 10): url = self.url.format(str(offset)) self.get_page(url) print('第%d頁完成' % self.page) time.sleep(random.randint(1, 3)) self.page += 1 if __name__ == '__main__': start = time.time() spider = MaoyanSpider() spider.main() end = time.time() print('執行時間: %.2f' % (end - start))
肯定是否爲靜態
打開二手房頁面 -> 查看網頁源碼 -> 搜索關鍵字,可以搜索到就說明,是靜態頁面。
xpath表達式
一、基準xpath表達式(匹配每一個房源信息節點列表)
//ul[@class="sellListContent"]/li[@class="clear LOGCLICKDATA"] | //ul[@class="sellListContent"]/li[@class="clear LOGVIEWDATA LOGCLICKDATA"]
二、依次遍歷後每一個房源信息xpath表達式
代碼實現
import requests from lxml import etree import time import random class LianjiaSpider(object): def __init__(self): self.url = 'https://bj.lianjia.com/ershoufang/pg{}/' self.blog = 1 self.ua_list = [ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET \ CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)', ] def get_html(self, url): headers = {'User-Agent': random.choice(self.ua_list)} # 嘗試3次,不然換下一頁地址 if self.blog <= 3: try: # 設定超時時間,超時後拋出異常,被except捕捉,繼續執行此函數再次請求 res = requests.get(url=url, headers=headers, timeout=5) res.encoding = 'utf-8' html = res.text self.parse_page(html) # 直接調用解析函數 except Exception as e: print('再次嘗試') self.blog += 1 self.get_html(url) def parse_page(self, html): parse_html = etree.HTML(html) # li_list: [<element li at xxx>,<element li at xxx>] li_list = parse_html.xpath('//ul[@class="sellListContent"]/li[@class="clear LOGVIEWDATA LOGCLICKDATA"]') item = {} for li in li_list: name_list = li.xpath('.//a[@data-el="region"]/text()') # 名稱 item['name'] = [name_list[0].strip() if name_list else None][0] info_list = li.xpath('.//div[@class="houseInfo"]/text()') # 戶型+面積+方位+是否精裝 if info_list: info_list = info_list[0].strip().split('|') if len(info_list) == 5: item['model'] = info_list[1].strip() item['area'] = info_list[2].strip() item['direction'] = info_list[3].strip() item['perfect'] = info_list[4].strip() else: item['model'] = item['area'] = item['direction'] = item['perfect'] = None else: item['model'] = item['area'] = item['direction'] = item['perfect'] = None floor_list = li.xpath('.//div[@class="positionInfo"]/text()') # 樓層 item['floor'] = [floor_list[0].strip().split()[0] if floor_list else None][0] address_list = li.xpath('.//div[@class="positionInfo"]/a/text()') # 地區 item['address'] = [address_list[0].strip() if address_list else None][0] total_list = li.xpath('.//div[@class="totalPrice"]/span/text()') # 總價 item['total_price'] = [total_list[0].strip() if total_list else None][0] unit_list = li.xpath('.//div[@class="unitPrice"]/span/text()') # 單價 item['unit_price'] = [unit_list[0].strip() if unit_list else None][0] print(item) def main(self): for pg in range(1, 11): url = self.url.format(pg) self.get_html(url) time.sleep(random.randint(1, 3)) # 對self.blog進行一下初始化 self.blog = 1 if __name__ == '__main__': start = time.time() spider = LianjiaSpider() spider.main() end = time.time() print('執行時間:%.2f' % (end - start))
安裝方法
須要安裝插件