新人的第二篇文章,寫的不好請見諒
這段代碼隻是針對京東的商品資訊爬取,很多都是根據頁面源碼去比對擷取資料的,别的網站用不了,也可能過一段時間官方修改了頁面就不能用了,不過這裡也隻是提供學習使用,希望可以幫到初學者
這裡附上兩個我學習時用的文章
使用的是requests+BeautifulSoup請求以及解析網頁(本文章所使用的技術)
這個是使用的webdriver,和本文不一樣,有需要的可以看一下
'''
爬取的是京東的8424西瓜的商品資訊
要爬取企業資訊需要驗證碼,要一個一個輸入
若不爬取企業資訊則可以實作自動爬取想要的頁數,請做如下改動
注釋掉97行115行124行132行 打開125行(加了幾行注釋可能行數就變了,不過下面相應的行也會标出注釋)
'''
import re
import xlwt
import time
import requests
from PIL import Image
from bs4 import BeautifulSoup
#from lxml import etree
item_value = []
count = 1
browser = requests.session()
requestVerifyCodeUrl = "https://mall.jd.com/sys/vc/createVerifyCode.html"
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
def parserUrl(url, params={}):
#解析URL(要多次請求是以就單獨列出來一個方法)
global headers
req = requests.get(url, headers=headers, params=params)#headers一定要有,模拟浏覽器請求,params是參數
#time.sleep(1) #貌似不需要1s就可以一直請求京東,淘寶好像就會有驗證
soup = BeautifulSoup(req.text, "lxml")
return soup
def enterprisePage(url):
#處理企業詳情頁面相關資料
while True:
global headers
global requestVerifyCodeUrl
#這裡不可以用requests.get請求了,因為cookie的緣故,這個是我找到的最簡單的解決辦法了browser = requests.session()就可以自動儲存cookie了
req = browser.get(requestVerifyCodeUrl, headers=headers)
#儲存驗證碼圖檔
f = open("VerifyCodeImage.jpg", 'wb')
f.write(req.content)
f.close()
f1 = open("VerifyCodeImage.jpg", 'rb')
image = Image.open(f1)
image.show()
f1.close()
#手動輸入
vc = input('請輸入驗證碼:')#深度學習識别會在後續的文章中給出
datas = {'verifyCode' : vc}
#這裡使用browser.post就會和上面請求驗證碼的cookie一緻了
req2 = browser.post(url, data=datas, headers=headers)
soup = BeautifulSoup(req2.text, "lxml")
#判斷若是有form的代碼塊則證明沒有驗證成功,這個就要去網頁源碼中觀察倆個頁面的差異了
if soup.find('form'):
print('驗證碼輸入錯誤!請重新輸入!')
continue
infoList = soup.find_all('li', attrs={'class':'noBorder'})#擷取企業相關資訊代碼段
for info in infoList:
if info.find('label', attrs={'class':'jLabel'}):
if info.find('label', attrs={'class':'jLabel'}).text == "企業名稱: ":
item_value.append(info.find('span').text)#企業名稱
if info.find('label', attrs={'class':'jLabel'}).text == "公司位址:":
item_value.append(info.find('span').text)#企業位址
return
def itemPage(url):
#處理商品詳情頁面相關資料
#淨含量是在清單頁面沒有的是以要進到詳情頁面擷取
soup = parserUrl(url)
clearfixList = soup.find_all('dl', attrs={'class':'clearfix'})#擷取重量相關代碼段
for clearfix in clearfixList:
if clearfix.find('dt').text == "淨含量":
weight = re.sub("[a-zA-Z]", "", clearfix.find('dd').text)
return weight
return None
def storePage(url):
#處理店鋪詳情頁面相關資料
#嚴格來說并沒有進到店鋪頁面,這個頁面沒有什麼要擷取的,但是要從這裡擷取企業頁面于是就中間加了這麼一個函數
storID = re.sub("[^0-9]", "", url)
enterpriseUrl = 'https://mall.jd.com/showLicence-' + str(storID) + '.html'
#本來企業url是在店鋪頁面中爬取的,但是是動态加載的,源碼中是沒有的,但是經過觀察發現這這兩個頁面的url一部分是固定的,
#隻是更改了店鋪的id,這樣我們就可以拼接出企業url了(曲線救國)
enterprisePage(enterpriseUrl)
def mainPage(sheet, n):
#處理搜尋頁面相關資料
url = "https://search.jd.com/search?"
#隻要參數這樣設定隻改變n就可以爬取想要的頁數的資料了,不用考慮翻頁和下拉滾動條
params = {"keyword":"8424西瓜", 'page':str(n), 'scrolling':'y'}
soup = parserUrl(url, params)
#下面的相關資訊的擷取都是要求網頁源碼中對應的字段去比對,并不是所有網站通用的
item_list = soup.find_all("li", attrs={"class":"gl-item"})
for item in item_list:
p_name = item.find('div', attrs={"class":"p-name p-name-type-2"})#擷取商品相關代碼段
itemName = p_name.find('em').text
itemUrl = 'https:' + p_name.find('a')['href']
p_price = item.find('div', attrs={"class":"p-price"})#擷取價格相關代碼段
itemPrice = p_price.find('i').text
p_shop = item.find('div', attrs={"class":"p-shop"})#擷取店鋪相關代碼段
storeName = p_shop.find('a').text
storeUrl = 'https:' + p_shop.find('a')['href']
item_value.clear()
item_value.append(storeName)#店鋪名字
item_value.append(storeUrl)#店鋪URL
item_value.append(itemName)#商品名字
item_value.append(itemUrl)#商品URl
storePage(storeUrl)#在店鋪頁面處理資料 不輸入驗證碼注釋掉這一行
item_value.append(itemPrice)#商品價格
itemWeight = itemPage(itemUrl)#在商品頁面處理資料
if itemWeight:
item_value.append(itemWeight)#商品重量
else :
item_value.append(0)
if itemWeight:
itemUnitPrice = float(itemPrice) / float(itemWeight) / 2
item_value.append('%.2f' %itemUnitPrice)#商品單價
else :
item_value.append(0)
#寫入excel表
global count
for i in range(0, len(item_value)):
sheet.write(count, i, item_value[i])
count += 1
if count == 4: return#不輸入驗證碼注釋掉這一行,數字減一是爬取商品的數目
if n%2 == 0:
print("******已完成第" + str(n/2) +"頁商品資訊寫入******")
def main():
n = input("請輸入要爬取的頁數:")
n = int(n) * 2
print("**************正在寫入**************")
print("請稍候...")
value_title = ['店鋪名稱','店鋪URL','商品名稱','商品URL','企業名稱','企業位址','價格(元)','重量(kg)','單價(元/500g)']#不輸入驗證碼注釋掉這一行并且打開下一行
#value_title = ['店鋪名稱','店鋪URL','商品名稱','商品URL','價格(元)','重量(kg)','單價(元/500g)']
workbook = xlwt.Workbook()
sheet = workbook.add_sheet('8424西瓜')
for i in range(0, len(value_title)):
sheet.write(0, i, value_title[i])#寫入表頭
'''
這裡要說明一下京東的搜尋頁面最開始是隻加載一半的,當下拉滾動條會加載剩下的一半,又發現url中的參數page=1當點選下一頁page=3,
會這樣每次+2,通過下拉滾動條加載後半頁抓包可見頁面是發送了一個請求的,這個請求的網址的page參數是2,4,6雙數的,
不難發現隻要n++就可以一個不漏的爬取所有資訊了,不需要什麼模拟下拉滾動條和翻頁,是以要爬取1頁page=1-2,爬取2頁page=1-4,爬取3頁page=1-6,
不要習慣的從0開始哈
'''
for i in range(1, n+1):
mainPage(sheet, i)
break#不輸入驗證碼注釋掉這一行
workbook.save('京東商品資料.xls')
print("**************寫入完成**************")
if __name__ == '__main__':
main()
源檔案這裡可以下載下傳,不過也就是一份.py的檔案,就是上面的代碼沒加注釋版。
前人栽樹後人乘涼,乘涼之後也要記得栽樹哦。