Поиск по блогу

понедельник, 3 ноября 2014 г.

Как я учился, чтобы исправить свои дурацкие ошибки... и совершал новые при отладке в пауке XMLFeed...

В пауке XMLFeed... решил поробовать создать новый столбец из свежеспарсенного словаря списков... Пишем файл pipeline.py в котором фильтруем записи о серверах по времени, типу прокси и стране. Потом записываем результат в виде строк "http://777.77.77.77:8080" в текстовый файл. В процессе работы выскакивают ошибки, я быстро ликивидирую безграмотность перечитывая и конспектируя книгу Лутца. Сроки поджимают, стоит ли продолжать ликбез? Насколько он необходим?

Действительно, для работы "в продакшене" нужен минимальный набор навыков. Очевидно, что его у меня нет (иначе бы не складывал строку со списком). Очевидно, что поиск ошибки при таких знаниях должен быть сопряжен с изрядной тратой времени на закрепление основ.

Например, здесь я перечитал главы о списках, словарях, кортежах - это околло 100 страниц... Причем, пока читаешь, чувствуешь себя очень умным... поскольку все понимаешь.

В то же время, когда надо понять, как работает def process_item в pipelines scrapy, то чувствуешь себя полудурком, поскольку надо уметь сначала распечатать стек, понять назначение классов, посмотреть атрибуты функций... Потом разобраться, как эта "process_item " вызывается из twisted ...

Здесь могло бы помочь знание общих правил (например, как работаю итераторы...), может быть выделить на занятия по 1 часу в день? Но что читать и в какой последовательности?

Еще одно направление - дебаггинг... Но здесь пока все ясно: where, break, next, continue, return, args, ... dir(), help, file

Методические ошибки. В выводе результатов дебаггера распечатывалось не один словарь "Item", а штук 8... Поначалу я этого не заметил, потому что экспериментировал с файлом в 100 строк, ... вывод на умещался на экране... Ошибка очень плохая, потому, что я искал причину ошибки в филах pipeline, а она была в spider C:\Users\kiss\Documents\GitMyScrapy\scrapy_xml_1\XMLFeedSpider\XMLFeedSpider\proxylists.py

In []:
# Сначала я использовал
itertag = 'prx:proxy'
# Потом
itertag = 'item'
# Потом понял, что количесво повторов (вывода) соответствуют количеству тегов 'item'

#instead of online ['http://www.proxylists.net/feed.xml']
    namespaces = [('prx','http://www.proxyrss.com/specification.html'),('content','http://purl.org/rss/1.0/modules/content/')]
    iterator = 'xml' # you can change this; see the docs
    itertag = 'channel' # change it accordingly
    #pdb.set_trace()

Выше правильное решение, но я нашел его "случайно", а большую часть времени потратил на поиск "кошки в пустой черной комнате...". Конечно, было небезполезно разобраться с тем, как вызывается "process_item", но я начал предполагать, что эта функция вызывается для каждой итерации в пауке... оказалось, что все проще - вызов происходит один раз... естественно, после того, как сфомирован объект Item (словарь списков). Т.е., первоначальный код для pipeline работал нормально.

Вот она, первоначальная "детская ошибка"

In []:
<item>
    <title>AL proxies on 2014/10/15 04:21:41</title>
    <link>http://www.proxylists.net/al_0.html</link>
    <description>AL proxies are in the database at the moment.</description>
    <guid>http://www.proxylists.net/al_0.html</guid>
    <prx:proxy>
        <prx:ip>77.242.22.254</prx:ip>
        <prx:port>8741</prx:port>
        <prx:type>Socks4</prx:type>
        <prx:country>Albania</prx:country>
        <prx:check_timestamp>10/13 03:36:32</prx:check_timestamp>
    </prx:proxy>
</item>

Далее процесс поиска и программирования.

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

Зачем же я оставляю этот компромат? Уповаю на память "на припоминание", может помочь вспомнить не только, "как я это выводил", но и активизировать соответствующие "забытые" синаптические ассоциации.

In [6]:
%load 'C:\\Users\\kiss\\Documents\\GitMyScrapy\\scrapy_xml_1\\XMLFeedSpider\\XMLFeedSpider\\pipelines.py'
In []:
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html

from  datetime import datetime
#import pdb 

class XmlfeedspiderPipeline(object):
    """
    This pipeline forms strings like 
    "http://777.78.79.67:8080" 
    in field item['proxylist'] 
    There are three filters here: timestamp, country, proxytype
    """   
    print "In === XmlfeedspiderPipeline"
    #Select last proxy onlytimestanmp=FROMPREVIOUS_LIST_TIMESTAMP
    timestamp =0
    year='2014/'  # for stringto_time  method
    #Country filter
    country = 'Brazil'
    # Type - 'prxtype' (Anonymous, Distorting, Transparent, Socks4, Socks5)
    proxytype =  'Anonymous'
    
    def process_item(self, item, spider):
         #pdb.set_trace()
#         if self.stringto_time(item['prxcheck_timestamp']) != 0:
#            if item['prxcountry'] == self.country:
#                if item['prxtype'] == self.proxytype:
#                    #make new linestring for proxyfile
         item['proxylist'] = item['prxtype'] + item['prxip'] +':'+ item['port']
         print item['proxylist']
         #else:
            #raise DropItem("Missing price in %s" % item)
         return item

    def stringto_time(self,timestring):
        """
        Convert string like '10/15 05:09:21' 
        to datetime oblect
        year - is added here by hands
        """
        your_string =self.year + timestring 
        return  datetime.strptime(your_string, "%Y/%m/%d %H:%M:%S")
        

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

Далее посмотрим, как нам преобразоват строку в дату для поля check_timestamp

Это совершенно другая задача, она решается довольно просто

In [2]:
 import datetime
In [5]:
year='2014/'
your_string =year +'10/15 05:09:21' 
dt=datetime.datetime.strptime(your_string, "%Y/%m/%d %H:%M:%S")
dt.isoformat()
Out[5]:
'2014-10-15T05:09:21'

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

In [7]:
port=[u'8741', u'1080', u'8080', u'8080']
ip=[u'77.242.22.254', u'41.191.253.146', u'191.103.9.210', u'191.103.9.209']
In [8]:
s=ip.append(port)
s
In [9]:
print s
None

In [10]:
ip.append('xxx')
In [11]:
ip
Out[11]:
[u'77.242.22.254',
 u'41.191.253.146',
 u'191.103.9.210',
 u'191.103.9.209',
 [u'8741', u'1080', u'8080', u'8080'],
 'xxx']
In [19]:
ip[1]
Out[19]:
u'41.191.253.146'
In [22]:
len(ip)
Out[22]:
6
In [23]:
len(ip[4])
Out[23]:
4
In [25]:
for i in ip:
    print i.index()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-25-e65d713217dd> in <module>()
      1 for i in ip:
----> 2     print i.index()

TypeError: index() takes at least 1 argument (0 given)
In [26]:
help(list)
Help on class list in module __builtin__:

class list(object)
 |  list() -> new empty list
 |  list(iterable) -> new list initialized from iterable's items
 |  
 |  Methods defined here:
 |  
 |  __add__(...)
 |      x.__add__(y) <==> x+y
 |  
 |  __contains__(...)
 |      x.__contains__(y) <==> y in x
 |  
 |  __delitem__(...)
 |      x.__delitem__(y) <==> del x[y]
 |  
 |  __delslice__(...)
 |      x.__delslice__(i, j) <==> del x[i:j]
 |      
 |      Use of negative indices is not supported.
 |  
 |  __eq__(...)
 |      x.__eq__(y) <==> x==y
 |  
 |  __ge__(...)
 |      x.__ge__(y) <==> x>=y
 |  
 |  __getattribute__(...)
 |      x.__getattribute__('name') <==> x.name
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __getslice__(...)
 |      x.__getslice__(i, j) <==> x[i:j]
 |      
 |      Use of negative indices is not supported.
 |  
 |  __gt__(...)
 |      x.__gt__(y) <==> x>y
 |  
 |  __iadd__(...)
 |      x.__iadd__(y) <==> x+=y
 |  
 |  __imul__(...)
 |      x.__imul__(y) <==> x*=y
 |  
 |  __init__(...)
 |      x.__init__(...) initializes x; see help(type(x)) for signature
 |  
 |  __iter__(...)
 |      x.__iter__() <==> iter(x)
 |  
 |  __le__(...)
 |      x.__le__(y) <==> x<=y
 |  
 |  __len__(...)
 |      x.__len__() <==> len(x)
 |  
 |  __lt__(...)
 |      x.__lt__(y) <==> x<y
 |  
 |  __mul__(...)
 |      x.__mul__(n) <==> x*n
 |  
 |  __ne__(...)
 |      x.__ne__(y) <==> x!=y
 |  
 |  __repr__(...)
 |      x.__repr__() <==> repr(x)
 |  
 |  __reversed__(...)
 |      L.__reversed__() -- return a reverse iterator over the list
 |  
 |  __rmul__(...)
 |      x.__rmul__(n) <==> n*x
 |  
 |  __setitem__(...)
 |      x.__setitem__(i, y) <==> x[i]=y
 |  
 |  __setslice__(...)
 |      x.__setslice__(i, j, y) <==> x[i:j]=y
 |      
 |      Use  of negative indices is not supported.
 |  
 |  __sizeof__(...)
 |      L.__sizeof__() -- size of L in memory, in bytes
 |  
 |  append(...)
 |      L.append(object) -- append object to end
 |  
 |  count(...)
 |      L.count(value) -> integer -- return number of occurrences of value
 |  
 |  extend(...)
 |      L.extend(iterable) -- extend list by appending elements from the iterable
 |  
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |  
 |  insert(...)
 |      L.insert(index, object) -- insert object before index
 |  
 |  pop(...)
 |      L.pop([index]) -> item -- remove and return item at index (default last).
 |      Raises IndexError if list is empty or index is out of range.
 |  
 |  remove(...)
 |      L.remove(value) -- remove first occurrence of value.
 |      Raises ValueError if the value is not present.
 |  
 |  reverse(...)
 |      L.reverse() -- reverse *IN PLACE*
 |  
 |  sort(...)
 |      L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
 |      cmp(x, y) -> -1, 0, 1
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None
 |  
 |  __new__ = <built-in method __new__ of type object>
 |      T.__new__(S, ...) -> a new object with type S, a subtype of T


In [27]:
ip.extend(port)
In [28]:
ip
Out[28]:
[u'77.242.22.254',
 u'41.191.253.146',
 u'191.103.9.210',
 u'191.103.9.209',
 [u'8741', u'1080', u'8080', u'8080'],
 'xxx',
 u'8741',
 u'1080',
 u'8080',
 u'8080']
In [29]:
col2 = [row[1] for row in ip]
In [31]:
print col2
[u'7', u'1', u'9', u'9', u'1080', 'x', u'7', u'0', u'0', u'0']

In [32]:
col3 = [rw[1] for rw in ip]
col3
Out[32]:
[u'7', u'1', u'9', u'9', u'1080', 'x', u'7', u'0', u'0', u'0']
In [33]:
dir(ip)
Out[33]:
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__delslice__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getslice__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__setslice__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']
In [62]:
len(ip)
Out[62]:
10
In [63]:
il=[i  for i in range(len(ip))   ]
il
Out[63]:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In []:
 
In [34]:
help(ip.__add__)
Help on method-wrapper object:

__add__ = class method-wrapper(object)
 |  Methods defined here:
 |  
 |  __call__(...)
 |      x.__call__(...) <==> x(...)
 |  
 |  __cmp__(...)
 |      x.__cmp__(y) <==> cmp(x,y)
 |  
 |  __getattribute__(...)
 |      x.__getattribute__('name') <==> x.name
 |  
 |  __hash__(...)
 |      x.__hash__() <==> hash(x)
 |  
 |  __repr__(...)
 |      x.__repr__() <==> repr(x)
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __objclass__
 |  
 |  __self__


In [41]:
for x in ip: print x, ip.index(x)
 77.242.22.254 0
41.191.253.146 1
191.103.9.210 2
191.103.9.209 3
[u'8741', u'1080', u'8080', u'8080'] 4
xxx 5
8741 6
1080 7
8080 8
8080 8

In [48]:
ip[ip.index('77.242.22.254')]+':'+ ip[4][0]
Out[48]:
u'77.242.22.254:8741'
In []:
item['proxylist'] =item['prxip']       
         ipdb.set_trace()          
         ip=item['prxip'] #the list of IP
         for ipadr in ip:
             j=ip.index(ipadr)
             item['proxylist'][j] = ipadr +':'+ item['prxport'][ip.index(ipadr)]  
           
In [56]:
ddd={'p':[8741, 1080, 8080, 8080], 'ip':[u'77.242.22.254', u'41.191.253.146', u'191.103.9.210', u'191.103.9.209']}
In [59]:
ddd['pp']=ddd['p']
In [60]:
ddd['pp'][1]=1111
In [61]:
ddd['p'][1]
Out[61]:
1111
In [57]:
d1=ddd['p']
In [58]:
dir(d1)
Out[58]:
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__delslice__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getslice__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__setslice__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']
In [68]:
dir(list)
Out[68]:
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__delslice__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getslice__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__setslice__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

Здесь и далее цитаты из Лутца (начиная со стр. 257)

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

Например, нельзя выполнить операцию конкатенации для списка и строки, если предварительно не преобразовать список в строку (используя, например, функцию str или оператор форматирования %) или строку в список (с помощью встроенной функцией list):

In [50]:
>>> str([1, 2]) + '34' # То же, что и “[1, 2]” + “34”
Out[50]:
'[1, 2]34'
In [51]:
[1, 2] + list('34') # То же, что и [1, 2] + [“3”, “4”]
Out[51]:
[1, 2, '3', '4']

Подробнее об операции обхода элементов списка в цикле for и о встроенной функции range мы поговорим в главе 13, потому что они имеют отношениюк синтаксису инструкций. Говоря коротко, оператор цикла for выбирает элементы последовательности в порядке слева направо и выполняет одну или более инструкций для каждого из них.

Последняя строка в табл. 8.1 представляет генератор списков и вызов встроенной функции map, которые подробно описываются в главе 14 и расширенное обсуждение которых приводится в главе 20. Как говорилось в главе 4, генераторы списков – это способ построить новый список, применяя выражение к каждому элементу последовательности; они являются близкими родственниками инструкции цикла for.

...в версии 3.0 метод keys возвращает итератор, а не список. Вызов функции list принудительно выполняет обход всех значений итератора, что позволяет вывести их все сразу. В версии 2.6 метод keys конструирует и возвращает обычный список, поэтому для отображения результатов вызов функции list в этой версии интерпретатора не требуется. Подробнее об этом рассказывается ниже, в этой главе.

In []:
>>> sorted(open(script1.py))
[import sys\n, print(2 ** 33)\n, print(sys.path)\n, x = 2\n]

>>> list(zip(open(script1.py), open(script1.py)))
[(import sys\n, import sys\n), (print(sys.path)\n, print(sys.path)\n),
(x = 2\n, x = 2\n), (print(2 ** 33)\n, print(2 ** 33)\n)]

>>> list(enumerate(open(script1.py)))
[(0, import sys\n), (1, print(sys.path)\n), (2, x = 2\n),
(3, print(2 ** 33)\n)]

>>> list(filter(bool, open(script1.py)))
[import sys\n, print(sys.path)\n, x = 2\n, print(2 ** 33)\n]

>>> import functools, operator
>>> functools.reduce(operator.add, open(script1.py))
import sys\nprint(sys.path)\nx = 2\nprint(2 ** 33)\n

стр 430 ...\Все они являются инструментами итераций, но каждая из них играет свою, уникальную роль. С функциями zip и enumerate мы встречались в предыдущей главе. С функциями filter и reduce мы познакомимся в главе 19, когда будем рассматривать тему функционального программирования, поэтому пока мы не будем погружаться в их особенности.

С функцией sorted мы встретились в первый раз в главе 4 и использовали ее при работе со словарями в главе 8. sorted – это встроенная функция, использующая протокол итераций, – она похожа на метод sort списков, но возвращает новый отсортированный список и принимает любые итерируемые объекты. Обратите внимание, что в отличие от функции map и других, в версии Python 3.0 функция sorted возвращает фактический список, а не итерируемый объект.

стр. 439

Еще больше о генераторах списков и об итераторах мы узнаем в главе 20, когда будем рассматривать их в контексте функций, и еще раз вернемся к ним в главе 29, когда будем знакомиться с классами. Позднее вы узнаете, что:

•• С помощью инструкции yield пользовательские функции можно превратить в итерируемые функции-генераторы.

•• Генераторы списков можно трансформировать в итерируемые выражения-генераторы, заключив их в круглые скобки.

•• В пользовательские классы можно добавить поддержку итераций с помощью методов перегрузки операторов iter или getitem.

В частности, реализация пользовательских итераторов с помощью классов позволяет обеспечить возможность использования произвольных объектов в любых итерацонных контекстах, с которыми мы познакомились здесь

стр. 440 В число итерационных контекстов языка Python входят: цикл for, генераторы списков, встроенная функция map, оператор in проверки вхождения, а также встроенные функции sorted, sum, any и all.

В эту категорию также входят встроенные функции list и tuple, строковый метод join и операции присваивания последовательностей – все они следуют итерационному протоколу (метод next) для обхода итерируемых объектов.

Генераторы списков и матрицы (p. 564)

In []:
 
In [52]:
>>> M = [[1, 2, 3],
... [4, 5, 6],
... [7, 8, 9]]
>>> N = [[2, 2, 2],
... [3, 3, 3],
... [4, 4, 4]]
In [53]:
[row[1] for row in M]
Out[53]:
[2, 5, 8]
In []:
>>> open(myfile).readlines()
[aaa\n, bbb\n, ccc\n]
#Если требуется удалить символы конца строки, их можно отсечь сразу во всех строках за одно действие с помощью генератора списков или
#функции map (в Python 3.0 функция map возвращает итерируемый объект, поэтому нам пришлось использовать функцию list, чтобы полу-
#чить весь список с результатами в интерактивном сеансе):
>>> [line.rstrip() for line in open(myfile).readlines()]
[aaa, bbb, ccc]
In []:
>>> [line.rstrip() for line in open(myfile)]
[aaa, bbb, ccc]
>>> list(map((lambda line: line.rstrip()), open(myfile)))
[aaa, bbb, ccc]
#В последних двух случаях используются файловые итераторы (по сути это означает, что вам не требуется вызывать метод, который будет чи-
#тать строки из файла). Вызов функции map выглядит немного длиннее, чем генератор списков, но ни в одном из этих двух случаев 
#не требуется явно управлять конструированием списка результатов.
In []:
p. 566
Производительность этих тестов может зависеть от вида решаемой задачи, а также от изменений и оптимизаций в самом интерпретаторе 
языка Python. Например, в последних версиях Python была увеличена скорость выполнения инструкции цикла for. 
Тем не менее генераторы списков обычно показывают более высокую скорость работы, чем циклы for, и даже более высокую, чем функция map 
(хотя функция map может выйти победителем в состязании среди встроенных функций). 
Чтобы проверить скорость работы альтернативных реализаций, можно использовать функции time.clock и time.time в модуле time. 
В версии Python 2.4 появился новый модуль timeit, который рассматривается в разделе «Хронометраж итерационных альтернатив» 
далее в этой главе.

Еще раз об итераторах: генераторы (p. 568)

В частности, существуют две языковые конструкции, откладывающие создание ре- зультатов, когда это возможно:

Функции-генераторы – выглядят как обычные инструкции def, но для возврата результатов по одному значению за раз используют инструкцию yield, которая приостанавливает выполнение функции.

Выражения-генераторы – напоминают генераторы списков, о которых рассказывалось в предыдущем разделе, но они не конструируют список с результатами, а возвращают объект, который будет воспроизводить результаты по требованию.

Чтобы по-настоящему понять функции-генераторы, вы должны знать, что они тесно связаны с понятием протокола итераций в языке Python. Как мы уже знаем, итерируемые объекты определяют метод _next _, который либо воз- вращает следующий элемент в итерации, либо возбуждает особое исключение StopIteration по окончании итераций. Доступ к итератору объекта можно по- лучить с помощью встроенной функции iter.

Как отмечалось в главе 14, в Python 2.6 и в более ранних версиях итерируемые объекты объявляют метод next, а не _nex . То же относится и к объектам генераторов, которые мы обсуждаем. В версии 3.0 метод next был переименован в next__ . Для обе- спечения удобства и совместимости предоставляется встроен- ная функция next: вызов next(I) – это то же самое, что вызов I. next _() в версии 3.0 и I.next() в версии 2.6. Для реализации итераций вручную в более ранних версиях Python программы должны вызывать метод I.next().

Как использовать словарь для "перевода" - замены строки 'Anonymous' на строку 'http://'

In []:
# Type - 'prxtype' (Anonymous, Distorting, Transparent, Socks4, Socks5)
In [64]:
ltype=['Anonymous', 'Distorting', 'Transparent', 'Socks4']
In [65]:
dtype={'Anonymous':'http://', 'Distorting':'http://', 'Transparent':'http://', 'Socks4':'', 'Socks5':''}
In [66]:
ltranslate= dtype[ltype[2]] 
In [67]:
ltranslate
Out[67]:
'http'
In []:
di


Посты чуть ниже также могут вас заинтересовать

Комментариев нет:

Отправить комментарий