2015-06-19 2 views
1

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

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

Я пытаюсь использовать команду -o file.csv, но он объединяет каждый URL-адрес страницы в одну ячейку в виде списка и включает в себя дубликаты.

Альтернатива, которую я имею, это просто написать мой собственный код в «синтаксическом разборе» и вручную создать список ссылок и проверить, существуют ли они в списке перед их добавлением, а затем вручную разобрать URL-адрес, чтобы увидеть если домен во внутреннем или внешнем.

Кажется, что Scrapy следует делать с помощью нескольких команд. Есть ли встроенный метод для этого?

Вот код, с которым я работаю. Я прокомментировал часть заголовка bc. Думаю, мне нужно создать другой объект для них. На данный момент я отказался от этой части.

def parse_items(self, response): 
    item = WebconnectItem() 
    sel = Selector(response) 
    items = [] 
# item["title"] = sel.xpath('//title/text()').extract() 
# item["current_url"] = response.url 
    item["link_url"] = sel.xpath('//a/@href').extract() 
    item["link_text"] = sel.xpath('//a/text()').extract() 
    items.append(item) 
    return items 
+0

можно поделиться кодом? Это поможет вам в решении –

+1

, я предлагаю использовать запросы и beautifulsoup 4. Я пробовал Scrapy, и я чувствовал то же самое, если бы вы захотели, я могу найти простое руководство по этому поводу. – taesu

+0

Я добавил код. Я думаю, что вы можете быть прав насчет запросов и BS4. У меня уже работает мой искатель, но его привлекает все, что может сделать Scrapy. С запросами и BS4 я знаю все, что происходит. С помощью Scrapy я чувствую, что вы вводите код в пустоту, и бог знает, что выйдет. – pekasus

ответ

0

реализации с использованием запросов & BS4
примечание это не является оптимальным решением, но оно показывает, как это можно сделать с помощью запросов и BS4.
установка goto для меня.

import requests 
from bs4 import BeautifulSoup 
URL = "http://www.cnn.com/" 

# get request 
r = requests.get(URL) 
# turn into bs instance 
soup = BeautifulSoup(r.text) 
# get all links 
links = soup.findAll('a') 

internal_unique = [] 
external_unique = [] 
internal_links = [] 
external_links = [] 

for link in links: 
    if 'ccn.com' in link['href'] or link['href'].startswith('/'): 
     if link['href'] not in internal_unique: 
      internal_links.append({'link':link['href'],'text':link.get_text()}) 
      internal_unique.append(link['href']) 
    else: 
     if link['href'] not in external_unique: 
      external_links.append({'link':link['href'],'text':link.get_text()}) 
      external_unique.append(link['href']) 
print internal_links 
print external_links 
+0

Это так freaking просто в запросах! Я использую urlparse на всех ссылках, а затем запускаю оператор if в 'netloc'. – pekasus

+1

просит >> любую другую http-библиотеку –

1

Scrapy имеет extensive documentation и the tutorial хорошее введение.

Он построен на вершине Twisted, поэтому вам нужно думать в терминах асинхронных запросов и ответов, что сильно отличается от того, что вы обычно делаете с python-запросами и BS4. python-запросы блокируют ваш поток при выдаче HTTP-запросов. Scrapy этого не делает, он позволяет обрабатывать ответы, в то время как другие запросы могут быть связаны с проводом.

Вы можете использовать BS4 в ответных обратных вызовах (например, в вашем методе parse_items).

Вы правы, что Scrapy выдаст 1 вывод в строке на выходе. Он не будет делать дедубликации URL-адресов, потому что элементы - это всего лишь предметы для Scrapy. В вашем случае они содержат URL-адреса. Scrapy не выполняет дедупликацию предметов на основе того, что они содержат. Вы должны были бы поручить это сделать (с item pipeline, например)

Как для URL-адресов, представленных в виде списка в ваших link_url и link_text полей, это потому, что sel.xpath('//a/@href').extract()returns lists

Scrapy 1,0 (скоро будет выпущен) добавляет метод .extract_first(), который поможет в вашем случае.

+0

Конвейер элемента - это ключ, отсутствующий в учебниках, которые я сделал. То, как вы объясняете это, яснее. Таким образом, в основном конвейеры являются «кодовым» участком лечения. Я пытался свалить все в гусеничном ходу, не понимая, что он должен идти в конвейере. – pekasus

+1

Спасибо за отзыв. Я увижу, чтобы обновить документы и учебник о конвейерах. Обратные вызовы Scrapy предназначены для извлечения элементов со страниц. Трубопроводы - это один из способов работы с элементами, пока они обрабатываются, по одному (так что вы можете хранить кортежи 'set()' of (url, text) 'и игнорировать элемент, если его значения уже находятся в Экспортирование 2 файлов может быть [немного сложнее] (http://doc.scrapy.org/en/1.0/topics/exporters.html), вам может быть лучше сплит выход после факта (вы могли бы иметь внутреннее/внешнее поле в определении вашего элемента, чтобы помочь группировать ссылки. –

+0

Это становится понятнее, как вы объясните. Это тип информации, которую я пытался найти. Я читал документы несколько раз, но эти данные которые удерживают все вместе, отсутствуют. Поле int/ext - хорошая идея. Я также хотел бы выполнить анализ ключевых слов на каждой внутренней странице, взвешивание заголовка, h1 и т. д. Я полагаю, что это тоже будет код конвейера. , Я бы сделал код «if internal», который выполняет анализ ключевых слов. Это имеет смысл. Спасибо за вашу помощь. – pekasus

1

Значит, ваши мысли о scrapy в значительной степени точны. Очень мощная, крутая кривая обучения, но имеет много обещаний, если вы сможете пройти мимо этой части. Есть даже несколько дополнительных услуг на вершине, таких как ScrapingHub, которые могут позаботиться о ротации IP-адресов, сохранении заданий и т. Д.

Разница заключается в том, что scrapy работает с использованием конвейеров элементов, а не традиционной модели. У них отличный код для решения именно того, что у вас есть. Любая обработка результатов должна выполняться в этих конвейерах элементов, а не в самом скребке. Документы являются here, и это пример трубопровод для удаления дубликатов и записи в формат JSON:

class DuplicatesPipeline(object): 

    def __init__(self): 
     self.ids_seen = set() 

    def process_item(self, item, spider): 
     if item['id'] in self.ids_seen: 
      raise DropItem("Duplicate item found: %s" % item) 
     else: 
      self.ids_seen.add(item['id']) 
      return item 

class JsonWriterPipeline(object): 

    def __init__(self): 
     self.file = open('items.jl', 'wb') 

    def process_item(self, item, spider): 
     line = json.dumps(dict(item)) + "\n" 
     self.file.write(line) 
     return item 
+0

Это имеет смысл. Хотя это открывает его собственную банку червей. Сохраняются ли эти элементы в памяти, когда они находятся в конвейере, или хранятся в файле, который необходимо прочитать первым? Он экспортирует один элемент за раз или весь список? – pekasus

+0

@JoshuaMeyer Это действительно сделано, чтобы быть одним предметом за раз, и не все происходит в памяти сразу. Поскольку все происходит асинхронно, методы конвейеров элемента используются как обратные вызовы. Они вводят конвейер через скребок и затем записываются на диск (как в примере jsonwriter). Имеет ли это смысл? –

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