python - 美丽的汤 find_all() 不返回所有元素
问题描述
我正在尝试使用 bs4抓取该网站。在特定的汽车广告图块上使用检查,我想出了我需要刮什么才能获得标题和汽车页面的链接。
我正在使用 bs4 库的 find_all() 函数,但问题是它没有抓取所有汽车的所需信息。它只返回大约 21 辆的信息,而在网站上可以清楚地看到大约有 2410 辆汽车。
相关代码:
from bs4 import BeautifulSoup as bs
from urllib.request import Request, urlopen
import re
import requests
url = 'https://www.cardekho.com/used-cars+in+bangalore'
req = Request(url , headers={'User-Agent': 'Mozilla/5.0'})
webpage = urlopen(req).read()
page_soup = bs(webpage,"html.parser")
tags = page_soup.find_all("div","title")
print(len(tags))
如何获取页面上所有汽车的信息。
PS - 只想指出一件事,所有的汽车都不是一次显示的。向下滚动时会加载更多汽车信息。会不会是因为这个?没有把握。
解决方案
好的,我已经编写了一个示例代码来向您展示它是如何完成的。虽然该站点有一个我们可以利用的方便的 api,但第一页不能通过 api 获得,而是嵌入在代码中的script
标签中html
。这需要额外的处理来提取。之后,只需从 api 获取 json 数据,将其解析为 python 字典并将汽车条目附加到列表中。在滚动站点时检查 Chrome 或 Firefox 中的网络活动时,可以找到指向 api 的链接。
from bs4 import BeautifulSoup
import re
import json
from subprocess import check_output
import requests
import time
from tqdm import tqdm #tqdm is just to implement a progress bar, https://pypi.org/project/tqdm/
cars = [] #create empty list to which we will append the car dicts from the json data
url = 'https://www.cardekho.com/used-cars+in+bangalore'
r = requests.get(url , headers={'User-Agent': 'Mozilla/5.0'})
soup = BeautifulSoup(r.content.decode('utf-8'),"html.parser")
s = soup.find('script', {"type":"application/ld+json"}).next_sibling #find the section with the json data. It looks for a script tage with application/ld+json type, and takes the next tag, which is the one with the data we need, see page source code
js = 'window = {};\n'+s.text.strip()+';\nprocess.stdout.write(JSON.stringify(window.__INITIAL_STATE__));' #strip the text from unnecessary strings and load the json as python dict, taken from: https://stackoverflow.com/questions/54991571/extract-json-from-html-script-tag-with-beautifulsoup-in-python/54992015#54992015
with open('temp.js','w') as f: # save the sting to a javascript file
f.write(js)
data_site = json.loads(check_output(['node','temp.js'])) #execute the file with node, which will return the json data that will be loaded with json.loads.
for i in data_site['items']: #iterate over the dict and append all cars to the empty list 'cars'
cars.append(i)
for page in tqdm(range(20, data_site['total_count'], 20)): #'pagefrom' in the api call is 20, 40, 60, etc. so create a range and loop it
r = requests.get(f"https://www.cardekho.com/api/v1/usedcar/search?&cityId=105&connectoid=&lang_code=en®ionId=0&searchstring=used-cars%2Bin%2Bbangalore&pagefrom={page}&sortby=updated_date&sortorder=asc&mink=0&maxk=200000&dealer_id=®CityNames=®StateNames=", headers={'User-Agent': 'Mozilla/5.0'})
data = r.json()
for i in data['data']['cars']: #iterate over the dict and append all cars to the empty list 'cars'
cars.append(i)
time.sleep(5) #wait a few seconds to avoid overloading the site
这将导致cars
成为字典列表。车名可以在vid
钥匙中找到,并且 url 存在于vlink
钥匙中。您可以将其加载到 pandas 数据框中以探索数据:
import pandas as pd
df = pd.DataFrame(cars)
df.head()
将输出(为了便于阅读,我省略了图像列):
位置 | 我的耳朵 | BT | 英尺 | 公里 | 它 | 圆周率 | PN | 普 | dvn | 我知道了 | 尿酸 | 席位 | ip | OEM | 模型 | 视频 | 城市 | 链接 | p_numeric | webp_image | 位置 | 页号 | 中心变量 ID | isExpiredModel | 型号ID | 是正版 | is_ftc | 卖家位置 | utype | 意见 | tmGaadiStore | 分类 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 科拉曼加拉 | 2014 | 越野车 | 柴油机 | 30,000 | 0 | https://images10.gaadicdn.com/usedcar_image/320x240/used_car_2206305_1614944913.jpg | 99 万 | 马恒达 XUV500 W6 2WD | 13 | 3019084 | 9509A09F1673FE2566DF59EC54AAC05B | 1 | 马恒达 | 马恒达 XUV500 | 马恒达 XUV500 2011-2015 W6 2WD | 班加罗尔 | /二手车详细信息/二手马恒达-XUV500-2011-2015-W6-2WD-cars-Bangalore_9509A09F1673FE2566DF59EC54AAC05B.htm | 990000 | https://images10.gaadicdn.com/usedcar_image/320x240webp/2021/used_car_2206305_1614944913.webp | 1 | 1 | 3822 | 真的 | 570 | 0 | 0 | {'address': 'BDA Complex, 100 Feet Rd, 3rd Block, Koramangala 3 Block, Koramangala, Bengaluru, Karnataka 560034, Bangalore', 'lat': 12.931, 'lng': 77.6228} | 经销商 | 235 | 错误的 | ||
1 | 马拉哈利殖民地 | 2017 | 越野车 | 汽油 | 30,000 | 0 | https://images10.gaadicdn.com/usedcar_image/320x240/used_car_2203506_1614754307.jpeg | 78.5 万 | 福特 Ecosport 1.5 汽油趋势 BSIV | 14 | 3015331 | 2C0E4C4E543D4792C1C3186B361F718B | 1 | 福特 | 福特生态运动 | 福特 Ecosport 2015-2021 1.5 汽油趋势 BSIV | 班加罗尔 | /二手车详细信息/二手福特-Ecosport-2015-2021-1.5-Petrol-Trend-BSIV-cars-Bangalore_2C0E4C4E543D4792C1C3186B361F718B.htm | 785000 | https://images10.gaadicdn.com/usedcar_image/320x240webp/2021/used_car_2203506_1614754307.webp | 2 | 1 | 6086 | 真的 | 175 | 0 | 0 | {'address': '2, Varthur Rd, Ayyappa Layout, Chandra Layout, Marathahalli, Bengaluru, Karnataka 560037, Marathahalli Colony, Bangalore', 'lat': 12.956727624875453, 'lng': 77.70174980163576} | 经销商 | 495 | 错误的 | ||
2 | 叶拉汉卡 | 2020 | 越野车 | 柴油机 | 13,969 | 0 | https://images10.gaadicdn.com/usedcar_image/320x240/usedcar_11_276591614316705_1614316747.jpg | 410万 | 丰田Fortuner 2.8 4WD AT | 12 | 3007934 | BBC13FB62DF6840097AA62DDEA05BB04 | 1 | 丰田 | 丰田财富 | 丰田 Fortuner 2016-2021 2.8 4WD AT | 班加罗尔 | /二手车详细信息/二手丰田-Fortuner-2016-2021-2.8-4WD-AT-cars-Bangalore_BBC13FB62DF6840097AA62DDEA05BB04.htm | 4100000 | https://images10.gaadicdn.com/usedcar_image/320x240webp/2021/usedcar_11_276591614316705_1614316747.webp | 3 | 1 | 7618 | 真的 | 364 | 0 | 0 | {'address': 'Sonnappanahalli Kempegowda Intl Airport Road Jala Uttarahalli Hobli, Yelahanka, Bangalore, Karnataka 560064', 'lat': 13.1518821, 'lng': 77.6220694} | 经销商 | 516 | 错误的 | ||
3 | 比亚塔拉亚纳普拉 | 2017 | 轿车 | 柴油机 | 18,000 | 0 | https://images10.gaadicdn.com/usedcar_image/320x240/used_car_2202297_1615013237.jpg | 350万 | 梅赛德斯-奔驰 E 级 E250 CDI 前卫 | 15 | 3013606 | 4553943A967049D873712AFFA5F65A56 | 1 | 奔驰 | 奔驰E级 | 梅赛德斯-奔驰 E 级 2009-2012 E250 CDI 前卫 | 班加罗尔 | /二手车详细信息/二手梅赛德斯-奔驰-E-Class-2009-2012-E250-CDI-Avantgarde-cars-Bangalore_4553943A967049D873712AFFA5F65A56.htm | 350万 | https://images10.gaadicdn.com/usedcar_image/320x240webp/2021/used_car_2202297_1615013237.webp | 4 | 1 | 4611 | 真的 | 674 | 0 | 0 | {'address': 'NO 19, Near Traffic Signal, Byatanarayanapura, International Airport Road, Byatarayanapura, Bangalore, Karnataka 560085', 'lat': 13.0669588, 'lng': 77.5928756} | 经销商 | 414 | 错误的 | ||
4 | 楠 | 2015 | 轿车 | 柴油机 | 80,000 | 0 | https://stimg.cardekho.com/pwa/img/noimage.svg | 125 万 | 斯柯达明锐 Elegance 2.0 TDI AT | 1 | 3002709 | 156E5F2317C0A3A3BF8C03FFC35D404C | 1 | 斯柯达 | 斯柯达明锐 | 斯柯达明锐 2013-2017 Elegance 2.0 TDI AT | 班加罗尔 | /二手车详细信息/二手Skoda-Octavia-2013-2017-Elegance-2.0-TDI-AT-cars-Bangalore_156E5F2317C0A3A3BF8C03FFC35D404C.htm | 1250000 | 5 | 1 | 3092 | 真的 | 947 | 0 | 0 | {'lat':0,'lng':0} | 个人 | 332 | 错误的 |
或者,如果您希望将 dict 分解seller_location
为列,则可以使用df = pd.json_normalize(cars)
.
您可以将所有数据保存到csv
文件中:df.to_csv('output.csv')
推荐阅读
- javascript - Leaflet and Ordance Survey Open Data:在网页上映射
- python - 使用多个依赖文件将 .py 转换为 .exe
- react-native - 反应本机导航-无法在额外属性扩展上获取属性“RNNKotlinVersion”,因为它不存在
- python - Python - 开始写入文本文件的第二行
- powershell - 我可以单独获取 AD 帐户属性,但不能在 foreach 循环中获取?
- android - 无法在 kotlin 中创建视图模型类的实例
- angular - Typescript 上的 Drawflow 库
- html - Bootstrap-vue b-table 响应属性无法识别 lg 或 xl 值
- java - Run SonarScanner analysis with Java 11, run target code with Java 8
- wordpress - WordPress taxonomy in CPT URL