【发布时间】:2017-12-21 16:13:18
【问题描述】:
我已经编写了下面的代码来抓取 cargurus 网站。搜索显示每页 15 个条目。
我想迭代地从第 1 页移动到第 n 页并抓取每一页。下面的代码应该做到这一点,但是在脚本的末尾我有一个数据帧 df ,它复制了第一页 numPages 次。
我认为代码没有给计算机时间来接收请求,所以我添加了一个 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)
【问题讨论】:
-
使用
print()显示页面中的 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
-
就我而言,它使用 javascript 替换数据 - 如果您使用不同的 url,您将获得相同的数据,因为
requests+beautifulsoup无法运行JavaScript。您可能必须使用Selenium来控制将读取页面并运行 javaScript 的 Web 浏览器。 -
在 Chrome/Firefox 的 DevTool 中,我看到它使用 url
https://www.cargurus.com/Cars/inventorylisting/ajaxFetchSubsetInventoryListing.action?sourceContext=forSaleTab_false_0来获取一些数据。也许阅读这个页面(使用不同的参数)你可以得到所有你需要的 JSON,你可以使用模块json轻松转换 ot python 字典 -
我想我正在阅读同一页。这就是这个问题的重点。为什么请求不抓取下一页 html 代码?我确实打印了网址。它在代码中。 URL 会随着循环的每次迭代而变化。这是输出(缩短)。对于第一个 3 进行说明。 https:///www.cargurus.com/Cars/i... =true#resultsPage=1 https:///www.cargurus.com/Cars/i... =true#resultsPage=2
标签: python web-scraping beautifulsoup python-requests