Неправильный вывод в файле CSV с использованием выражения xPath - PullRequest
0 голосов
/ 06 марта 2020

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

import pandas as pd
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
import time

option = Options()
option.add_argument("--disable-infobars")
option.add_argument("start-maximized")
option.add_argument("--disable-extensions")
option.add_experimental_option("excludeSwitches", ['enable-automation'])

# Pass the argument 1 to allow and 2 to block
# option.add_experimental_option("prefs", {
#     "profile.default_content_setting_values.notifications": 1
# })
driver = webdriver.Chrome(chrome_options=option, executable_path='C:\\Users\\Awais\\Desktop\\web crawling\\chromedriver.exe')

url = ["https://www.marks4sure.com/210-060-exam.html",
"https://www.marks4sure.com/210-065-exam.html",
"https://www.marks4sure.com/200-355-exam.html",
"https://www.marks4sure.com/9A0-127-exam.html",
"https://www.marks4sure.com/300-470-exam.html",]

driver.implicitly_wait(0.5)

na = "N/A"

# text = 'Note: This exam is available on Demand only. You can Pre-Order this Exam and we will arrange this for you.'
links = []
exam_code = []
exam_name = []
total_q = []

for items in range(0, 5):
    driver.get(url[items])
    # if driver.find_element_by_xpath("//div[contains(@class, 'alert') and contains(@class, 'alert-danger')]") == text:
    #     continue
    items += 1

    try:
        c_url = driver.current_url
        links.append(c_url)
    except:
        pass

    try:
        codes = driver.find_element_by_xpath('''//div[contains(@class, 'col-sm-6') and contains(@class, 'exam-row-data') and position() = 2]''')
        exam_code.append(codes.text)
    except:
        exam_code.append(na)

    try:
        names = driver.find_element_by_xpath('//*[@id="content"]/div/div[1]/div[2]/div[3]/div[2]/a')
        exam_name.append(names.text)
    except:
        exam_name.append(na)

    try:
        question = driver.find_element_by_xpath('//*[@id="content"]/div/div[1]/div[2]/div[4]/div[2]/strong')
        total_q.append(question.text)
    except:
        total_q.append(na)
    continue


all_info = list(zip(links, exam_name, exam_name, total_q))
print(all_info)

df = pd.DataFrame(all_info, columns=["Links", "Exam Code", "Exam Name", "Total Question"])
df.to_csv("data5.csv", index=False)
driver.close()

Ответы [ 3 ]

2 голосов
/ 06 марта 2020

Вы получаете там название экзамена дважды, а не коды экзамена, потому что это то, что вы говорите, чтобы сделать это (небольшая опечатка здесь с наличием exam_name там дважды):

all_info = list(zip(links, exam_name, exam_name, total_q))

изменить на: all_info = list(zip(links, exam_code, exam_name, total_q))

Несколько вещей, которые меня смущают.

1) Зачем использовать Selnium? Нет необходимости в селене, поскольку данные возвращаются в первоначальном запросе в источнике html. Поэтому я бы просто использовал requests, поскольку это ускорило бы обработку.

2) Ссылка и код экзамена уже находятся в URL, который вы перебираете. Я бы просто разделил или использовал регулярное выражение для этой строки, чтобы получить ссылку и код. Тогда вам действительно нужно получить название экзамена и количество вопросов.

С учетом сказанного я немного изменил его, чтобы просто получить название экзамена и количество вопросов:

import requests
from bs4 import BeautifulSoup
import pandas as pd


urls = ["https://www.marks4sure.com/210-060-exam.html",
"https://www.marks4sure.com/210-065-exam.html",
"https://www.marks4sure.com/200-355-exam.html",
"https://www.marks4sure.com/9A0-127-exam.html",
"https://www.marks4sure.com/300-470-exam.html",]

links = []
exam_code = []
exam_name = []
total_q = []

for url in urls:
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')

    links.append(url)
    exam_code.append(url.rsplit('-exam')[0].split('/')[-1])

    exam_row = soup.select('div[class*="exam-row-data"]')
    for exam in exam_row:


        if exam.text == 'Exam Name: ':
            exam_name.append(exam.find_next_sibling("div").text)
            continue

        if 'Questions' in exam.text and 'Total Questions' not in exam.text:
            total_q.append(exam.text.strip())
            continue

all_info = list(zip(links, exam_code, exam_name, total_q))
print(all_info)

df = pd.DataFrame(all_info, columns=["Links", "Exam Code", "Exam Name", "Total Question"])
df.to_csv("data5.csv", index=False)
1 голос
/ 06 марта 2020

Привет, чтобы получить код экзамена. Я думаю, что лучше работать с регулярным выражением и получить его из самого URL. Также приведенный ниже код дает мне коды экзаменов правильно, за исключением 4-й ссылки, которая имеет другую структуру по сравнению с другими.

# -*- coding: utf-8 -*-
"""
Created on Fri Mar  6 14:48:00 2020

@author: prakh
"""

import pandas as pd
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
import time

option = Options()
option.add_argument("--disable-infobars")
option.add_argument("start-maximized")
option.add_argument("--disable-extensions")
option.add_experimental_option("excludeSwitches", ['enable-automation'])

# Pass the argument 1 to allow and 2 to block
# option.add_experimental_option("prefs", {
#     "profile.default_content_setting_values.notifications": 1
# })
driver = webdriver.Chrome(executable_path='C:/Users/prakh/Documents/PythonScripts/chromedriver.exe') 

url = ["https://www.marks4sure.com/210-060-exam.html",
"https://www.marks4sure.com/210-065-exam.html",
"https://www.marks4sure.com/200-355-exam.html",
"https://www.marks4sure.com/9A0-127-exam.html",
"https://www.marks4sure.com/300-470-exam.html",]

driver.implicitly_wait(0.5)

na = "N/A"

# text = 'Note: This exam is available on Demand only. You can Pre-Order this Exam and we will arrange this for you.'
links = []
exam_code = []
exam_name = []
total_q = []

for items in range(0, 5):
    driver.get(url[items])
    # if driver.find_element_by_xpath("//div[contains(@class, 'alert') and contains(@class, 'alert-danger')]") == text:
    #     continue
    items += 1

    try:
        c_url = driver.current_url
        links.append(c_url)
    except:
        pass

    try:
        codes = driver.find_element_by_xpath('//*[@id="content"]/div/div[1]/div[2]/div[2]/div[2]')
        exam_code.append(codes.text)
    except:
        exam_code.append(na)

    try:
        names = driver.find_element_by_xpath('//*[@id="content"]/div/div[1]/div[2]/div[3]/div[2]/a')
        exam_name.append(names.text)
    except:
        exam_name.append(na)

    try:
        question = driver.find_element_by_xpath('//*[@id="content"]/div/div[1]/div[2]/div[4]/div[2]/strong')
        total_q.append(question.text)
    except:
        total_q.append(na)
    continue


all_info = list(zip(links, exam_code, exam_name, total_q))
print(all_info)

df = pd.DataFrame(all_info, columns=["Links", "Exam Code", "Exam Name", "Total Question"])
df.to_csv("data5.csv", index=False)
driver.close()
0 голосов
/ 06 марта 2020

Вам не нужен селен, поскольку исходный код содержит необходимую информацию без использования JavaScript.
Кроме того, большинство страниц перенаправляются на marks4sure.com / 200-301-exam. html, так что вы получите те же результаты. Только marks4sure.com / 300-470-экзамен. html не.

import requests
from bs4 import BeautifulSoup

urls = ["https://www.marks4sure.com/210-060-exam.html",
 "https://www.marks4sure.com/210-065-exam.html",
 "https://www.marks4sure.com/200-355-exam.html",
 "https://www.marks4sure.com/9A0-127-exam.html",
 "https://www.marks4sure.com/300-470-exam.html",]

with open("output.csv", "w") as f:
    f.write("exam_code,exam_name,exam_quest\n")
    for url in urls:
        page = requests.get(url)
        soup = BeautifulSoup(page.text, 'html5lib')
        for n, v in enumerate(soup.find_all(class_ = "col-sm-6 exam-row-data")):
            if n == 1:
                exam_code = v.text.strip()
            if n == 3:
                exam_name = v.text.strip()
            if n == 5:
                exam_quest = v.text.strip()
        f.write(f"{exam_code},{exam_name},{exam_quest}\n")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...