使用循环进行 Web 抓取并写入 csv

Posted

技术标签:

【中文标题】使用循环进行 Web 抓取并写入 csv【英文标题】:Webscraping with loop and writing to csv 【发布时间】:2020-09-22 20:32:30 【问题描述】:

我正在尝试从网站上的多个 URL 中抓取非结构化数据。我使用 BeautifulSoup 成功提取了我需要的块。然后,为了帮助构建数据集,我将值添加到列表中,然后再将它们写入 csv 文件。

但是,当尝试传输数据时,只会传输列表中的最后一个值。我认为这是因为每次调用循环时列表都会获取新值。如何不断向文件中添加新值,以便我的 csv 文件具有来自每个循环的值?谢谢。

for i in range(1, 3):
    url = "https://website.com/webid=".format(i)
    s = session.get(url, headers=headers, cookies=cookies)
    soup = bs(s.text, 'html.parser')
    data = soup.find_all('td') 
    t = soup.find_all('td')
    a = t[0]
    b = t[1]
    c = t[2]
    info = [a, b, c]
    print(info)

df = pd.DataFrame(info)
df.to_csv('a.csv', index=False, header=False)

针对 cme​​ts 和其他答案:

如果我的原始代码块不清楚,我深表歉意,我试图生成最少的必要代码来解释我的情况。幸运的是,@Matt_F 能够理解并引导我朝着正确的方向前进。对于那些想要更明确地解释我正在运行的代码的人,请参阅下面的完整代码块(不包括导入、cookie、标头和有效负载)。

session = requests.Session()
s = session.post("https://WEBSITE.com/register?view=login&return=aW5kZXgucGhwP0l0ZW1pZD02NjM", data=payload, headers=headers, cookies=cookies)

for i in range(0,9999):
    print(i)
    # establish connection
    url = "https://WEBSITE.com/WEB-SITE/data-list?vw=detail&id=&return=1".format(i)
    s = session.get(url, headers=headers, cookies=cookies)
    # set timer for delay
    t = time.time()
    delay = time.time() - t
    time.sleep(10*delay)
    # begin to pull data
    soup = bs(s.text, 'html.parser')
    if "Error: no data found" in s.text:
        print('skipped')
    else:
        soup.prettify()
        # print(soup)
        d = soup.find_all('td',"valign": "top")
        d_info = d[0:-1] 
        print(d_info)
        df1 = pd.DataFrame(d_info)
        df1t = df1.T
    
        # p = soup.find_all('p')
        # p_info = p[0:-1]
        # df2 = pd.DataFrame(p_info)
        # df2t = df2.T
    
        # result = pd.concat([df1t, df2t], axis=1, sort=False)
        df1t.to_csv('file.csv', mode='a', index=False, header=False)  

【问题讨论】:

你在哪里声明info 你好,亲爱的 Bjørn_Jung - 非常感谢这个很好的例子;我目前正在研究 python、csv 和 pandas 的所有内容。我喜欢你的例子。您能否提供一个 URL,我们可以运行这个出色且清晰的演示代码。那太棒了。期待您的来信。问候;) 【参考方案1】:

我相信您的问题是您在默认模式下以写入模式打开 csv 文件。您应该使用“a”属性以“附加”模式打开它。

df.to_csv('a.csv', mode='a', index=False, header=False)

see this thread

【讨论】:

非常感谢亲爱的马特提供了您的精彩回答 - 这非常有帮助。很高兴看到这个帖子!【参考方案2】:

附注 - 代码如下:

a = t[0]
b = t[1]
c = t[2]
d = t[3]
e = t[4]

像这样的代码对于我作为一个 python 初学者来说是相当困难的。

我对设计深思熟虑:我们不应该使用数据结构来表示您的数据。 您将列表中的元素分配给名称,然后从中创建一个新列表。

所以我猜你的数据是二维的。 第一个维度是索引(行)和 第二个维度是列(td-data)。

我了解到我们必须创建一个空列表,它稍后会成为您的整个数据集。 对于每个标签,您都需要文本或属性。将整个标签对象放入 pandas 是行不通的。

td_results = []
for i in range(1, 100):
    url = "https://my-website.com/webid=".format(i)
    s = session.get(url, headers=headers, cookies=cookies)
 
    soup = bs(s.text, 'html.parser')
    data = soup.find_all('td') 
    td_results.append(column.text for column in soup.find_all('td')) # <- this here is the critical part
    # he could find something or not
    # and the amount of td elements can be different


print(td_results)
df = pdDataFrame(td_results)

因此,如果您知道所有页面确实具有相同的结构,并且您知道例如您需要前 10 个元素,那么您可以使用订阅方法。

获取前 10 个元素的示例:

td_results.append(column.text for column in soup.find_all('td')[:10])

你怎么看这些沉思!?期待您的来信

【讨论】:

以上是关于使用循环进行 Web 抓取并写入 csv的主要内容,如果未能解决你的问题,请参考以下文章

使用 python 和 Beautifulsoup4 从抓取数据中写入和保存 CSV 文件

在 Python CSV Writer 循环中写入标题一次

如何通过网络抓取将表格数据从网站写入 CSV

如何在同一循环中“从 .csv 读取并写入 excel”

抓取的网站数据未写入 CSV

网页抓取 - Python;写入 CSV