import random
import re
import time
import xlsxwriter
from selenium import webdriver
from lxml import etree
import requests
# ua池
ua_list=[
"Mozilla/5.0 (Windows NT 10.0; Win64; x32) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.39 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.26 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36',
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X; zh-CN) AppleWebKit/537.51.1 (KHTML, like Gecko) Mobile/17D50 UCBrowser/12.8.2.1268 Mobile AliApp(TUnionSDK/0.1.20.3)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36',
'Mozilla/5.0 (Linux; Android 8.1.0; OPPO R11t Build/OPM1.171019.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/11.19 SP-engine/2.15.0 baiduboxapp/11.19.5.10 (Baidu; P1 8.1.0)',
'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.14.0 main%2F1.0 baiduboxapp/11.18.0.16 (Baidu; P2 13.3.1) NABar/0.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134',
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
]
ua=random.choice(ua_list)
# Ip池
proxy_list=[
{"http" or "https": "124.71.14.222:10002"},
{"http" or "https": '60.167.133.17:1133'},
{"http" or "https": '183.0.203.167:8118'},
{"http" or "https": '111.231.86.149:7890'},
{"http" or "https": "183.0.203.167:8118"},
{"http" or "https": '163.125.222.12:8118'},
{"http" or "https": '111.59.199.58:8118'},
]
proxies=random.choice(proxy_list)
word=input('請輸入你要獲取的商品:', )
page=input('請輸入商品頁數:',)
# 獲取商品鏈接和id
def get_link():
links=[]
skus_id=[]
for i in range(int(page)):
url=f'https://search.jd.com/Search?keyword={word}&wq={word}&page={i}'
headers={
"user-agent": ua,
}
res=requests.get(url=url, headers=headers, proxies=proxies).text
time.sleep(0.5)
# print(res)
# 提取商品鏈接并進行拼接操作
html=etree.HTML(res)
link=html.xpath('//*[@id="J_goodsList"]/ul/li[*]/div/div[3]/a/@href')
link=['https:' + k for k in link]
for l in link:
links.append(l)
# 提取商品id
sku_id=[re.findall('\d+', i)[0] for i in link]
for s in sku_id:
skus_id.append(s)
print(f'第{i+1}頁。')
print(links)
goods(links, skus_id)
# 獲取商品詳情
def goods(links, skus_id):
goo=[]
pict=0
for i in range(len(links)):
headers={
"User-Agent": ua,
'referer': 'https://search.jd.com/',
}
res=requests.get(url=links[i], headers=headers, proxies=proxies).text
time.sleep(2)
# print(res)
html=etree.HTML(res)
# 店鋪名稱
title=html.xpath('//*[@id="crumb-wrap"]/div/div[2]/div[2]/div[1]/div/a/@title')
print(title)
# 品牌
brand=html.xpath('//*[@id="parameter-brand"]/li/@title')
print(brand)
# 商品編號
serial=html.xpath('//*[@id="detail"]/div[2]/div[1]/div[1]/ul[2]/li[2]/text()')
serial=[serial[0].split(':')[-1]]
print(serial)
# 正式商品名稱
official=html.xpath('//*[@id="detail"]/div[2]/div[1]/div[1]/ul[2]/li[1]/text()')
official=[official[0].split(':')[-1].strip()]
print(official)
# 網頁商品名稱
name=html.xpath('/html/body/div[6]/div/div[2]/div[1]/text()')
if len(name)==1:
name=[name[0].strip()]
elif len(name)==2:
name=[name[1].strip()]
print(name)
# 商品第一張主圖片
picture=['https:' + html.xpath('//*[@id="spec-img"]/@data-origin')[0]]
print(picture)
res2=requests.get(url=picture[0], headers=headers)
with open(f'D:\pythonproject\python項目爬蟲\接單\京東商品評價獲取(接單考核)\商品圖片/{pict}.jpg', 'wb')as f:
f.write(res2.content)
pict +=1
# 京東價,請求價格信息json
p=requests.get('https://p.3.cn/prices/mgets?skuIds=J_' + skus_id[i], headers=headers, proxies=proxies).text
print(p)
price=re.findall('"p":"(.*?)","op"', p)
print(price)
# 優惠劵和促銷
options=webdriver.ChromeOptions()# 無界面模式
options.add_argument('--headless')
driver=webdriver.Chrome(options=options)
driver.get(links[i])
time.sleep(1)
# 獲取源代碼
data=driver.page_source
time.sleep(0.5)
driver.close()
driver.quit()
# 促銷
html2=etree.HTML(data)
promotion1=html2.xpath('//*[@id="prom"]/div/div[1]/em[2]/text()')
promotion2=html2.xpath('//*[@id="prom"]/div/div[2]/em[2]/text()')
if promotion1==[] and promotion2==[]:
promotion=['暫無促銷信息']
elif promotion1==[] and promotion2 !=[]:
promotion=promotion2
elif promotion2==[] and promotion1 !=[]:
promotion=promotion1
else:
promotion=[promotion1[0], promotion2[0]]
print(promotion)
# 優惠劵信息
coupon=html2.xpath('//*[@id="summary-quan"]/div[2]/dl/dd/a/span/span/text()')
if coupon==[]:
coupon=['暫無可領的優惠券']
print(coupon)
# 累計評價
comm_url=f'https://club.jd.com/comment/productCommentSummaries.action?referenceIds={skus_id[i]}'
comment_headers={
'user-agent': ua,
}
res_js=requests.get(url=comm_url, headers=comment_headers, proxies=proxies).text
comment=re.findall('"CommentCountStr":"(.*?)","CommentCount":', res_js)
print(comment)
for g in zip(title, brand, serial, official, name, price, promotion, coupon, comment, picture):
goo.append(g)
print(f'第{i+1}件商品打印完成。')
print(goo)
save(goo)
5.數據保存,并通過xlsxwrite進行圖片保存
# 數據保存
def save(goo):
# 創建工作簿
workbook=xlsxwriter.Workbook('京東商品詳情.xlsx')
# 創建工作表
worksheet=workbook.add_worksheet(word)
# 大部分樣式如下:
format={
# 'font_size': 10, # 字體大小
'bold': True, # 是否粗體
# 'bg_color': '#101010', # 表格背景顏色
# 'fg_color': '#00FF00',
# 'font_color': '#0000FF', # 字體顏色
'align': 'center', # 水平居中對齊
'valign': 'vcenter', # 垂直居中對齊
# 'num_format': 'yyyy-mm-dd H:M:S',# 設置日期格式
# 后面參數是線條寬度
'border': 1, # 邊框寬度
'top': 1, # 上邊框
'left': 1, # 左邊框
'right': 1, # 右邊框
'bottom': 1 # 底邊框
}
style=workbook.add_format(format)
# 寫入圖片
a=0
worksheet.set_column(9, 9, 350) # 設置列寬
for i in range(len(goo)):
worksheet.set_row(i + 1, 350) # 設置行高350
worksheet.insert_image(i + 1, 9, f'D:\pythonproject\python項目爬蟲\接單\京東商品評價獲取(接單考核)\商品圖片/{a}.jpg', {'url': goo[i][-1]})
a +=1
# 寫入數據
col=('店鋪名稱', '品牌', '商品編號', '正式商品名稱', '網頁商品名稱', '京東價', '促銷', '優惠劵', '累計評價', '商品第一張主圖片',)
for i in range(len(col)):
worksheet.write(0, i, col[i])
for i in range(len(goo)):
for c in range(len(col) - 1):
worksheet.write(i + 1, c, goo[i][c], style)
workbook.close()
6.開啟程序
if __name__=='__main__':
get_link()
原文鏈接:https://blog.csdn.net/weixin_62871152/article/details/121457846
開始之前,做一點小小的說明哈:
首先打開網易云的網頁版網易云
然后搜索歌曲,這里我就搜索一首錦零的“空山新雨后”
這時我們來觀察網頁的url,可以發現s=后面就是我們搜索的關鍵字
當我們換一首歌,會發現也是這樣的,正好驗證了我們的想法
所以下一步讓我們點進去一首歌,然后進行播放,看看能否直接獲取音樂文件的url,如果能,那么直接對url進行requests.get訪問,我們就能拿到.mp3文件了
點進第一首“空山新雨后”,我們可以看到有一個“生成外鏈播放器”
看到這個,我心中一陣激動,仿佛就要大功告成;于是我滿懷開心的點了一下,結果。。。
好吧,不過我們不能放棄,來我們分析一下網頁
但當我們定位到兩個最有可能出現外鏈的地方時,發現什么都沒有
不過作為“規格嚴格,功夫到家”的傳承者,我不能放棄啊,于是我又打開了抓包工具
按照常規套路,我們定位到XHR
點擊播放后,出現了一大堆東西,我們要做的就是找到其中的content-type為audio一類的包
功夫不負有心人,在尋找了一(億)會兒后,我找到了
于是我又滿懷開心的復制了這個包對應的Request-URL
粘貼后訪問這個url,結果非常滿意,這就是我一直在找的url
現在我把那個url貼出來
https://m10.music.126.net/20200715163315/a075d787d191f6729a517527d6064f59/ymusic/0552/0f0e/530f/28d03e94478dcc3e0479de4b61d224e9.mp3
接下來就超級簡單了
下面的代碼是最常規的操作,應該有爬蟲基礎的都能看懂;如果有不懂的,注釋都在上面
#導入requests包
import requests
#進行UA偽裝
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36'
}
#指定url
url='https://m10.music.126.net/20200715163315/a075d787d191f6729a517527d6064f59/ymusic/0552/0f0e/530f/28d03e94478dcc3e0479de4b61d224e9.mp3'
#調用requests.get方法對url進行訪問,和持久化存儲數據
audio_content=requests.get(url=url,headers=headers).content
#存入本地
with open('空山新雨后.mp3','wb') as f :
f.write(audio_content)
print("空山新雨后爬取成功!!!")
看到這里,你可能會想,為啥根本沒用selenium模塊呢?能不能直接爬取任何一首我想要的歌,而不用每首都去費心費力的找一個url呢?當然可以噠!
其實網易云在線播放每首歌曲時,都有一個外鏈地址,這是不會變的,跟每首歌的唯一一個id綁定在一起,每首歌audio文件的url如下:
url='http://music.163.com/song/media/outer/url?id=' + 歌曲的id值 + '.mp3'
id值的獲取也很簡單,當我們點進每首歌時,上方會出現對應的網址,那里有id值,如下圖:
所以只需把上面程序中的url改成新的url即可
如果還想要更好的體驗效果,實現在程序里直接搜索歌曲,拿到id值,就需要用到selenium模塊
為什么用selenium而不用xpath或bs4?
因為搜索頁面的數據是動態加載出來的,如果直接對搜索頁面的網頁進行數據解析,就拿不到任何數據;以我目前的技術,就只能想到使用萬能的selenium模塊,下面大概說明一下步驟:
from selenium.webdriver.chrome.options import Options
chrome_options=Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
import requests
import re
from selenium import webdriver
from time import sleep
name=input('請輸入歌名:')
url_1='https://music.163.com/#/search/m/?s=' + name + '&type=1'
#初始化browser對象
browser=webdriver.Chrome(executable_path='chromedriver.exe',chrome_options=chrome_options)
#訪問該url
browser.get(url=url_1)
#由于網頁中有iframe框架,進行切換
browser.switch_to.frame('g_iframe')
#等待0.5秒
sleep(0.5)
#抓取到頁面信息
page_text=browser.execute_script("return document.documentElement.outerHTML")
#退出瀏覽器
browser.quit()
ex1='<a.*?id="([0-9]*?)"'
ex2='<b.*?title="(.*?)"><span class="s-fc7">'
ex3='class="td w1"><div.*?class="text"><a.*?href=".*?">(.*?)</a></div></div>'
id_list=re.findall(ex1,page_text,re.M)[::2]
song_list=re.findall(ex2,page_text,re.M)
singer_list=re.findall(ex3,page_text,re.M)
li=list(zip(song_list,singer_list,id_list))
for i in range(len(li)):
print(str(i+1) + '.' + str(li[i]),end='\n')
終究是我才疏學淺,這個找外鏈進行爬取的方法也存在很多不足,比如不能在線播放的歌曲是無法下載的。
不過寫這樣一個小程序練練手,對自己能力的提高確是有極大幫助的。
Python 和 JavaScript 是兩種廣泛應用于 Web 開發的重要編程語言,在日常的 Web 開發和 Web 數據處理中,我們經常需要使用這兩種語言。
例如,在 Web 端爬蟲過程中,我們可能會遇到需要解密網頁源代碼的情況,這時就需要一層一層剝離關鍵的 JS 代碼,并使用 Python 執行這段代碼以獲取關鍵信息。
那么,Python 如何調用 JS 呢?有哪些方式呢?
以一段簡單的JS腳本(add.js)為例,計算兩個數的和。
// JavaScript 示例代碼
function add(a, b) {
return a + b;
}
使用 Python 的os.popen或subprocess執行 node 命令,執行 JS 腳本。
首先,確保本地已經安裝了 Node.js 環境:
> node -v
v18.16.1
修改 JS 腳本,新增一個導出函數 init ,方便內部函數被調用:
// JavaScript 示例代碼
function add(a, b) {
return a + b;
}
// 新增一個導出函數(node方式)
module.exports.init=function (arg1, arg2) {
// 調用函數,并返回
console.log(add(arg1, arg2));
};
// 調用 init 方法并傳遞參數
module.exports.init(parseInt(process.argv[3]), parseInt(process.argv[4]));
使用subprocess模擬node.js命令行調用并獲取結果:
import subprocess
from loguru import logger
if __name__=='__main__':
# 使用 subprocess 模塊執行 Node.js 命令
result=subprocess.run(["node", "add.js", "init", "3", "5"], capture_output=True, text=True)
# 輸出執行結果
logger.info(f"Node.js 執行結果: {result.stdout.strip()}")
PyExecJS 是使用最多的一種方式,底層實現方式是本地 JS 環境下運行 JS 代碼,支持的 JS 環境包含:Node.js、PhantomJS 等。
首先第一步安裝:
pip install PyExecJS==1.5.1
安裝完成之后,即可以使用其調用 JS 腳本:
#! -*-conding=: UTF-8 -*-
from loguru import logger
import execjs
# 定義 JavaScript 代碼
# js_code="""
# function add(a, b) {
# return a + b;
# }
# """
if __name__=='__main__':
# Python 示例代碼
js_code=open("add.js", "r", encoding="utf-8").read()
# 使用 PyExecJS 執行 JavaScript 代碼
ctx=execjs.compile(js_code)
# 調用 JavaScript 函數,并計算結果
result=ctx.call("add", 3, 5)
logger.info(f"調用 JavaScript 函數的結果為: {result}")
DrissionPage方式
這款工具既能控制瀏覽器,也能收發數據包,甚至能把兩者合而為一。
首先安裝依賴庫:
pip install DrissionPage==4.0.4.22
執行 JS 腳本:
#! -*-conding=: UTF-8 -*-
from DrissionPage import ChromiumPage
if __name__=='__main__':
page=ChromiumPage()
# 打開網頁
page.get("about:blank")
# 定義 JavaScript 代碼
js_code="""
function add(a, b) {
return a + b;
}
"""
# 在當前頁面上執行 JavaScript 代碼,并傳遞參數
result=page.run_js(js_code + " return add(8, 5)")
# 輸出執行結果
print("JavaScript 執行結果:", result) # JavaScript 執行結果: 13
page.quit()
playwright方式
Playwright 是一個用于 Web 測試和自動化的框架。
首先安裝依賴庫:
pip install playwright==1.43.0
playwright install # 安裝驅動
執行 JS 腳本:
#! -*-conding=: UTF-8 -*-
from playwright.sync_api import sync_playwright
if __name__=='__main__':
# 啟動 Playwright
with sync_playwright() as p:
# 啟動 Chromium 瀏覽器
browser=p.chromium.launch(headless=False)
# 創建新頁面
page=browser.new_page()
# 打開網頁
page.goto("https://baidu.com")
# 定義 JavaScript 代碼
js_code="""
function add(a, b) {
return a + b;
}
"""
page.add_script_tag(content=js_code) # 使用 page.add_script_tag() 方法將其注入到頁面中,然后在頁面上執行它
# 在當前頁面上執行 JavaScript 代碼
result=page.evaluate("add(5, 7)")
# 輸出執行結果
print("JavaScript 執行結果:", result) # JavaScript 執行結果: 12
# 關閉瀏覽器
browser.close()
selenium方式
Selenium是一個用于測試網站的自動化測試工具,支持各種瀏覽器包括 Chrome、Firefox、Safari 等主流界面瀏覽器和 phantomJS 無界面瀏覽器。
首先安裝依賴庫:
pip install selenium==4.20.0
執行 JS 腳本:
#! -*-conding=: UTF-8 -*-
from selenium import webdriver
# 啟動 Chrome 瀏覽器
driver=webdriver.Chrome()
# 打開網頁
driver.get("about:blank")
# 定義 JavaScript 代碼
js_code="""
function add(a, b) {
return a + b;
}
"""
# 在當前頁面上執行 JavaScript 代碼,并傳遞參數
result=driver.execute_script(js_code + " return add(3, 5)")
# 輸出執行結果
print("JavaScript 執行結果:", result)
# 關閉瀏覽器
driver.quit()
類似的自動化工具還有很多,如果只是單純的調用 JS 腳本,屬實有點殺雞用牛刀的趕jio。
Js2Py 作為一個純 Python 實現的 JS 解釋器,可以完全脫離 JS 環境,直接將 JS 代碼轉換為 Python 代碼。
首先第一步安裝:
pip install Js2Py==0.74
調用 JS 腳本:
#! -*-conding=: UTF-8 -*-
from js2py import eval_js
if __name__=='__main__':
# JavaScript 示例代碼
js_code="""
function add(a, b) {
return a + b;
}
"""
# 執行 JavaScript 代碼
result=eval_js(js_code + "add(3, 5)")
# 輸出執行結果
print("JavaScript 執行結果:", result)
PyMiniRacer 是一個 Python 模塊,它提供了一個輕量級、快速且安全的方式來執行 JavaScript 代碼,無需借助完整的 V8 引擎或 Node.js 環境。
不知道佬們用的多不多,據說速度比PyExecJS快不少。
直接安裝:
pip install py_mini_racer==0.6.0
運行:
#! -*-conding=: UTF-8 -*-
from py_mini_racer import MiniRacer
if __name__=='__main__':
# 創建 PyMiniRacer 實例
ctx=MiniRacer()
js_code="""
function add(a, b) {
return a + b;
}
"""
# 在 JavaScript 環境中執行代碼并傳遞參數
ctx.eval(js_code)
result=ctx.call("add", 3, 5)
# 輸出執行結果
print("JavaScript 執行結果:", result) # JavaScript 執行結果: 8
Python 中執行和調用 JavaScript 代碼有多種方法:
每種工具都有其適用的場景和局限性,選擇合適的工具取決于具體的需求和項目要求。
原文鏈接:https://juejin.cn/post/7367701663169790002
*請認真填寫需求信息,我們會在24小時內與您取得聯系。