Скрипт веб-поиска возвращает повторяющиеся значения - PullRequest
1 голос
/ 15 мая 2019

Мой веб-скрипт по какой-то причине возвращает повторяющиеся результаты, я пробовал так много альтернатив, но просто не могу заставить его работать вообще. Может кто-нибудь помочь, пожалуйста?

import requests
from bs4 import BeautifulSoup as bs
from bs4.element import Tag
import csv

soup = [ ]
pages = [ ]

csv_file = open('444.csv', 'w')

csv_writer = csv.writer(csv_file)
csv_writer.writerow(['Practice', 'Practice Manager'])

for i in range(35899, 35909):
   url = 'https://www.nhs.uk/Services/GP/Staff/DefaultView.aspx?id=' + str(i)
   pages.append(url)

for item in pages:
   page = requests.get(item)
   soup.append(bs(page.text, 'lxml'))

business = []
for items in soup:
   h1Obj = items.select('[class^=panel]:has([class^="gp notranslate"]:contains(""))')
   for i in h1Obj:
      tagArray = i.findChildren()
   for tag in tagArray:
      if isinstance(tag,Tag) and tag.name in 'h1':
         business.append(tag.text)
      else:
         print('no-business')

names = []
for items in soup:
   h4Obj = items.select('[class^=panel]:not(p):has([class^="staff-title"]:contains("Practice Manager"))')
   for i in h4Obj:
      tagArray = i.findChildren()
      for tag in tagArray:
         if isinstance(tag,Tag) and tag.name in 'h4':
            names.append(tag.text)
         else:
            print('no-name')

print(business, names)
csv_writer.writerow([business, names])
csv_file.close()

В настоящее время он возвращает повторяющиеся значения для всех.

Что нужно сделать, это вернуть одно значение «business» и одно «names» для каждого URL-вызова. Если нет «business» или «name», ему нужно вернуть значение «no-business» или «no-name».

Может кто-нибудь помочь мне?

Ответы [ 3 ]

1 голос
/ 15 мая 2019

Вы можете использовать следующий идентификатор для создания начального списка списков.Вы можете написать каждую строку в CSV, а не добавлять в окончательный список.

import requests
from bs4 import BeautifulSoup as bs

results = []
with requests.Session() as s:

    for i in range(35899, 35909):
        r = s.get('https://www.nhs.uk/Services/GP/Staff/DefaultView.aspx?id=' + str(i))
        soup = bs(r.content, 'lxml')
        row = [item.text for item in soup.select('.staff-title:has(em:contains("Practice Manager")) [id]')]
        if not row: row = ['no practice manager']
        practice = soup.select_one('.gp').text if soup.select_one(':has(#org-title)')  else 'No practice name'
        row.insert(0, practice)
        results.append(row)
print(results)

Не уверен, как вы хотите, чтобы список для нескольких имен

import requests
from bs4 import BeautifulSoup as bs
import csv

with open('output.csv', 'w', newline='') as csvfile:
    w = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)

    with requests.Session() as s:

        for i in range(35899, 35909):
            r = s.get('https://www.nhs.uk/Services/GP/Staff/DefaultView.aspx?id=' + str(i))
            soup = bs(r.content, 'lxml')
            row = [item.text for item in soup.select('.staff-title:has(em:contains("Practice Manager")) [id]')]
            if not row: row = ['no practice manager']
            practice = soup.select_one('.gp').text if soup.select_one(':has(#org-title)')  else 'No practice name'
            row.insert(0, practice)
            w.writerow(row)
1 голос
/ 15 мая 2019

Я не знаю, является ли это лучшим способом сделать это, но я использовал набор вместо списка, чтобы удалить дубликаты, и перед сохранением файла я конвертирую набор в список следующим образом:

import requests
from bs4 import BeautifulSoup as bs
from bs4.element import Tag
import csv

soup = [ ]
pages = [ ]

csv_file = open('444.csv', 'w')

csv_writer = csv.writer(csv_file)
csv_writer.writerow(['Practice', 'Practice Manager'])

for i in range(35899, 35909):
   url = 'https://www.nhs.uk/Services/GP/Staff/DefaultView.aspx?id=' + str(i)
   pages.append(url)

for item in pages:
   page = requests.get(item)
   soup.append(bs(page.text, 'lxml'))

business = set()
for items in soup:
   h1Obj = items.select('[class^=panel]:has([class^="gp notranslate"]:contains(""))')
   for i in h1Obj:
      tagArray = i.findChildren()
   for tag in tagArray:
      if isinstance(tag,Tag) and tag.name in 'h1':
         business.add(tag.text)
      else:
         print('no-business')


names = set()
for items in soup:
   h4Obj = items.select('[class^=panel]:not(p):has([class^="staff-title"]:contains("Practice Manager"))')
   for i in h4Obj:
      tagArray = i.findChildren()
      for tag in tagArray:
         if isinstance(tag,Tag) and tag.name in 'h4':
            names.add(tag.text)
         else:
            print('no-business')

print(business, names)
csv_writer.writerow([list(business), list(names)])
csv_file.close()
0 голосов
/ 15 мая 2019

Похоже, что проблема связана с тем, что на некоторых из этих страниц вообще нет информации, и вы получаете сообщение об ошибке «Скрытый профиль». Я немного изменил ваш код, чтобы покрыть первые 5 страниц. Помимо сохранения в файл, это выглядит так:

[same imports]
pages = [ ]

for i in range(35899, 35904):
   url = 'https://www.nhs.uk/Services/GP/Staff/DefaultView.aspx?id=' + str(i)
   pages.append(url)

soup = [ ]
for item in pages:
   page = requests.get(item)
   soup.append(bs(page.text, 'lxml'))

business = []
for items in soup:
       h1Obj = items.select('[class^=panel]:has([class^="gp notranslate"]:contains(""))')
       for i in h1Obj:
          tagArray = i.findChildren()
       for tag in tagArray:
          if isinstance(tag,Tag) and tag.name in 'h1':
             business.append(tag.text)


names = []
for items in soup:    
  h4Obj = items.select('[class^=panel]:not(p):has([class^="staff-title"]:contains("Practice Manager"))')
  for i in h4Obj:
      tagArray = i.findChildren()
  for tag in tagArray:
     if isinstance(tag,Tag) and tag.name in 'h4':
        names.append(tag.text)


for bus, name in zip(business,names):
    print(bus,'---',name)

Вывод выглядит так:

Bilbrook Medical Centre --- Di Palfrey
Caversham Group Practice --- Di Palfrey
Caversham Group Practice --- Di Palfrey
The Moorcroft Medical Ctr --- Ms Kim Stanyer 
Brotton Surgery --- Mrs Gina Bayliss

Обратите внимание, что дублируются только 2-я и 3-я записи; это (почему-то, не знаю, почему) вызвано «Скрытый профиль» на третьей странице. Поэтому, если вы измените основные блоки кода на:

business = []
for items in soup:
   if "ProfileHiddenError.aspx" in (str(items)):
    business.append('Profile Hidden')
   else:
       h1Obj = items.select('[class^=panel]:has([class^="gp notranslate"]:contains(""))')
       for i in h1Obj:
          tagArray = i.findChildren()
       for tag in tagArray:
          if isinstance(tag,Tag) and tag.name in 'h1':
             business.append(tag.text)


names = []
for items in soup:
    if "ProfileHiddenError.aspx" in (str(items)):
        names.append('Profile Hidden')        
    elif not "Practice Manager" in str(items):
        names.append('No Practice Manager Specified')     
    else:
      h4Obj = items.select('[class^=panel]:not(p):has([class^="staff-title"]:contains("Practice Manager"))')
      for i in h4Obj:        
          tagArray = i.findChildren()
      for tag in tagArray:
         if isinstance(tag,Tag) and tag.name in 'h4':
            names.append(tag.text)


for bus, name in zip(business,names):
    print(bus,'---',name)

Вывод, на этот раз:

BBilbrook Medical Centre --- Di Palfrey
Caversham Group Practice --- No Practice Manager Specified
Profile Hidden --- Profile Hidden
The Moorcroft Medical Ctr --- Ms Kim Stanyer 
Brotton Surgery --- Mrs Gina Bayliss

Надеюсь, это поможет вам решить проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...