Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
先,介紹一下正則的概念。正則表達(dá)式是由一個(gè)字符序列形成的搜索模式。當(dāng)你在文本中搜索數(shù)據(jù)時(shí),你可以用搜索模式來(lái)描述你要查詢的內(nèi)容。正則表達(dá)式可用于所有文本搜索和文本替換的操作。其基本語(yǔ)法結(jié)構(gòu)如下:
/正則表達(dá)式主體/修飾符(可選)
其中,修飾符部分是可選內(nèi)容。常見(jiàn)的修飾符有:
修飾符描述i執(zhí)行對(duì)大小寫不敏感的匹配。g執(zhí)行全局匹配(查找所有匹配而非在找到第一個(gè)匹配后停止)。m執(zhí)行多行匹配。
另外,JS的正則表達(dá)式模式和Python相似,具體可以參考資料2所示。主要包括:方括號(hào)、元字符和量詞等。
支持正則表達(dá)式的String對(duì)象的方法如下:
方法描述FFIEsearch檢索與正則表達(dá)式相匹配的值。14match找到一個(gè)或多個(gè)正則表達(dá)式的匹配。14replace替換與正則表達(dá)式匹配的子串。14split把字符串分割為字符串?dāng)?shù)組。14
其中,match會(huì)返回匹配上的內(nèi)容,比較常用。
以下給出一個(gè)利用JavaScript正則獲取字符串括號(hào)內(nèi)的內(nèi)容的小例子:
encode='aa(ddsdd)gh'var re=/\([^\)]+\)/gencode=encode.match(re)[0]encode=encode.substring(1,encode.length-1) //ddsdd
原文鏈接:https://blog.csdn.net/sinat_23133783/article/details/109082113?utm_medium=distribute.pc_category.none-task-blog-hot-3.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-3.nonecase&request_id=
作者:麥片加奶不加糖
extract提取
注:extract 應(yīng)與request保持同一層級(jí)
注:變量名的前面要有 -
# 獲取響應(yīng)數(shù)據(jù): 響應(yīng)行(200,ok)\響應(yīng)頭
- config:
name: 測(cè)試百度網(wǎng)站
base_url: https://www.baidu.com
- test:
name: 接口名稱 百度接口
request:
url: /
method: GET
extract: # 提取值存儲(chǔ)到變量中
- code: status_code # 響應(yīng)碼
- info: reason # ok
- header_Content: headers.Content-Type # 響應(yīng)頭部
validate:
- eq: [$code,200] # 引用變量 $變量名
- eq: [$info,"OK"]
- eq: [$header_Content,'text/html']
extract 解析響應(yīng)正文(支持正則)
通過(guò) extract 提取響應(yīng)正文的數(shù)據(jù)并存儲(chǔ)到變量中(可使用正則提取),如下:
注:如果斷言為中文,加上headers頭部的Accept-Language即可,后面有專門寫的中文亂碼解碼的問(wèn)題解決
# 獲取響應(yīng)數(shù)據(jù) 響應(yīng)正文(支持正則)
- config:
name: 百度
base_url: https://www.baidu.com
- test:
name: 百度主頁(yè)
request:
url: /
method: GET
headers: # 如果斷言為中文的話,加上headers的Accept-Language即可
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36
extract:
- title: <title>(.+?)</title> # 可以使用正則表達(dá)式提取
validate:
- eq: [$title,"百度一下,你就知道"]
extract 解析響應(yīng)正文(支持json)
通過(guò) extract 提取響應(yīng)正文的數(shù)據(jù)并存儲(chǔ)到變量中(提取json數(shù)據(jù)),格式以content為根節(jié)點(diǎn):content.key.key.key ;如下:
次爬取用到的知識(shí)點(diǎn)有:
正文
1) 找到對(duì)應(yīng)的URL, URL里的參數(shù)正是Query String Parameters的參數(shù), 且請(qǐng)求方式是GET
2) 我們請(qǐng)求該URL得到內(nèi)容就是"Response"里的內(nèi)容, 那么點(diǎn)擊它來(lái)確認(rèn)信息.
3) 下拉看到"男裝"字樣, 那么再往下找, 并沒(méi)有發(fā)現(xiàn)有關(guān)"男裝"的商品信息.
4) 任意復(fù)制一個(gè)商品信息, 空白處右擊再點(diǎn)擊"查看網(wǎng)頁(yè)源代碼", 在源碼查找該商品, 即可看到該商品的信息.
5) 對(duì)比網(wǎng)頁(yè)源代碼和"Response"響應(yīng)內(nèi)容, 發(fā)現(xiàn)源代碼<script>..........</script>中的商品信息被替換, 這便是采用了JS加密
6) 如果去請(qǐng)求上面的URL, 得到的則是加密過(guò)的信息, 這時(shí)就可以利用Selenium庫(kù)來(lái)模擬瀏覽器, 進(jìn)而得到商品信息.
獲取單個(gè)商品界面
# -*- coding: utf-8 -*- from selenium import webdriver #從selenium導(dǎo)入瀏覽器驅(qū)動(dòng) browser=webdriver.Chrome() #聲明驅(qū)動(dòng)對(duì)象, 即Chrome瀏覽器 def get_one_page(): '''獲取單個(gè)頁(yè)面''' browser.get("https://www.xxxxx.com") #請(qǐng)求網(wǎng)站
# -*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver.common.by import By #導(dǎo)入元素定位方法模塊 from selenium.webdriver.support.ui import WebDriverWait #導(dǎo)入等待判斷模塊 from selenium.webdriver.support import expected_conditions as EC #導(dǎo)入判斷條件模塊 browser=webdriver.Chrome() def get_one_page(): '''獲取單個(gè)頁(yè)面''' browser.get("https://www.xxxxx.com") input=WebDriverWait(browser,10).until( #等待判斷 EC.presence_of_element_located((By.CSS_SELECTOR,"#q"))) #若輸入框顯示成功,則獲取,否則等待 input.send_keys("男裝") #輸入商品名稱
# -*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC browser=webdriver.Chrome() def get_one_page(): '''獲取單個(gè)頁(yè)面''' browser.get("https://www.xxxxx.com") input=WebDriverWait(browser,10).until( EC.presence_of_element_located((By.CSS_SELECTOR,"#q"))) # input.send_keys("男裝") button=WebDriverWait(browser,10).until( #等待判斷 EC.element_to_be_clickable((By.CSS_SELECTOR,"#J_TSearchForm > div.search-button > button"))) #若按鈕可點(diǎn)擊, 則獲取, 否則等待 button.click()
# -*- coding: utf-8 -*- ? import re from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC browser=webdriver.Chrome() def get_one_page(): '''獲取單個(gè)頁(yè)面''' browser.get("https://www.xxxxx.com") input=WebDriverWait(browser, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, "#q"))) input.send_keys("男裝") button=WebDriverWait(browser, 10).until( EC.element_to_be_clickable( (By.CSS_SELECTOR, "#J_TSearchForm > div.search-button > button"))) button.click() pages=WebDriverWait(browser, 10).until( # 等待判斷 EC.presence_of_element_located( (By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.total"))) # 若總頁(yè)數(shù)加載成功,則獲取總頁(yè)數(shù),否則等待 return pages.text def main(): pages=get_one_page() print(pages) if __name__=='__main__': main()
# -*- coding: utf-8 -*- import re from selenium import webdriver from selenium.common.exceptions import TimeoutException from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC browser=webdriver.Chrome() def get_one_page(): '''獲取單個(gè)頁(yè)面''' try: browser.get("https://www.xxxxx.com") input=WebDriverWait(browser,10).until( EC.presence_of_element_located((By.CSS_SELECTOR,"#q"))) input.send_keys("男裝") button=WebDriverWait(browser,10).until( EC.element_to_be_clickable((By.CSS_SELECTOR,"#J_TSearchForm > div.search-button > button"))) button.click() pages=WebDriverWait(browser,10).until( EC.presence_of_element_located((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > div.total"))) return pages.text except TimeoutException: return get_one_page() #如果超時(shí),繼續(xù)獲取 def main(): pages=get_one_page() pages=int(re.compile("(\d+)").findall(pages)[0]) #采用正則表達(dá)式提取文本中的總頁(yè)數(shù) print(pages) if __name__=='__main__': main() ?
關(guān)于Selenium的更多內(nèi)容,可參看官方文檔https://selenium-python.readthedocs.io/waits.html
獲取多個(gè)商品界面
采用獲取"到第 頁(yè)"輸入框方式, 切換到下一頁(yè), 同樣是等待判斷
需要注意的是, 最后要加入判斷: 高亮是否是當(dāng)前頁(yè)
def get_next_page(page): try: input=WebDriverWait(browser, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > input"))) # 若輸入框加載成功,則獲取,否則等待 input.send_keys(page) # 輸入頁(yè)碼 button=WebDriverWait(browser, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit"))) # 若按鈕可點(diǎn)擊,則獲取,否則等待 button.click() # 點(diǎn)擊按鈕 WebDriverWait(browser,10).until( EC.text_to_be_present_in_element((By.CSS_SELECTOR,"#mainsrp-pager > div > div > div > ul > li.item.active > span"),str(page))) # 判斷高亮是否是當(dāng)前頁(yè) except TimeoutException: # 超時(shí), 繼續(xù)請(qǐng)求 return get_next_page(page) def main(): pages=get_one_page() pages=int(re.compile("(\d+)").findall(pages)[0]) for page in range(1,pages+1): get_next_page(page) if __name__=='__main__': main()
獲取商品信息
首先, 判斷信息是否加載成功, 緊接著獲取源碼并初始化, 進(jìn)而解析.
需要注意的是, 在"get_one_page"和"get_next_page"中調(diào)用之后, 才可執(zhí)行
def get_info(): """獲取詳情""" WebDriverWait(browser,20).until(EC.presence_of_element_located(( By.CSS_SELECTOR,"#mainsrp-itemlist .items .item"))) #判斷商品信息是否加載成功 text=browser.page_source #獲取網(wǎng)頁(yè)源碼 html=pq(text) #初始化網(wǎng)頁(yè)源碼 items=html('#mainsrp-itemlist .items .item').items() #采用items方法會(huì)得到生成器 for item in items: #遍歷每個(gè)節(jié)點(diǎn)對(duì)象 data=[] image=item.find(".pic .img").attr("src") #用find方法查找子孫節(jié)點(diǎn),用attr方法獲取屬性名稱 price=item.find(".price").text().strip().replace("\n","") #用text方法獲取文本,strip()去掉前后字符串,默認(rèn)是空格 deal=item.find(".deal-cnt").text()[:-2] title=item.find(".title").text().strip() shop=item.find(".shop").text().strip() location=item.find(".location").text() data.append([shop, location, title, price, deal, image]) print(data)
保存到MySQL數(shù)據(jù)庫(kù)
def save_to_mysql(data): """存儲(chǔ)到數(shù)據(jù)庫(kù)""" # 創(chuàng)建數(shù)據(jù)庫(kù)連接對(duì)象 db=pymysql.connect(host="localhost",user="root",password="password",port=3306, db="spiders",charset="utf8") # 獲取游標(biāo) cursor=db.cursor() #創(chuàng)建數(shù)據(jù)庫(kù) cursor.execute("CREATE TABLE IF NOT EXISTS {0}(shop VARCHAR(20),location VARCHAR(10),title VARCHAR(255),price VARCHAR(20),deal VARCHAR(20), image VARCHAR(255))".format("男裝")) #SQL語(yǔ)句 sql="INSERT INTO {0} values(%s,%s,%s,%s,%s,%s)".format("男裝") try: #傳入?yún)?shù)sql,data if cursor.execute(sql,data): #插入數(shù)據(jù)庫(kù) db.commit() print("********已入庫(kù)**********") except: print("#########入庫(kù)失敗#########") #回滾,相當(dāng)什么都沒(méi)做 db.rollback() #關(guān)閉數(shù)據(jù)庫(kù) db.close()
完整代碼
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。