【问题标题】:Web Scraping Data to File with Results Separated by CommasWeb 将数据抓取到文件中,结果用逗号分隔
【发布时间】:2016-12-24 09:08:22
【问题描述】:

上学期我参加了 Python 课程,我们进行了大约一周的网络抓取。我意识到它对我现在正在为我的工作做的一些数据输入非常有帮助,但我很难弄清楚它。我正在尝试在http://servicenet.dewalt.com/Parts/Detail/29730 上获取零件号的所有型号 (您必须单击“您可以在此处查看完整列表”才能查看型号)。 这是型号的屏幕截图 .

到目前为止,这就是我所拥有的,但我确定我已经完成了:

from bs4 import BeautifulSoup
import requests
import uuid
import json
import os.path
from multiprocessing.dummy import Pool as Threadpool

#############
# get data for given url
#############

def getdata(url):
    save_path=r'/Users/crazy4byu/PycharmProjects/ServiceNetWebScraping/Data'
    FitList=[]
    html = requests.get(url).text
    soup = BeautifulSoup(html,'html5lib')

    DW704 = soup.find_all('td',{'class':None})
    for item1 in DW704:
        FitList.append(
                {
                    'Model':item1.find('a').text
                }
        )

    with open(os.path.join(save_path,'data_'+str(uuid.uuid1())+'.json'),'w') as outfile:
    json.dump(FitList,outfile)

#############
# Main
#############

if'__main__' == __name__:
    #makes a list of my urls
    urls=[]
    urls.append(r'http://servicenet.dewalt.com/Parts/Detail/29730')

    pool = Threadpool(25)
    pool.map(getdata, urls)

    pool.close()
    pool.join()

最后,我想要一个基本上是这种格式的文本文件: 110 Type 1、1301 Type 100、1317 Type 100等(每个型号以逗号分隔)。

目前,我收到一条错误消息,提示“AttributeError: 'NoneType' object has no attribute 'text'”,但我确信这不是唯一的问题。我真的很感谢你的帮助!谢谢大家!

【问题讨论】:

  • 你为什么要抓取页面上的每一个 td?

标签: python web-scraping beautifulsoup comma nonetype


【解决方案1】:

它失败是因为在某些单元格中没有链接 - item1.find('a') 是 None ,因此您无法获得它的“文本”属性。

此外,您根本不需要使用 JSON,因为您希望输出文件只是用逗号分隔的型号)。

这是我的代码:

from bs4 import BeautifulSoup
import requests
import uuid
import os.path
from multiprocessing.dummy import Pool as Threadpool

#############
# get data for given url
#############

def getdata(url):
    save_path='./'
    FitList=list()
    html = requests.get(url).text
    soup = BeautifulSoup(html)

    DW704 = soup.find_all('td',{'class':None})
    for item1 in DW704:
        print(item1.find('a'))
        if item1.find('a') is not None:
            if item1.find('a').text.strip() != "":
                FitList.append(item1.find('a').text)

    with open(os.path.join(save_path,'data_'+str(uuid.uuid1())+'.json'),'w') as outfile:
        outfile.write(",".join(FitList))

#############
# Main
#############

if'__main__' == __name__:
    #makes a list of my urls
    urls=[]
    urls.append(r'http://servicenet.dewalt.com/Parts/Detail/29730')

    pool = Threadpool(25)
    pool.map(getdata, urls)

    pool.close()
    pool.join()

【讨论】:

  • 完美!我知道这可能是一个愚蠢的问题,但是您会使用什么解析器来消除空白,所以就像:110 Type 1、1301 Type 100、1317 Type 100 等等?我一直在尝试弄乱它,但还没有弄清楚...
  • 我已经更新了脚本,使其在输出文件中不包含空行。
【解决方案2】:

您想要的文本在 table 的 tbody 行中的第一个 td 内的锚点内,带有 id customerList,不要'不要抓取页面上所有可用的 td,即使里面有一个带有文本的锚点,它也绝不意味着它与您想要的表格或内容有关。:

from bs4 import BeautifulSoup
import io
import requests

soup = BeautifulSoup(requests.get("http://servicenet.dewalt.com/Parts/Detail/29730").content)
# Get all the specific table rows.
rows = soup.select("#customerList tbody tr")

# use io.open to handle the non ascii.
with io.open("data.txt", "w", encoding="utf-8") as f:
    for row in rows:
        # get text from first anchor inside the first td
        f.write(row.select_one("td a").text + u"\n")

data.txt 看起来像:

110 Type 1
1301 Type 100
1317 Type 100
1317 Type 101
1317-44 Type 100
1338 Type 100
1339 Type 100
1348 Type 100
1348K Type 100
2214 Type 100
2214-90 Type 101
22810 Type 1
etc............

如果你真的想要单行逗号分隔,你可以str.join每个元素:

rows = soup.select("#customerList tbody tr")

with io.open("data.txt", "w", encoding="utf-8") as f:
        f.write(u",".join([row.select_one("td a").text for row in rows]))

这会给你:

110 Type 1,1301 Type 100,1317 Type 100,1317 Type 101,1317-44 Type 100,1338 Type 100,1339 Type 100,1348 Type 100,1348K Type 100,2214 Type 100,2214-90 Type 101,22810 Type 1,23802 Type 1,23808-BDK Type 100,24873 Type 1,2610-220 Type 1,2670 Type 100,2670 Type 101,2670G Type 100,2674 Type 100,2674-34 Type 1,2675 Type 100,2675 Type 101,2683 Type 1,2683-220 Type 1,2684 Type 1,2684-34 Type 1,2685 Type 1,2694 Type 1,2695 Type 1,2697 Type 1,2697 Type 2,2698 Type 1,27111 Type 1,27111 Type 2,27126 Type 1,27126 Type 2,27128 Type 1,27128 Type 2,2717 Type 100,2717 Type 101,27182 Type 1,27182 Type 2,27188 Type 1,27513-BDK Type 100,27513-BDK Type 3,27713 Type 1,27997 Type 3,3057 Type 1,3057-44 Type 1,3057-48 Type 1,3060 Type 1,3064 Type 1,3064-44 Type 1,3103 Type 100,3103 Type 101,3104 Type 100,3105 Type 100,3105 Type 101,3105K Type 101,3105K Type 102,3107 Type 100,3107 Type 101,3108 Type 100,3108K Type 100,3110 Type 100,3110K Type 100,3110K Type 101,3110KG Type 100,3660 Type 1,3660 Type 2,3660 Type 3,3680 Type 1,3680 Type 2,3680 Type 3,4252 Type 100,4255 Type 100,4267 Type 1,4292 Type 1,5036 Type 100,5036K Type 100,5321 Type 100,6101 Type 100,6112 Type 100,6112 Type 101,6112-90 Type 100,6124 Type 100,6124 Type 101,6126 Type 100,6127 Type 100,6129 Type 100,6138 Type 100,6138 Type 101,6138 Type 102,6138-34 Type 100,6138-34 Type 102,6513 Type 100,6513 Type 101,6934 Type 100,6940 Type 100,6943 Type 100,6943 Type 101,6943 Type 102,6945 Type 100,6945 Type 101,BD4500 Type 1,DW120K Type 1,DW130 Type 1,DW130 Type 2,DW130 Type 3,DW130-220 Type 2,DW130-220 Type 3,DW140 Type 1,DW140 Type 2,DW142 Type 1,DW142 Type 2,DW290 Type 1,DW290 Type 2,DW290-220 Type 1,DW290-B2 Type 1,DW290-BR Type 1,DW290G Type 1,DW290K Type 2,DW291 Type 1,DW291 Type 2,DW291-B2 Type 1,DW291-B3 Type 1,DW296 Type 1,DW296 Type 2,DW304K Type 1,DW304K Type 2,DW304K-35 Type 1,DW304K-35 Type 2,DW304K-44 Type 1,DW305K Type 1,DW305K Type 2,DW306K Type 1,DW306K Type 2,DW306K220 Type 2,DW306KG Type 2,DW352-AR Type 2,DW352-AR Type 3,DW352-AR Type 4,DW352-B2 Type 1,DW352-B2 Type 2,DW352-B2 Type 3,DW352-B2 Type 4,DW352-B3 Type 1,DW352-B3 Type 2,DW352-B3 Type 3,DW352-B3 Type 4,DW352-BR Type 2,DW352-BR Type 3,DW352-BR Type 4,DW357 Type 1,DW358 Type 1,DW358-35 Type 1,DW358-44 Type 1,DW359 Type 1,DW359 Type 2,DW359 Type 3,DW359 Type 4,DW359-220 Type 1,DW359-B2 Type 1,DW359-B2 Type 2,DW359-B3 Type 1,DW359-B3 Type 2,DW359K Type 1,DW359K Type 2,DW359K Type 3,DW359K Type 4,DW360 Type 1,DW360 Type 2,DW361 Type 1,DW361 Type 2,DW362 Type 1,DW362 Type 2,DW362 Type 4,DW362K Type 2,DW362K Type 4,DW364 Type 1,DW364 Type 2,DW364 Type 3,DW364 Type 4,DW364 Type 5,DW364 Type 6,DW364K Type 3,DW364K Type 5,DW364K Type 6,DW384 Type 1,DW384 Type 2,DW384 Type 3,DW384 Type 4,DW384 Type 5,DW389-AR Type 1,DW389-B2 Type 1,DW389-B2 Type 2,DW389-B3 Type 1,DW389-B3 Type 2,DW389-BR Type 2,DW704 Type 1,DW704 Type 2,DW704 Type 3,DW704 Type 4,DW704 Type 4A,DW704 Type 5,DW705 Type 1,DW705 Type 2,DW705 Type 3,DW705 Type 4,DW705 Type 4A,DW705 Type 5,DW705 Type 6,DW705 Type 7,DW705 Type 8,DW705-220 Type 1,DW705-220 Type 2,DW705-35 Type 1,DW705-35 Type 2,DW705-35 Type 3,DW705-35 Type 4,DW705-44 Type 1,DW705-44 Type 2,DW705-AR Type 6,DW705-B2 Type 4,DW705-B2 Type 5,DW705-B2 Type 6,DW705-B2 Type 7,DW705-B3 Type 5,DW705-B3 Type 6,DW705-B3 Type 7,DW705-BR Type 7,DW705S Type 5,DW705S Type 6,DW705S Type 7,DW705S Type 8,DW708 Type 1,DW708 Type 3,DW715 Type 1,DW744 Type 1,DW744 Type 2,DW744 Type 3,DW744S Type 2,DW744S Type 3,DW744SB Type 3,DW845 Type 1,DW845 Type 2,DW845 Type 3,DW847 Type 1,DW847 Type 2,DW849 Type 1,DW849 Type 2,DW849 Type 3,DW849-AR Type 1,DW849-AR Type 2,DW849-AR Type 3,DW849-B2 Type 1,DW849-B2 Type 2,DW849-B2 Type 3,DW849-B3 Type 1,DW849-BR Type 1,DW849-BR Type 2,DW849-BR Type 3,DW880 Type 1,DW880 Type 2,DW880 Type 3,DW888 Type 1,DW888 Type 2,DW888 Type 3,DW888-AR Type 3,DW888-B2 Type 3,EP9500 Type 101,EP9500 Type 102,ET1460 Type 1,ET1475 Type 100,ET1475 Type 101,ET1475 Type 102,ET1480 Type 1,ET1490 Type 1,ET1560 Type 1,EW5000 Type 100,G-2610 Type 100,G-2610 Type 101,MT6129 Type 100,MTE33 Type 101,MTE36 Type 101,MTE36 Type 102,Q400 Type 1,Q450 Type 1,Q450K Type 1,Q510 Type 1,Q600 Type 1,QP350K Type 1

【讨论】:

    【解决方案3】:

    在您的get_data 函数中,您不是专注于您所追求的特定数据,而是获取所有 td 没有类的标签。与其进行如此广泛的搜索,不如专门针对您的数据?

    您所关注的部分列表包含在table 标记中。所以,搜索第一个表..

    import requests
    from bs4 import BeautifulSoup
    
    r = requests.get('http://servicenet.dewalt.com/Parts/Detail/29730')
    soup = BeautifulSoup(r.content, 'lxml')
    
    table = soup.find('table')
    

    然后隔离您所追求的标签(tr 标签):

    for tr in table.find_all('tr'):
        print(tr.text)
    

    这给了我一个输出:

                    Model Number
    
    
                    Parts Diagram
    
    
    
    110 Type 1
    
    
    
    
    
    1301 Type 100
    

    其余模型依此类推。由此,您应该能够弄清楚如何解析文本以删除空格等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-17
      相关资源
      最近更新 更多