Создание набора данных с помощью Python, парсинг веб-страниц

Я просмотрел много сообщений, но не нашел решения, которое вполне соответствует тому, что мне нужно. Во-первых, я предваряю, говоря, что я новичок в Python (я использую Python 2).

Я пытаюсь собрать данные с веб-страницы (http://www.tdcj.state.tx.us/death_row/dr_executed_offenders.html). Обратите внимание на красивую HTML-таблицу. Я смог прочитать это в список без особых проблем. Однако также обратите внимание на две колонки со ссылками. Я хотел бы удалить столбец первой ссылки (но я не знаю, как это сделать, поскольку мои данные находятся в списке).

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

Наконец, я хочу распечатать этот список в виде файла с разделителями табуляции, который можно прочитать в R как фрейм данных.

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

from bs4 import BeautifulSoup
import requests
from lxml import html
import csv
import string
import sys

#obtain the main url with bigger data
main_url = "http://www.tdcj.state.tx.us/death_row/dr_executed_offenders.html"

#convert the html to BeautifulSoup
doc = requests.get(main_url)
soup = BeautifulSoup(doc.text, 'lxml')

#find in html the table
tbl = soup.find("table", attrs = {"class":"os"})

#create labels for list rows by table headers
headings = [th.get_text() for th in tbl.find("tr").find_all("th")]

#convert the unicode to string
headers = []
for i in range(0,len(headings)-1):
    headers.append(str(headings[i]))

#access the remaining information
prisoners = []
for row in tbl.find_all("tr")[1:]:
    #attach the appropriate header to the appropriate corresponding data
    #also, converts unicode to string
    info = zip(headers, (str(td.get_text()) for td in row.find_all("td")))    
    #append each of the newly made rows
    prisoners.append(info)

#print each row of the list to a file for R
with open('output.txt', 'a') as output:
    for p in prisoners:
        output.write(str(p)+'\n')
output.close()

Если вы можете помочь мне разобраться с любой из трех частей, с которыми я борюсь, я был бы очень признателен!


person user1723196    schedule 24.04.2016    source источник


Ответы (1)


Не нужно UglyStew. Лаконичный, выразительный парсинг R будет работать просто отлично.

library(xml2)
library(rvest)
library(pbapply)
library(dplyr)

URL <- "http://www.tdcj.state.tx.us/death_row/dr_executed_offenders.html"
pg <- read_html(URL)

nod <- html_nodes(pg, "table.os")[[1]]
tab <- html_table(nod)

last_urls <- html_attr(html_nodes(nod, xpath=".//tr/td[3]/a"), "href")
last_urls <- sprintf("http://www.tdcj.state.tx.us/death_row/%s", last_urls)
last_st <- pbsapply(last_urls, function(x) {
  pg2 <- read_html(x)
  trimws(html_text(html_nodes(pg2, 
                              xpath=".//p[contains(., 'Last Statement')]/following-sibling::p")))
})

death_row <- mutate(tab[, -c(2:3)], last_statement=last_st)
death_row <- setNames(death_row, gsub("\\.", "_", tolower(make.names(colnames(death_row)))))
death_row <- mutate(death_row, date=as.Date(date, "%m/%d/%Y"))

glimpse(death_row)

## Observations: 537
## Variables: 9
## $ execution      (int) 537, 536, 535, 534, 533, 532, 531, 530, 529, 528, 527, 5...
## $ last_name      (chr) "Vasquez", "Ward", "Wesbrook", "Garcia", "Freeman", "Mas...
## $ first_name     (chr) "Pablo", "Adam", "Coy", "Gustavo", "James", "Richard", "...
## $ tdcj_number    (int) 999297, 999525, 999281, 999018, 999539, 999414, 999419, ...
## $ age            (int) 38, 33, 58, 43, 35, 43, 36, 33, 35, 27, 46, 67, 32, 34, ...
## $ date           (date) 2016-04-06, 2016-03-22, 2016-03-09, 2016-02-16, 2016-01...
## $ race           (chr) "Hispanic", "White", "White", "Hispanic", "White", "Whit...
## $ county         (chr) "Hidalgo", "Hunt", "Harris", "Collin", "Wharton", "Harri...
## $ last_statement (list) I just want to tell my family thank you, my mom and  da...

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

person hrbrmstr    schedule 24.04.2016
comment
БЛАГОДАРЮ ВАС. Сначала я попробовал R, потому что это то, с чем я лучше всего знаком, но я не смог найти достойную документацию, которая помогла бы с обобщениями шаблонов, которые вы используете в xpath и sprintf. Итак, мой код закончился там, где у вас есть last_urls. Есть ли у вас какие-либо предложения по местам, которые я могу посмотреть в следующий раз? - person user1723196; 24.04.2016
comment
Я выучил XPath, когда мне нужно было обрабатывать много SGML. XML/XPath — это вещи, которые заставляют людей пить, поэтому я бы не рекомендовал слишком углубляться, если вам это действительно не нужно. Я почти уверен, что мог бы сделать селектор CSS для указанного XPath, но я думаю, что в XPath (к сожалению). Лучший способ стать лучше — это практиковаться. Я не видел подробного справочника, похожего на поваренную книгу, но я оставлю примечание здесь, если найду его. - person hrbrmstr; 24.04.2016