python - BeautifulSoup 抓取位于 csv 中的 URL,然后输出到新的 csv
问题描述
希望你在这个电晕期间保持安全。
我对python很陌生。
我正在尝试抓取一个销售汽车轮胎的网站。我正在尝试获取“urls.csv”中每个 URL 中所有轮胎的“品牌”、“型号”、“价格”,然后将其导出到另一个 csv。如果有帮助,这是我的 urls.csv 中的 URL 的粘贴箱。
我在这里搜索过类似的问题,包括这个。然而,即便如此,他们还是将 URL 粘贴到代码中并运行它。我想要有干净的代码来查看我的 csv 并获取第一个 URL,抓取它,将结果放入输出 csv,然后返回到 csv 并获取第二个 URL,抓取它,把它放在第二行输出.csv。
当我手动将 URL 放入代码中时,我设法制作了一个可以抓取单个 URL 的刮刀。(这对我来说很重要哈哈)。我当前的代码:
import requests
from requests import get
from bs4 import BeautifulSoup
import pandas as pd
#I want to be able to swap this request for every URL in the csv
page = requests.get('https://www.beaurepaires.com.au/tyresize/155W_70R_13')
soup = BeautifulSoup(page.content, 'html.parser')
tyres = soup.find(class_='comp-product-details products-grid')
items = tyres.find_all(class_='item')
brand = [str(item.find(class_='dealer-logo')).split(' ')[1].split('=')[1].split('"')[1] for item in items]
model = [item.find(class_='product-title').get_text() for item in items]
price = [item.find(class_='main-price').get_text().split('/')[0].split(' ')[1] for item in items]
tyre_stuff = pd.DataFrame({
'brand':brand,
'model':model,
'price':price,
})
print(tyre_stuff)
tyre_stuff.to_csv('beaurepaires_01.csv', mode='a', header=False)
有人可以指出我正确的方向吗?我想我必须导入 csv,而且我觉得我将无法使用 '.to_csv' 命令。我也觉得我可能不得不使用 urllib 或类似的东西。
EDIT1:这是我的 csv 格式的 URL
https://www.beaurepaires.com.au/tyresize/145W_65R_15
https://www.beaurepaires.com.au/tyresize/155W_65R_13
https://www.beaurepaires.com.au/tyresize/155W_65R_14
https://www.beaurepaires.com.au/tyresize/155W_70R_13
EDIT2:这是我根据 Paul 的帮助更新的代码,但我仍然坚持如何让 csv.DictWriter 工作以输出我的结果
def get_products(url):
import requests
from bs4 import BeautifulSoup
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, "html.parser")
for item in soup.findAll("div", {"class": "product-item show-online-price"}):
title = item["title"]
brand = item.find("img", {"class": "dealer-logo"})["alt"]
price = item.find("span", {"class": "price"}).getText()
yield {
"title": title,
"brand": brand,
"price": price
}
def get_all_products(filename):
import csv
with open(filename, "r", newline="") as file:
for tokens in csv.reader(file):
url = tokens[0]
for product in get_products(url):
yield product
def main():
from time import sleep
from random import randint
import csv
sleep(randint(3,11))
with open('output.csv', 'w', newline='') as csvfile:
fieldnames = ['title', 'brand','price']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
for product in get_all_products("urls.csv"):
writer.writeheader()
writer.writerow({'title', 'brand', 'price'})
print(product)
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
解决方案
可能是这样的?现在它只是在发出请求时打印产品,但将它们写入 csv 文件应该很容易。get_products
是一个生成器,可将给定 URL 中的所有产品作为字典生成。它被称为get_products
而不是get_product
因为给定的 URL 可能有多个产品。
get_all_products
get_products
是另一个生成器,它为给定 csv 文件名中的每个 URL生成每个产品。
正如其他人所提到的,您没有任何理由将 URL 保存在 csv 文件中,因为您没有逗号分隔的值或由任何类型的分隔符分隔的值。您只有一堆 URL,为什么不将它们存储在纯文本文件中呢?它甚至会减少几行代码。
def get_products(url):
import requests
from bs4 import BeautifulSoup
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, "html.parser")
for item in soup.findAll("div", {"class": "product-item show-online-price"}):
title = item["title"]
price = item.find("span", {"class": "price"}).getText()
logo = item.find("img", {"class": "dealer-logo"})["src"]
yield {
"title": title,
"price": price,
"logo": logo
}
def get_all_products(filename):
with open(filename, "r", newline="") as file:
for url in file.readlines():
for product in get_products(url.strip()):
yield product
def main():
from csv import DictWriter
with open("products.csv", "w", newline="") as file:
field_names = ["title", "price", "logo"]
writer = DictWriter(file, fieldnames=field_names)
writer.writeheader()
for product in get_all_products("urls.txt"):
writer.writerow(product)
file.flush()
print(product)
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
推荐阅读
- sql - 从 MS Access 转换到 SQL Server 时转换多个 IIf
- javascript - React/Gatsby 组件与 MDX 文件中的组件交互(提升状态)
- javascript - 在 Angular 组件和非 Angular 组件之间进行通信:从来自回调的可观察对象返回数据
- html - 在 VScode 中按 Enter 选择建议
- python - 用于排列的递归生成器
- c++ - 使用 lamdas 引用传递的稳定排序自定义比较器会产生编译错误
- c++ - std::string_view 如何从 std::string 构造?
- java - Apache Artemis - 记录 AMQ212037 连接失败和对等点重置连接 [code=GENERIC_EXCEPTION]
- ffmpeg - 如何从mov文件中提取ffmpeg中的音频
- amazon-web-services - 从 EMR 覆盖到 S3 存储桶需要很长时间