首页 > 解决方案 > 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())

标签: python

解决方案


可能是这样的?现在它只是在发出请求时打印产品,但将它们写入 csv 文件应该很容易。get_products是一个生成器,可将给定 URL 中的所有产品作为字典生成。它被称为get_products而不是get_product因为给定的 URL 可能有多个产品。

get_all_productsget_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())

推荐阅读