2015-06-01 2 views
2

Я работаю над небольшим скребком для веб-сайтов, чтобы просто почувствовать голанг. В настоящее время он захватывает информацию из вики из таблицы, а затем захватывает информацию специально из ячеек. Я в настоящее время нет кода на меня (не в настоящее время у себя дома), но он выглядит довольно похож на это:golang web scraper, игнорируя конкретные ячейки таблицы

func main() { 
     doc, err := goquery.NewDocument("http://monsterhunter.wikia.com/wiki/MH4:_Item_List") 
     if err != nil { 
       log.Fatal(err) 
     } 

     doc.Find("tbody").Each(func(i int, s *goquery.Selection) { 
       title := s.Find("td").Text() 
       fmt.Printf(title) 
     }) 
} 

Вопрос заключается в том, что на этом сайте первая ячейка представляет собой изображение, поэтому он печатает изображение источник, которого я не хочу. Как я могу игнорировать первую ячейку в каждой строке большой таблицы?

+0

Вы можете найти 'td' без какого-либо дочернего элемента' a'. –

+0

Хорошо, я могу попытаться выяснить, как это сделать. Я просто попробовал нарезать заголовок, чтобы получить 4 первых символа, потому что все они начинаются с «

ответ

3

Давайте проясним некоторые вещи. A Selection представляет собой набор узлов, соответствующих некоторым критериям.

doc.Find() является Selection.Find(), который возвращает новый Selection содержащий элементы, соответствующие критериям. И Selection.Each() итераций по каждому из элементов коллекции и вызывает переданное ему значение функции.

Так что в вашем случае Find("tbody") найдут все tbody элементов, Each() будет перебрать все элементы tbody и вызвать вашу анонимную функцию.

Внутри вашей анонимной функции s является Selection одного tbody элемент. Вы звоните s.Find("td"), который вернет новый Selection, который будет содержать всеtd элементы текущей таблицы. Поэтому, когда вы вызываете Text(), это будет комбинированное текстовое содержимое каждого из td элементов, включая их потомков. Это не то, что вы хотите.

Что вы должны сделать, это позвонить другому Each() на номер Selection, указанный s.Find("td"). И проверьте, прошел ли Selection второй анонимной функции img.

Пример кода:

doc.Find("tbody").Each(func(i int, s *goquery.Selection) { 
    // s here is a tbody element 
    s.Find("td").Each(func(j int, s2 *goquery.Selection) { 
     // s2 here is a td element 
     if s3 := s2.Find("img"); s3 != nil && s3.Length() > 0 { 
      return // This TD has at least one img child, skip it 
     } 
     fmt.Printf(s2.Text()) 
    }) 
}) 

В качестве альтернативы вы можете искать tr элементы и пропустить первый td ребенка каждой строки, проверяя, если индекс передается на 3-й анонимной функции 0 (первый ребенок), что-то вроде этого :

doc.Find("tbody").Each(func(i int, s *goquery.Selection) { 
    // s here is a tbody element 
    s.Find("tr").Each(func(j int, s2 *goquery.Selection) { 
     // s2 here is a tr element 
     s2.Find("td").Each(func(k int, s3 *goquery.Selection) { 
      // s3 here is a td element 
      if k == 0 { 
       return // This is the first TD in the row 
      } 
      fmt.Printf(s3.Text()) 
     }) 
    }) 
}) 
+0

Oh ok I see thank you so much! these are both extremely helpful! –

+0

@icza How can this be modified to be able to handel empty ''? Когда у меня есть '' Я получаю эту ошибку: 'panic: ошибка времени выполнения: индекс за пределами диапазона' – Kaah

+0

@Kaah I не видите свой код, и я не знаю, где эта паника. Лучше всего было бы опубликовать это как новый вопрос. – icza

Смежные вопросы