【问题标题】:Write multiple files inside for-loop在for循环中写入多个文件
【发布时间】:2021-07-06 02:17:13
【问题描述】:

我正在尝试抓取多个链接,提取在<p> HTML 标记上找到的文本并将输出写入不同的文件。每个链接都应该有自己的输出文件。到目前为止:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from urllib.request import Request, urlopen
from bs4 import BeautifulSoup
import re
import csv
import pyperclip
import pprint
import requests

urls = ['https://link1',
        'https://link2']
url_list = list(urls)

#scrape elements
for url in urls:
    response = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'})
    soup = BeautifulSoup(response.content, "html.parser")
    page = soup.find_all('p')
    page = soup.getText()
for line in urls:
    with open('filename{}.txt'.format(line), 'w', encoding="utf8") as outfile:
        outfile.write('\n'.join([i for i in page.split('\n') if len(i) > 0]))

我收到OSError: [Errno 22] Invalid argument: filenamehttps://link1

如果我把我的代码改成这个

for index, line in enumerate(urls):
    with open('filename{}.txt'.format(index), 'w', encoding="utf8") as outfile:
        outfile.write('\n'.join([i for i in page.split('\n') if len(i) > 0]))

脚本运行,但出现语义错误;两个输出文件都包含从 link2 中提取的文本。我猜第二个 for 循环就是这样做的。

我已经研究了类似1 答案的 S/O,但我无法弄清楚。

【问题讨论】:

    标签: python for-loop beautifulsoup python-3.8


    【解决方案1】:

    我猜你在某种 *nix 系统上,因为错误与 / 解释了路径的一部分有关。

    因此,您必须做一些事情来正确命名文件或创建要保存输出的路径。

    话虽如此,使用URL 作为文件名并不是一个好主意,因为上面的错误。

    您可以将/ 替换为_,或者只是以不同的方式命名您的文件。

    还有,这个:

    urls = ['https://link1',
            'https://link2']
    

    已经是一个列表,所以不需要这个:

    url_list = list(urls)
    

    而且不需要两个for loops。您可以在从列表中抓取 URLS 时写入文件。

    这是一些虚拟网站的工作代码:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    import requests
    from bs4 import BeautifulSoup
    
    urls = ['https://lipsum.com/', 'https://de.lipsum.com/']
    
    for url in urls:
        response = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'})
        soup = BeautifulSoup(response.content, "html.parser")
        page = soup.find("div", {"id": "Panes"}).find("p").getText()
        with open('filename_{}.txt'.format(url.replace("/", "_")), 'w', encoding="utf8") as outfile:
            outfile.write('\n'.join([i for i in page.split('\n') if len(i) > 0]))
    

    您也可以将您的方法与enumerate() 一起使用:

    import requests
    from bs4 import BeautifulSoup
    
    urls = ['https://lipsum.com/', 'https://de.lipsum.com/']
    
    for index, url in enumerate(urls, start=1):
        response = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'})
        soup = BeautifulSoup(response.content, "html.parser")
        page = soup.find("div", {"id": "Panes"}).find("p").getText()
        with open('filename_{}.txt'.format(index), 'w', encoding="utf8") as outfile:
            outfile.write('\n'.join([i for i in page.split('\n') if len(i) > 0]))
    

    【讨论】:

    • 我收到AttributeError: 'NoneType' object has no attribute 'find'。如果我将“find”更改为find_all,我会得到AttributeError: ResultSet object has no attribute 'find'. You're probably treating a list of elements like a single element. Did you call find_all() when you meant to call find()?。另外,我认为这里对我来说是一个学习的机会;你能解释一下page=这行吗?
    • 你不应该在你的URLs 上使用这个page = soup.find("div", {"id": "Panes"}).find("p").getText()。我用这个只是为了说明这一点。您收到的错误意味着 your URL 没有 divPanesid
    • 哦,我明白了,它现在可以工作了。感谢您的澄清。
    猜你喜欢
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 2012-06-27
    • 2014-07-29
    • 2016-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多