Sử dụng proxy trong Scrapy
Bài đăng này đã không được cập nhật trong 3 năm
Giới thiệu
Scrapy là một framework chuyên được sử dụng để extracting data từ web. Nó cao hơn một tầng so với một số lib python cùng chức năng như Requests, BeautifulSoup, urrlib2...
Scrapy phù hợp cho những project chuyên biệt về crawl. Nó cung cấp CLI tools đầy đủ để phát triển nhanh một project.
Scrapy đơn giản và đầy đủ vì Scrapy cung cấp gần như đủ các function để phục vụ bạn crawl. Scrapy dễ dàng mở rộng ví dụ như kết hợp với Selenium để crawl những website sử dụng javascript. Với tài liệu đầy đủ, trực quan, người mới có thể tiếp xúc với Scrapy rất dễ dàng.
Một trong những vẫn đề khá là đau đầu khi crawl web đó là bị banned IP. Việc bạn request liên tục trong một khoảng thời gian ngắn chẳng khác nào việc DDOS cả. Đó là lý do, quản trị mạng con web mà bạn muốn crawl sẵn sàng banned IP tạm thời hoặc vĩnh viễn.
Kinh nghiệm của mình sau nhiều năm làm crawl có lẽ là tránh việc để họ bị banned IP. Còn nếu bị band rồi thì theo mình biết cách hữu hiệu nhất là sử dụng proxy. Hoặc, contact thẳng với bên website đó xin data cho nhanh . Tóm lại, việc sử dụng proxy để crawl là cần thiết.
Scrapy hỗ trợ rất tốt việc sử dụng proxy. Và cách dử dụng proxy trong Scrapy cũng rất đơn giản.
Cài đặt
Các ứng dụng viết trên nền Python thì thường hoạt động tốt nhất với nền tảng Linux và tệ nhật với Windows. Ở đây, mình chỉ hướng dẫn nhanh cách cài đặt trên nền tảng Linux. Còn windows bạn có thể tham khảo ở đây
Yêu cầu:
- Python: 2 hoặc 3
- Pip hoặc Conda
Ở mức độ cơ bản, thì bạn có thể cài đặt thằng vào Python trên hệ thống. Còn nâng cao hơn, bạn có thể sử dụng virtualenv
hay docker
... Ở đây, mình không đi sau vào cài đặt nên chỉ hướng dẫn ở mức độ cơ bản
Lệnh cài đặt:
- Với Pip:
pip install scrapy
- Với Conda
conda install -c conda-forge scrapy
Với lệnh này, bạn sẽ cài đặt scrapy lastversion. Nếu bạn muốn một version cụ thể ví dụ bạn muốn cài đặt version 0.24.6 - một version huyền thoại
pip install scrapy==0.24.6
Kiểm tra lại:
% python
Python 3.6.1 (default, Nov 9 2017, 10:16:55)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import scrapy
>>>
Done!
Tạo một project
Như đã nói ở trên Scrapy cung cấp CLI để tạo nhanh project.
Ở đây mình tạo một project lấy tên là extest
scrapy startproject extest
Cấu trúc project:
├── extest
│ ├── __init__.py
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── settings.py
│ └── spiders
│ ├── __init__.py
└── scrapy.cfg
Tạo một file tên là ballon.py
trong thư mục spider
from scrapy import Spider, Request
class TestDev(Spider):
name = "whatismyipaddress"
def start_requests(self):
urls = ['https://whatismyipaddress.com/']
for url in urls:
request = Request(url=url, callback=self.parse)
yield request
def parse(self, response):
ip = response.xpath("//div[@id='main_content']/div[@id='section_left']/div[2]/a//text()").extract_first()
print("Your ip {}".format(ip))
return
spider này đơn giản chỉ là mình lấy ra IP hiện tại của mình. chạy thử nào:
% scrapy crawl whatismyipaddress
2017-12-27 10:49:27 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: extest)
2017-12-27 10:49:27 [scrapy.utils.log] INFO: Overridden settings: {'BOT_NAME': 'extest', 'DOWNLOAD_DELAY': 3, 'NEWSPIDER_MODULE': 'extest.spiders', 'ROBOTSTXT_OBEY': True, 'SPIDER_MODULES': ['extest.spiders']}
2017-12-27 10:49:27 [scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.corestats.CoreStats',
'scrapy.extensions.telnet.TelnetConsole',
'scrapy.extensions.memusage.MemoryUsage',
'scrapy.extensions.logstats.LogStats']
2017-12-27 10:49:27 [scrapy.middleware] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware',
'scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware',
'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
'scrapy.downloadermiddlewares.retry.RetryMiddleware',
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
'scrapy.downloadermiddlewares.stats.DownloaderStats']
2017-12-27 10:49:27 [scrapy.middleware] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
'scrapy.spidermiddlewares.referer.RefererMiddleware',
'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
'scrapy.spidermiddlewares.depth.DepthMiddleware']
2017-12-27 10:49:27 [scrapy.middleware] INFO: Enabled item pipelines:
[]
2017-12-27 10:49:27 [scrapy.core.engine] INFO: Spider opened
2017-12-27 10:49:27 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2017-12-27 10:49:27 [scrapy.extensions.telnet] DEBUG: Telnet console listening on 127.0.0.1:6023
2017-12-27 10:49:27 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://whatismyipaddress.com/robots.txt> (referer: None)
2017-12-27 10:49:32 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://whatismyipaddress.com/> (referer: None)
Your ip xxx.97.243.xxx
2017-12-27 10:49:32 [scrapy.core.engine] INFO: Closing spider (finished)
2017-12-27 10:49:32 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 510,
'downloader/request_count': 2,
'downloader/request_method_count/GET': 2,
'downloader/response_bytes': 11213,
'downloader/response_count': 2,
'downloader/response_status_count/200': 2,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2017, 12, 27, 3, 49, 32, 730299),
'log_count/DEBUG': 3,
'log_count/INFO': 7,
'log_count/WARNING': 1,
'memusage/max': 51011584,
'memusage/startup': 51011584,
'response_received_count': 2,
'scheduler/dequeued': 1,
'scheduler/dequeued/memory': 1,
'scheduler/enqueued': 1,
'scheduler/enqueued/memory': 1,
'start_time': datetime.datetime(2017, 12, 27, 3, 49, 27, 531919)}
2017-12-27 10:49:32 [scrapy.core.engine] INFO: Spider closed (finished)
Thêm option --nolog để chỉ hiện thị nội dung mình muốn print
% scrapy crawl whatismyipaddress --nolog
Your ip xxx.97.243.xxx
OK. xxx.97.243.xxx
là IP hiện tại của mình
Sử dụng proxy
Đầu tiên là kiếm proxy. Google search ra rất nhiều bạn. Mà hàng free thì bạn biết đấy, có thể die bất cứ lúc nào. Nếu bạn xác định làm project về crawl thì mua proxy là điều mình nghĩ là cần thiết
Mình kiếm được một proxy là 165.227.186.129:80
Fake nào:
Đầu tiên là cấu hình lại code trong settings.py
: thêm dòng này vào
DOWNLOADER_MIDDLEWARES = {
'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 1,
}
Sau đó sửa lại file balloon.py
from scrapy import Spider, Request
class TestDev(Spider):
name = "whatismyipaddress"
def start_requests(self):
urls = ['https://whatismyipaddress.com/']
for url in urls:
request = Request(url=url, callback=self.parse)
request.meta["proxy"] = "http://165.227.186.129:80"
yield request
def parse(self, response):
ip = response.xpath("//div[@id='main_content']/div[@id='section_left']/div[2]/a//text()").extract_first()
print("Your ip {}".format(ip))
return
Run again:
% scrapy crawl whatismyipaddress --nolog
Your ip 165.227.186.129
Perfect!
Đây là cách đơng giản nhất. Nếu bạn không muốn đặt proxy trong balloon.py
, bạn có thể đặt trong middlewares.py
Add thêm một class vào bên dưới file:
class ProxyMiddleware(object):
def process_request(self, request, spider):
request.meta['proxy'] = "http://165.227.186.129:80"
Settings lại trong settings.py
DOWNLOADER_MIDDLEWARES = {
'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware': 110,
'extest.middlewares.ProxyMiddleware': 100,
}
Cơ bản là vậy. Để mở rộng hơn khi bạn có một list danh sách các proxy, bạn có thể đọc random trong class ProxyMiddleware
để đạt được kết quả tốt nhất.
Trên đây là hướng dẫn sử dụng proxy trong Scrapy cơ bản. Nếu có góp ý, vui lòng comment phía bên dưới.
Cảm ơn bạn đã đọc bài!
All rights reserved