1
версия

Python: 2.7.10Как получить тот же результат в книге «Web Зачистка с Python: Сбор данных из современного Web» Глава 7 данных Нормализация раздел

Мой код:

# -*- coding: utf-8 -*- 

from urllib2 import urlopen 
from bs4 import BeautifulSoup 
from collections import OrderedDict 
import re 
import string 

def cleanInput(input): 
    input = re.sub('\n+', " ", input) 
    input = re.sub('\[[0-9]*\]', "", input) 
    input = re.sub(' +', " ", input) 
    # input = bytes(input, "UTF-8") 
    input = bytearray(input, "UTF-8") 
    input = input.decode("ascii", "ignore") 

    cleanInput = [] 
    input = input.split(' ') 

    for item in input: 
     item = item.strip(string.punctuation) 
     if len(item) > 1 or (item.lower() == 'a' or item.lower() == 'i'): 
      cleanInput.append(item) 
    return cleanInput 

def ngrams(input, n): 
    input = cleanInput(input) 
    output = [] 

    for i in range(len(input)-n+1): 
     output.append(input[i:i+n]) 
    return output 

url = 'https://en.wikipedia.org/wiki/Python_(programming_language)' 
html = urlopen(url) 
bsObj = BeautifulSoup(html, 'lxml') 
content = bsObj.find("div", {"id": "mw-content-text"}).get_text() 
ngrams = ngrams(content, 2) 
keys = range(len(ngrams)) 
ngramsDic = {} 
for i in range(len(keys)): 
    ngramsDic[keys[i]] = ngrams[i] 
# ngrams = OrderedDict(sorted(ngrams.items(), key=lambda t: t[1], reverse=True)) 
ngrams = OrderedDict(sorted(ngramsDic.items(), key=lambda t: t[1], reverse=True)) 


print ngrams 
print "2-grams count is: " + str(len(ngrams)) 

я недавно обучения, как сделать веб-соскоб, следуя книге Web Scraping with Python: Collecting Data from the Modern Web, в то время как в главе 7 данных Нормализация раздел I сначала написать код, как Сэм е, как показано в книге, и получил сообщение об ошибке из терминала:

Traceback (most recent call last): 
    File "2grams.py", line 40, in <module> 
    ngrams = OrderedDict(sorted(ngrams.items(), key=lambda t: t[1], reverse=True)) 
AttributeError: 'list' object has no attribute 'items' 

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

enter image description here

Вопрос:

  1. Если я хочу получить результат, как показано в книге (where sorted by values and the frequency), я должен написать свои собственные строки в подсчитайте количество каждых 2 грамм, или код в книге уже имел эту функцию (коды в книге были кодом python 3)? book sample code on github
  2. Частота в моем выходе была совершенно иной, чем у автора, например, [u'Software', u'Foundation'] произошло 37 раз, но не 40. Каковы причины, вызывающие эту разницу (могут ли это быть мои ошибки кода)?

Скриншот Книга:

Book Screenshot1Book Screenshot2

ответ

1

Получена ошибка в этой главе тоже, потому что ngrams был список. Я преобразовал его в dict и работал

ngrams1 = OrderedDict(sorted(dict(ngrams1).items(), key=lambda t: t[1], reverse=True)) 
1

У меня такая же проблема, когда я читал эту книгу. ngrams должно быть dict. питона версии 3.4

вот мой код:

from urllib.request import urlopen 
from bs4 import BeautifulSoup 
from collections import OrderedDict 
import re 
import string 

def cleanInput(input): 
    input = re.sub('\n+',' ', input) 
    input = re.sub('\[0-9]*\]', '', input) 
    input = re.sub('\+', ' ', input) 
    input = bytes(input, 'utf-8') 
    input = input.decode('ascii', 'ignore') 
    cleanInput = [] 
    input = input.split(' ') 
    for item in input: 
     item = item.strip(string.punctuation) 
     if len(item) >1 or (item.lower() == 'a' or item.lower() == 'i'): 
      cleanInput.append(item) 
    return cleanInput 

def ngrams(input, n): 
    input = cleanInput(input) 
    output = [] 
    for i in range(len(input)-n+1): 
     output.append(input[i:i+n]) 
    return output 

html = urlopen("http://en.wikipedia.org/wiki/Python_(programming_language)") 
bsObj = BeautifulSoup(html, "lxml") 
content = bsObj.find("div", {"id": "mw-content-text"}).get_text() 
ngrams1 = ngrams(content, 2) 
#ngrams1 is something like this [['This', 'article'], ['article', 'is'], ['is', 'about'], ['about', 'the'], ['the', 'programming'], ['programming', 'language'], 
ngrams = {} 
for i in ngrams1: 
    j = str(i) #the key of ngrams should not be a list 
    ngrams[j] = ngrams.get(j, 0) + 1 
    # ngrams.get(j, 0) means return a value for the given key j. If key j is not available, then returns default value 0. 
    # when key j appear again, ngrams[j] = ngrams[j]+1 

ngrams = OrderedDict(sorted(ngrams.items(), key=lambda t: t[1], reverse=True)) 
print(ngrams) 
print("2-grams count is:"+str(len(ngrams))) 

Это часть моего результата:

OrderedDict([("['Python', 'Software']", 37), ("['Software', 'Foundation']", 37), ("['of', 'the']", 37), ("['of', 'Python']", 35), ("['Foundation', 'Retrieved']", 32), 
0

Более элегантное решение этой проблемы будет использовать collections.defaultdict.

Вот мой код (с помощью Python 2.7+):

import requests 
import re 
import string 
from bs4 import BeautifulSoup 
from collections import OrderedDict, defaultdict 


def clean_input(input): 
    input = re.sub('\n+', " ", input) 
    input = re.sub('\[[0-9]*\]', "", input) 
    input = re.sub(' +', " ", input) 
    input = bytes(input).decode(encoding='utf-8') 
    input = input.encode(encoding='ascii', errors='ignore') 
    clean_input = [] 
    input = input.split(' ') 
    for item in input: 
     item = item.strip(string.punctuation) 
     if len(item) > 1 or (item.lower() == 'a' or item.lower() == 'i'): 
      clean_input.append(item) 
    return clean_input 


def ngrams(input, n): 
    input = clean_input(input) 
    output = [] 
    for i in xrange(len(input)-n+1): 
     output.append(input[i:i+n]) 
    return output 


response = requests.get("http://en.wikipedia.org/wiki/Python_(programming_language") 
bsObj = BeautifulSoup(response.content, "html.parser") 
content = bsObj.find("div", {"id":"mw-content-text"}).get_text() 
ngrams1 = ngrams(content, 2) 
ngrams = defaultdict(int) 
for k in ngrams1: 
    ngrams[str(k)] += 1 
ngrams = OrderedDict(sorted(ngrams.items(), key=(lambda t: t[1]), reverse=True)) 
print ngrams 
print "2-grams count is: %d" % len(ngrams) 

Это часть моего результата:

OrderedDict([("['Python', 'programming']", 5), ("['programming', 'language']", 4), ("['for', 'Python']", 3), ("['the', 'page']", 2), ("['language', 'in']", 2), ("['sister', 'projects']", 1), ("['language', 'article']", 1), ("['page', 'I']", 1), ("['see', 'Why']", 1), 
0

Список не имеет элемент. Я просто изменил список на dict. Вот мой код я изменил

def ngrams(input, n): 
    input = cleanInput(input) 
    output = dict() 
    for i in range(len(input)-n+1): 
     new_ng = " ".join(input[i:i+n]) 
     if new_ng in output: 
      output[new_ng] += 1 
     else: 
      output[new_ng] = 1 
    return output 
0

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

Для этой книги, вы можете найти все примеры кода на:

http://pythonscraping.com/code/ и перенаправит вас на

https://github.com/REMitchell/python-scraping.

Затем вы можете найти свой код в папке chapter7. enter image description here Вы можете увидеть следующий скриншот в вашей книге, и URL-адрес из кода примера, который я отмечен синей коробке: enter image description here

Пример кода в 2-clean2grams.py:

from urllib.request import urlopen 
from bs4 import BeautifulSoup 
import re 
import string 
from collections import OrderedDict 

def cleanInput(input): 
    input = re.sub('\n+', " ", input) 
    input = re.sub('\[[0-9]*\]', "", input) 
    input = re.sub(' +', " ", input) 
    input = bytes(input, "UTF-8") 
    input = input.decode("ascii", "ignore") 
    cleanInput = [] 
    input = input.split(' ') 
    for item in input: 
     item = item.strip(string.punctuation) 
     if len(item) > 1 or (item.lower() == 'a' or item.lower() == 'i'): 
      cleanInput.append(item) 
    return cleanInput 

def getNgrams(input, n): 
    input = cleanInput(input) 
    output = dict() 
    for i in range(len(input)-n+1): 
     newNGram = " ".join(input[i:i+n]) 
     if newNGram in output: 
      output[newNGram] += 1 
     else: 
      output[newNGram] = 1 
    return output 

html = urlopen("http://en.wikipedia.org/wiki/Python_(programming_language)") 
bsObj = BeautifulSoup(html, "html.parser") 
content = bsObj.find("div", {"id":"mw-content-text"}).get_text() 
#ngrams = getNgrams(content, 2) 
#print(ngrams) 
#print("2-grams count is: "+str(len(ngrams))) 

ngrams = getNgrams(content, 2) 
ngrams = OrderedDict(sorted(ngrams.items(), key=lambda t: t[1], reverse=True)) 
print(ngrams) 

В этом примере код вы можете получить результат, как:

[('Python Software', 37), ('Software Foundation', 37), ... 

Если вы хотите, чтобы ваш результат как:

[("['Python', 'Software']", 37), ("['Software', 'Foundation']", 37), ... 

Вам просто нужно сделать небольшое изменение следующим образом:

enter image description here

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