2017-12-21 1 views
0

나는 아래의 코드를 작성하여 cargurus 웹 사이트를 긁었다. 검색은 페이지 당 15 개의 항목을 보여줍니다.웹 스크 레이 핑을 할 때 페이지를 넘기는 방법

페이지 1에서 n으로 반복적으로 이동하여 각 페이지를 긁어 내고 싶습니다. 아래 코드는 그렇게하기로되어 있지만, 스크립트의 끝에서 첫 번째 페이지 numPages 시간을 복제하는 데이터 프레임 df가 있습니다.

나는 time.sleep (1) 라인을 추가했지만 코드가 컴퓨터에 요청을 수신 할 시간이 없다고 생각했지만 작동하지 않는 것 같습니다.

내가 뭘 잘못하고 있니?

# Import Modules 
from bs4 import BeautifulSoup as bs 
import requests 
import pandas as pd 
import seaborn as sns 
import time 

#Utility Functions 
def to_number(s): 
    #Convert to Number 
    numval = int(s.replace(',','')) 
    return numval 

def get_location(s): 
    #Convert to City, State (SS), and zip (string) 
    s = s.replace(',','') 
    sList = s.split() 
    n = len(sList)-1 
    City = '' 
    for word in sList[0:n-1]: 
     City += word + ' ' 
    City = City[:-1] 
    State = sList[n-1] 
    Zip = sList[n] 
    return City, State, Zip 

def get_YearMakeModelTrim(s): 
    #Convert to Year, Make, Model, Trim 
    sList = s.split() 
    n = len(sList)-1 
    Year = sList[0] 
    Make = sList[1] 
    Model = sList[2] 
    if n == 3: 
     Trim = sList[3] 
    else: 
     Trim = "None" 
    return Year, Make, Model, Trim 

numPages = 10 

baseURL = 'https://www.cargurus.com/Cars/inventorylisting/viewDetailsFilterViewInventoryListing.action?sourceContext=forSaleTab_false_0&newSearchFromOverviewPage=true&inventorySearchWidgetType=AUTO&entitySelectingHelper.selectedEntity=c24578&entitySelectingHelper.selectedEntity2=c25202&zip=03062&distance=50000&searchChanged=true&modelChanged=false&filtersModified=true#resultsPage={}' 


data = [] 
for ii in range(numPages): 
    URL = baseURL.format(ii+1) 
    print(URL) 

    r = requests.get(URL).text 
    time.sleep(1) 
    soup = bs(r,'html.parser') 

    stats = soup.find_all("div", attrs = {"class": "cg-dealFinder-result-stats"}) 
    deals = soup.find_all("div", attrs = {"class": "cg-dealFinder-result-deal"}) 
    titles = soup.find_all("h4", {"class":"cg-dealFinder-result-model"}) 

    for title, deal, stat in zip(titles,deals,stats): 
     row = {} 
     row["Price"] = to_number(stat.find('span').get_text()[1:]) 
     row["Mileage"] = to_number(stat.find_all("p")[1].text[9:]) 
     row["City"], row["State"], row["Zip"] = get_location(stat.find_all("p")[2].text[10:]) 
     row["natAvgPrice"] = to_number(deal.find('span', attrs = {'class': 'nationalAvg'}).get_text()[17:]) 
     row["Year"], row["Make"], row["Model"], row["Trim"] = get_YearMakeModelTrim(title.find('span', attrs = {'itemprop': 'name'}).get_text()) 
     row["NewUsed"] = title.find('span', attrs = {'class': 'invisibleLayer'}).get_text()[:-5] 
     data.append(row) 

df = pd.DataFrame(data) 
#df = df.drop_duplicates() 

sns.pairplot(x_vars=["Mileage"], y_vars=["Price"], data=df, hue="Trim", size=5) 
+0

사용'인쇄()'만 처음 10 개 항목을 표시 페이지에서 - 항상 같은 페이지를 읽을 수 있습니다. – furas

+0

나는 같은 페이지를 읽고 있다고 생각한다. 그것이이 질문의 핵심입니다. 왜 이제 다음 페이지로 이동합니까? 나는 URL을 출력했다. 그것은 코드에 있습니다. 루프 반복마다 URL이 변경됩니다. 다음은 결과입니다 (줄임). 그림의 첫 번째 3. https : /// www.cargurus.com/Cars/i ... = true # resultsPage = 1 https : /// www.cargurus.com/Cars/i ... = true # resultsPage = 2 https : /// www.cargurus.com/Cars/i ... = true # resultsPage = 3 – DeeeeRoy

+0

나를 위해 javascript를 사용하여 데이터 이벤트를 대체합니다. 다른 URL을 사용하면 동일한 데이터를 얻을 수 있습니다. 왜냐하면'requests' +'' beautifulsoup'는'JavaScript'를 실행할 수 없습니다. 'Selenium'을 사용하여 페이지를 읽고 javaScript를 실행할 웹 브라우저를 제어해야 할 수도 있습니다. – furas

답변

1

이 페이지 그것은 매개 변수를 사용 POST 요청 URL

https://www.cargurus.com/Cars/inventorylisting/ajaxFetchSubs etInventoryListing.a ction? = sourceContext forSaleTab_false_0

로부터 데이터를 판독하는 자바 스크립트/AJAX를 사용 파라미터가 page.

from bs4 import BeautifulSoup 
import requests 

params = { 
    'zip': '03062', 
    'address': 'Nashua,+NH', 
    'latitude': "42.73040008544922", 
    'longitude': '-71.49479675292969', 
    'distance': 50000, 
    'selectedEntity': 'c24578', 
    'entitySelectingHelper.selectedEntity2': 'c25202', 
    'minPrice': '', 
    'maxPrice': '', 
    'minMileage': '', 
    'maxMileage': '', 
    'transmission': 'ANY', 
    'bodyTypeGroup': '',  
    'serviceProvider': '', 
    'page': 1, 
    'filterBySourcesString': '', 
    'filterFeaturedBySourcesString': '', 
    'displayFeaturedListings': True, 
    'searchSeoPageType': '',  
    'inventorySearchWidgetType': 'AUTO', 
    'allYearsForTrimName': False, 
    'daysOnMarketMin': '', 
    'daysOnMarketMax': '', 
    'vehicleDamageCategoriesRaw': '', 
    'minCo2Emission': '', 
    'maxCo2Emission': '', 
    'vatOnly': False, 
    'minEngineDisplacement': '', 
    'maxEngineDisplacement': '', 
    'minMpg': '', 
    'maxMpg': '', 
    'startYear': 2015, 
    'endYear': 2016, 
    'isRecentSearchView': False, 
} 

url = 'https://www.cargurus.com/Cars/inventorylisting/ajaxFetchSubsetInventoryListing.action?sourceContext=forSaleTab_false_0' 

display_keys = True 

for x in range(1, 4): 

    params['page'] = x 

    response = requests.post(url, data=params) 

    data = response.json() 

    if display_keys: 
     display_keys = False 
     for key in data.keys(): 
      print('key:', key) 
     for key in data['listings'][0].keys(): 
      print("data['listings'] key:", key) 
     print('-----') 

    print('--- offers number:', len(data['listings']), '---') 
    for item in data['listings'][:10]: 
     print(item['id'], data['modelName'], item['modelName'], item['trimName']) 

결과 - 키

key: listings 
key: modelName 
key: styleSet 
key: modelId 
key: serviceProviders 
key: page 
key: sellers 
key: remainingResults 
data['listings'] key: bodyType 
data['listings'] key: fleet 
data['listings'] key: serviceProviderId 
data['listings'] key: saved 
data['listings'] key: highwayFuelEconomy 
data['listings'] key: modelId 
data['listings'] key: nonwholesaleSellerId 
data['listings'] key: isFranchiseDealer 
data['listings'] key: regressionPrice 
data['listings'] key: rating 
data['listings'] key: listedDate 
data['listings'] key: dealerRatingPriceAdjustment 
data['listings'] key: isOEMCPO 
data['listings'] key: sellerId 
data['listings'] key: transmission 
data['listings'] key: mainPictureUrl 
data['listings'] key: monthlyPayment 
data['listings'] key: price 
data['listings'] key: exteriorColorName 
data['listings'] key: id 
data['listings'] key: isFeatured 
data['listings'] key: mileage 
data['listings'] key: makeId 
data['listings'] key: zip 
data['listings'] key: noPhotos 
data['listings'] key: isCertified 
data['listings'] key: msrpString 
data['listings'] key: engineCylinders 
data['listings'] key: expectedPriceString 
data['listings'] key: trimName 
data['listings'] key: daysOnMarket 
data['listings'] key: scaleMainPictureOnLoad 
data['listings'] key: vehicleDamageCategory 
data['listings'] key: monthlyPaymentString 
data['listings'] key: isOutlier 
data['listings'] key: cityFuelEconomy 
data['listings'] key: savingsAmount 
data['listings'] key: ownerCount 
data['listings'] key: absoluteRating 
data['listings'] key: salvage 
data['listings'] key: contacted 
data['listings'] key: priceString 
data['listings'] key: distance 
data['listings'] key: originalPrice 
data['listings'] key: sellerRating 
data['listings'] key: mileageString 
data['listings'] key: engineType 
data['listings'] key: wheelSystemDisplay 
data['listings'] key: isDisplayConquestSection 
data['listings'] key: serviceProviderName 
data['listings'] key: carYear 
data['listings'] key: savingsRecommendation 
data['listings'] key: specificOptionIds 
data['listings'] key: lemon 
data['listings'] key: vehicleIdentifier 
data['listings'] key: bodyTypeGroupId 
data['listings'] key: useAnonymousContactEmail 
data['listings'] key: msrp 
data['listings'] key: sellerCity 
data['listings'] key: bodyTypeGroupName 
data['listings'] key: savingsArrowImage 
data['listings'] key: dealScore 
data['listings'] key: frameDamaged 
data['listings'] key: hasAccidents 
data['listings'] key: isCPO 
data['listings'] key: expectedPrice 
data['listings'] key: engineDisplacement 
data['listings'] key: priceDifferentialString 
data['listings'] key: trimLevelName 
data['listings'] key: isNew 
data['listings'] key: modelName 
data['listings'] key: bodyTypeId 
data['listings'] key: theftTitle 
data['listings'] key: fuelType 
data['listings'] key: maxSeating 
data['listings'] key: wheelSystem 
data['listings'] key: isConquestEnabled 
data['listings'] key: autoEntityId 
data['listings'] key: franchiseMake 
data['listings'] key: optionIds 
data['listings'] key: makeName 
----- 

결과

- 난 URL과 데이터를 표시하기 위해 (다른 page와) 모든 요청

--- offers number: 2000 --- 
190057566 Honda Odyssey Odyssey Touring Elite 
194518873 Honda Odyssey Odyssey 
184211547 Honda Odyssey Odyssey Touring Elite 
185999601 Honda Odyssey Odyssey EX-L 
191225205 Honda Odyssey Odyssey EX-L 
192457272 Honda Odyssey Odyssey EX-L 
190727203 Honda Odyssey Odyssey EX-L 
189805101 Honda Odyssey Odyssey EX-L 
190017310 Honda Odyssey Odyssey EX-L 
185841600 Honda Odyssey Odyssey SE 
--- offers number: 1985 --- 
189574780 Honda Odyssey Odyssey EX-L 
185923444 Honda Odyssey Odyssey EX-L 
193088921 Honda Odyssey Odyssey Touring Elite 
191861106 Honda Odyssey Odyssey EX-L 
188361750 Honda Odyssey Odyssey Touring 
185077447 Honda Odyssey Odyssey EX-L 
182773821 Honda Odyssey Odyssey SE 
189573553 Honda Odyssey Odyssey EX 
191224649 Honda Odyssey Odyssey EX-L 
179786502 Honda Odyssey Odyssey EX 
--- offers number: 1970 --- 
192649298 Honda Odyssey Odyssey Touring Elite 
188612484 Honda Odyssey Odyssey EX-L 
182338399 Honda Odyssey Odyssey EX 
193159667 Honda Odyssey Odyssey EX-L 
188979870 Honda Odyssey Odyssey EX-L 
194311827 Honda Odyssey Odyssey EX 
181047736 Honda Odyssey Odyssey EX-L 
189115988 Honda Odyssey Odyssey EX-L 
183408178 Honda Odyssey Odyssey EX-L 
188950701 Honda Odyssey Odyssey EX-L