BeautifulSoup find_all返回重复项

时间:2019-07-31 21:53:41

标签: python web-scraping beautifulsoup

我正在尝试获取有关期刊文章的元数据;具体来说,每篇文章属于期刊的哪一部分。我正在使用find_all首先获取带有文章标题的所有标签,然后使用它来解析与文章部分和url信息的标签。

在测试代码时,我将其所有的标题,URL和文章类型打印到终端上,以便可以检查脚本是否获取了正确的数据。 正确的信息是打印(即所有唯一的标题和URL及其文章类型),因此我认为自己走在正确的轨道上。

问题是,当我实际运行下面粘贴的代码时,输​​出中的行数与问题中的文章数相对应,但是每一行都是该文章最后一篇文章的元数据的重复问题,而不是显示每篇文章的唯一数据。例如,如果一个问题有42篇文章,而不是输出中的42行代表该问题中的另一篇文章,那么我只会获得该问题中最后一篇文章的数据,在输出中重复42次。

我在代码中忽略了什么,以确保输出确实包含这些问题中每篇文章的所有唯一数据?

import requests
from bs4 import BeautifulSoup
import csv
import pandas as pd 
import re
from lxml.html import fromstring
import requests
from itertools import cycle
import traceback

def get_proxies():
    url = 'https://free-proxy-list.net/'
    response = requests.get(url)
    parser = fromstring(response.text)
    proxies = set()
    for i in parser.xpath('//tbody/tr')[:10]:
        if i.xpath('.//td[7][contains(text(),"yes")]'):
            proxy = ":".join([i.xpath('.//td[1]/text()')[0], i.xpath('.//td[2]/text()')[0]])
            proxies.add(proxy)
    return proxies


json_data =[]
base_url = 'https://ajph.aphapublications.org'

#Get Health Affairs 2018 issues

ajph2018 = ['https://ajph.aphapublications.org/toc/ajph/108/1',
            'https://ajph.aphapublications.org/toc/ajph/108/2',
            'https://ajph.aphapublications.org/toc/ajph/108/3',
            'https://ajph.aphapublications.org/toc/ajph/108/4',
            'https://ajph.aphapublications.org/toc/ajph/108/5',
            'https://ajph.aphapublications.org/toc/ajph/108/6',
            'https://ajph.aphapublications.org/toc/ajph/108/7',
            'https://ajph.aphapublications.org/toc/ajph/108/8',
            'https://ajph.aphapublications.org/toc/ajph/108/9',
            'https://ajph.aphapublications.org/toc/ajph/108/10',
            'https://ajph.aphapublications.org/toc/ajph/108/11',
            'https://ajph.aphapublications.org/toc/ajph/108/12',
            'https://ajph.aphapublications.org/toc/ajph/108/S1',
            'https://ajph.aphapublications.org/toc/ajph/108/S2',
            'https://ajph.aphapublications.org/toc/ajph/108/S3',
            'https://ajph.aphapublications.org/toc/ajph/108/S4',
            'https://ajph.aphapublications.org/toc/ajph/108/S5',
            'https://ajph.aphapublications.org/toc/ajph/108/S6',
            'https://ajph.aphapublications.org/toc/ajph/108/S7']

for a in ajph2018:
    issue=requests.get(a)
    soup1=BeautifulSoup(issue.text, 'lxml')

    
#Get articles data 
    ajph18_dict={"url":"NaN","articletype":"NaN", "title":"NaN"}
    all_titles = soup1.find_all("span", {"class":"hlFld-Title"})

    for each in all_titles: 
        title = each.text.strip()
        articletype=each.find_previous("h2", {"class":"tocHeading"}).text.strip()
        doi_tag = each.find_previous("a", {"class":"ref nowrap", "href": True})
        doi = doi_tag["href"]
        url = base_url + doi 
               
      
        if url is not None:
            ajph18_dict["url"]=url

        if title is not None:
            ajph18_dict["title"]=title

        if articletype is not None:
            ajph18_dict["articletype"]=articletype.text.strip()
    
        
        json_data.append(ajph18_dict)

df=pd.DataFrame(json_data)
df.to_csv("ajph_type.csv")

print("Saved")

1 个答案:

答案 0 :(得分:1)

每次在for循环中都添加相同的字典(ajph18_dict)时,对该字典所做的任何更改都会反映在列表的每个元素中。最后一个循环会覆盖之前的所有更改,因此您只需从最后一个循环中获取值

您需要将ajph18_dict={"url":"NaN","articletype":"NaN", "title":"NaN"}行放在for循环中,以便在每个循环中创建一个新对象

例如:

d = {}
l = []
for i in range(3):
    d['foo'] = i
    l.append(d)  # This just appends a reference to the same object every time

l现在是一个包含3个元素的列表,这些元素都是对同一词典d的引用。 d现在看起来像这样{'foo': 2}l现在看起来像这样[{'foo': 2}, {'foo': 2}, {'foo': 2}]

l = []
for i in range(3):
    d = {}  # "d" is a new object every loop
    d['foo'] = i
    l.append(d)  # every element in "l" is a different object

[{'foo': 0}, {'foo': 1}, {'foo': 2}]